feat: some type prefixes

This commit is contained in:
TrèsAbhi committed 2025-10-13 23:15:32 -05:00
1 parent dc60cffdff
commit 0d8cb5c1ae
31 files changed
+225 -222

No files matched your search

+22 -19
View File
@@ -1,28 +1,31 @@
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { COMMANDS_RAW, CommandRegistry } from '../events/interactionCreate'; import {
COMMANDS_RAW,
type CommandRegistry,
} from "../events/interactionCreate";
const subcommands = [ const subcommands = [
'embeds', "embeds",
'introduction', "introduction",
'invite', "invite",
'timezones', "timezones",
'credits', "credits",
] as const; ] as const;
type Subcommand = (typeof subcommands)[number]; type Subcommand = (typeof subcommands)[number];
const DOCS: Record<Subcommand, string> = { const DOCS: Record<Subcommand, string> = {
embeds: 'guide/embeds', embeds: "guide/embeds",
introduction: 'guide/introduction', introduction: "guide/introduction",
invite: 'guide/invite', invite: "guide/invite",
timezones: 'guide/timezones', timezones: "guide/timezones",
credits: 'about/credits', credits: "about/credits",
}; };
export const aboutCommand = new Promise<CommandRegistry>(async (resolve) => { export const aboutCommand = new Promise<CommandRegistry>(async (resolve) => {
resolve({ resolve({
command: createLocalizedCommand('about', [ command: createLocalizedCommand("about", [
{ subcommand: 'commands' }, { subcommand: "commands" },
...subcommands.map((subcommand) => ({ subcommand })), ...subcommands.map((subcommand) => ({ subcommand })),
]), ]),
@@ -30,7 +33,7 @@ export const aboutCommand = new Promise<CommandRegistry>(async (resolve) => {
const subcommand = interaction.options.getSubcommand(); const subcommand = interaction.options.getSubcommand();
const { strings } = translator(interaction.locale); const { strings } = translator(interaction.locale);
if (subcommand === 'commands') { if (subcommand === "commands") {
return `${strings.bot.commands.about.subcommands.commands.body}${( return `${strings.bot.commands.about.subcommands.commands.body}${(
await Promise.all(COMMANDS_RAW) await Promise.all(COMMANDS_RAW)
) )
@@ -40,7 +43,7 @@ export const aboutCommand = new Promise<CommandRegistry>(async (resolve) => {
(b.command.name_localizations?.[interaction.locale] ?? (b.command.name_localizations?.[interaction.locale] ??
b.command.name) b.command.name)
? -1 ? -1
: 1, : 1
) )
.map( .map(
(registry) => (registry) =>
@@ -51,9 +54,9 @@ export const aboutCommand = new Promise<CommandRegistry>(async (resolve) => {
registry.command.description_localizations?.[ registry.command.description_localizations?.[
interaction.locale interaction.locale
] ?? registry.command.description ] ?? registry.command.description
}`, }`
) )
.join('\n')}`; .join("\n")}`;
} }
const url = `https://raw.githubusercontent.com/tresabhi/blitzkit/main/docs/${DOCS[subcommand as Subcommand]}.md`; const url = `https://raw.githubusercontent.com/tresabhi/blitzkit/main/docs/${DOCS[subcommand as Subcommand]}.md`;
@@ -13,7 +13,7 @@ import { resolvePeriodFromButton } from '../../core/discord/resolvePeriodFromBut
import { resolvePeriodFromCommand } from '../../core/discord/resolvePeriodFromCommand'; import { resolvePeriodFromCommand } from '../../core/discord/resolvePeriodFromCommand';
import { resolvePlayerFromButton } from '../../core/discord/resolvePlayerFromButton'; import { resolvePlayerFromButton } from '../../core/discord/resolvePlayerFromButton';
import { resolvePlayerFromCommand } from '../../core/discord/resolvePlayerFromCommand'; import { resolvePlayerFromCommand } from '../../core/discord/resolvePlayerFromCommand';
import { CommandRegistry } from '../../events/interactionCreate'; import type { CommandRegistry } from '../../events/interactionCreate';
import { renderBreakdown } from './render'; import { renderBreakdown } from './render';
export const breakdownCommand = new Promise<CommandRegistry>( export const breakdownCommand = new Promise<CommandRegistry>(
@@ -1,5 +1,5 @@
import { import {
BlitzStats, type BlitzStats,
calculateWN8, calculateWN8,
getAccountInfo, getAccountInfo,
getClanAccountInfo, getClanAccountInfo,
@@ -17,11 +17,11 @@ import { TitleBar } from "../../components/TitleBar";
import { filtersToDescription } from "../../core/blitzkit/filtersToDescription"; import { filtersToDescription } from "../../core/blitzkit/filtersToDescription";
import { tankDefinitions } from "../../core/blitzkit/nonBlockingPromises"; import { tankDefinitions } from "../../core/blitzkit/nonBlockingPromises";
import { UserError } from "../../core/blitzkit/userError"; import { UserError } from "../../core/blitzkit/userError";
import { filterStats, StatFilters } from "../../core/blitzstars/filterStats"; import { filterStats, type StatFilters } from "../../core/blitzstars/filterStats";
import { getStatsInPeriod } from "../../core/blitzstars/getStatsInPeriod"; import { getStatsInPeriod } from "../../core/blitzstars/getStatsInPeriod";
import { blitzStarsTankAverages } from "../../core/blitzstars/tankAverages"; import { blitzStarsTankAverages } from "../../core/blitzstars/tankAverages";
import { ResolvedPeriod } from "../../core/discord/resolvePeriodFromCommand"; import type { ResolvedPeriod } from "../../core/discord/resolvePeriodFromCommand";
import { ResolvedPlayer } from "../../core/discord/resolvePlayerFromCommand"; import type { ResolvedPlayer } from "../../core/discord/resolvePlayerFromCommand";
import { translator } from "../../core/localization/translator"; import { translator } from "../../core/localization/translator";
const ROWS_PER_PAGE = 8; const ROWS_PER_PAGE = 8;
+9 -9
View File
@@ -1,14 +1,14 @@
import packageJSON from '../../../../package.json'; import packageJSON from "../../../../package.json";
import { client } from '../core/discord/client'; import { client } from "../core/discord/client";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { translator } from '../core/localization/translator'; import { translator } from "../core/localization/translator";
import { CommandRegistry } from '../events/interactionCreate'; import type { CommandRegistry } from "../events/interactionCreate";
const executionStart = new Date().getTime(); const executionStart = new Date().getTime();
export const debugCommand = new Promise<CommandRegistry>((resolve) => { export const debugCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
command: createLocalizedCommand('debug'), command: createLocalizedCommand("debug"),
async handler(interaction) { async handler(interaction) {
const { strings } = translator(interaction.locale); const { strings } = translator(interaction.locale);
@@ -23,15 +23,15 @@ export const debugCommand = new Promise<CommandRegistry>((resolve) => {
[ [
strings.bot.commands.debug.body.uptime, strings.bot.commands.debug.body.uptime,
`${Math.floor((uptime / 1000 / 60 / 60) % 24)}h ${Math.floor( `${Math.floor((uptime / 1000 / 60 / 60) % 24)}h ${Math.floor(
(uptime / 1000 / 60) % 60, (uptime / 1000 / 60) % 60
)}m ${Math.floor((uptime / 1000) % 60)}s ${Math.floor( )}m ${Math.floor((uptime / 1000) % 60)}s ${Math.floor(
uptime % 1000, uptime % 1000
)}ms`, )}ms`,
], ],
]; ];
return `${strings.bot.commands.debug.body.title}${list return `${strings.bot.commands.debug.body.title}${list
.map(([key, value]) => `- ${key}: ${value}`) .map(([key, value]) => `- ${key}: ${value}`)
.join('\n')}`; .join("\n")}`;
}, },
}); });
}); });
+1 -1
View File
@@ -11,7 +11,7 @@ import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { localizationObject } from "../core/discord/localizationObject"; import { localizationObject } from "../core/discord/localizationObject";
import { resolveClanFromCommand } from "../core/discord/resolveClanFromCommand"; import { resolveClanFromCommand } from "../core/discord/resolveClanFromCommand";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import type { CommandRegistry } from "../events/interactionCreate";
const DEFAULT_THRESHOLD = 7; const DEFAULT_THRESHOLD = 7;
+1 -1
View File
@@ -9,7 +9,7 @@ import { createLocalizedCommand } from '../core/discord/createLocalizedCommand';
import { embedInfo } from '../core/discord/embedInfo'; import { embedInfo } from '../core/discord/embedInfo';
import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand';
import { translator } from '../core/localization/translator'; import { translator } from '../core/localization/translator';
import { CommandRegistry } from '../events/interactionCreate'; import type { CommandRegistry } from '../events/interactionCreate';
import { theme } from '../stitches.config'; import { theme } from '../stitches.config';
export const verifyCommand = new Promise<CommandRegistry>((resolve) => { export const verifyCommand = new Promise<CommandRegistry>((resolve) => {
+1 -1
View File
@@ -1,7 +1,7 @@
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { createLocalizedCommand } from "../core/discord/createLocalizedCommand"; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import type { CommandRegistry } from "../events/interactionCreate";
export const pingCommand = new Promise<CommandRegistry>((resolve) => { export const pingCommand = new Promise<CommandRegistry>((resolve) => {
resolve({ resolve({
+1 -1
View File
@@ -22,7 +22,7 @@ import { addUsernameChoices } from "../core/discord/addUsernameChoices";
import { createLocalizedCommand } from "../core/discord/createLocalizedCommand"; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand"; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import type { CommandRegistry } from "../events/interactionCreate";
import { theme } from "../stitches.config"; import { theme } from "../stitches.config";
const LEAGUE_ACCENT = [ const LEAGUE_ACCENT = [
@@ -10,13 +10,13 @@ import {
imgur, imgur,
isOnGoingRatingSeason, isOnGoingRatingSeason,
LEAGUES, LEAGUES,
RatingInfo, type RatingInfo,
RatingLeaderboard, RatingLeaderboard,
Region, type Region,
} from "@blitzkit/core"; } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { import {
APIApplicationCommandOptionChoice, type APIApplicationCommandOptionChoice,
Locale, Locale,
SlashCommandSubcommandBuilder, SlashCommandSubcommandBuilder,
} from "discord.js"; } from "discord.js";
@@ -33,7 +33,7 @@ import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { localizationObject } from "../core/discord/localizationObject"; import { localizationObject } from "../core/discord/localizationObject";
import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand"; import { resolvePlayerFromCommand } from "../core/discord/resolvePlayerFromCommand";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import type { CommandRegistry } from "../events/interactionCreate";
interface SimplifiedPlayer { interface SimplifiedPlayer {
id: number; id: number;
+2 -2
View File
@@ -1,4 +1,4 @@
import { ClanList, fetchBlitz, Region } from "@blitzkit/core"; import { type ClanList, fetchBlitz, type Region } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
import { Locale } from "discord.js"; import { Locale } from "discord.js";
import markdownEscape from "markdown-escape"; import markdownEscape from "markdown-escape";
@@ -8,7 +8,7 @@ import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { embedInfo } from "../core/discord/embedInfo"; import { embedInfo } from "../core/discord/embedInfo";
import { localizationObject } from "../core/discord/localizationObject"; import { localizationObject } from "../core/discord/localizationObject";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import type { CommandRegistry } from "../events/interactionCreate";
const DEFAULT_LIMIT = 25; const DEFAULT_LIMIT = 25;
+3 -3
View File
@@ -1,7 +1,7 @@
import { import {
AccountList, type AccountList,
fetchBlitz, fetchBlitz,
Region, type Region,
usernamePattern, usernamePattern,
} from "@blitzkit/core"; } from "@blitzkit/core";
import { literals } from "@blitzkit/i18n"; import { literals } from "@blitzkit/i18n";
@@ -13,7 +13,7 @@ import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { embedInfo } from "../core/discord/embedInfo"; import { embedInfo } from "../core/discord/embedInfo";
import { localizationObject } from "../core/discord/localizationObject"; import { localizationObject } from "../core/discord/localizationObject";
import { translator } from "../core/localization/translator"; import { translator } from "../core/localization/translator";
import { CommandRegistry } from "../events/interactionCreate"; import type { CommandRegistry } from "../events/interactionCreate";
const DEFAULT_LIMIT = 25; const DEFAULT_LIMIT = 25;
+32 -32
View File
@@ -1,50 +1,50 @@
import { emblemURL, getAccountInfo, getClanAccountInfo } from '@blitzkit/core'; import { emblemURL, getAccountInfo, getClanAccountInfo } from "@blitzkit/core";
import { Locale } from 'discord.js'; import { Locale } from "discord.js";
import { AllStatsOverview } from '../components/AllStatsOverview'; import { AllStatsOverview } from "../components/AllStatsOverview";
import { CommandWrapper } from '../components/CommandWrapper'; import { CommandWrapper } from "../components/CommandWrapper";
import { NoData } from '../components/NoData'; import { NoData } from "../components/NoData";
import { TitleBar } from '../components/TitleBar'; import { TitleBar } from "../components/TitleBar";
import { filtersToDescription } from '../core/blitzkit/filtersToDescription'; import { filtersToDescription } from "../core/blitzkit/filtersToDescription";
import { filterStats, StatFilters } from '../core/blitzstars/filterStats'; import { filterStats, type StatFilters } from "../core/blitzstars/filterStats";
import { getBlitzStarsLinkButton } from '../core/blitzstars/getBlitzStarsLinkButton'; import { getBlitzStarsLinkButton } from "../core/blitzstars/getBlitzStarsLinkButton";
import { getStatsInPeriod } from '../core/blitzstars/getStatsInPeriod'; import { getStatsInPeriod } from "../core/blitzstars/getStatsInPeriod";
import { addPeriodicFilterOptions } from '../core/discord/addPeriodicFilterOptions'; import { addPeriodicFilterOptions } from "../core/discord/addPeriodicFilterOptions";
import { addUsernameChoices } from '../core/discord/addUsernameChoices'; import { addUsernameChoices } from "../core/discord/addUsernameChoices";
import { autocompleteTanks } from '../core/discord/autocompleteTanks'; import { autocompleteTanks } from "../core/discord/autocompleteTanks";
import { autocompleteUsername } from '../core/discord/autocompleteUsername'; import { autocompleteUsername } from "../core/discord/autocompleteUsername";
import { buttonRefresh } from '../core/discord/buttonRefresh'; import { buttonRefresh } from "../core/discord/buttonRefresh";
import { commandToURL } from '../core/discord/commandToURL'; import { commandToURL } from "../core/discord/commandToURL";
import { createLocalizedCommand } from '../core/discord/createLocalizedCommand'; import { createLocalizedCommand } from "../core/discord/createLocalizedCommand";
import { getCustomPeriodParams } from '../core/discord/getCustomPeriodParams'; import { getCustomPeriodParams } from "../core/discord/getCustomPeriodParams";
import { getFiltersFromButton } from '../core/discord/getFiltersFromButton'; import { getFiltersFromButton } from "../core/discord/getFiltersFromButton";
import { getFiltersFromCommand } from '../core/discord/getFiltersFromCommand'; import { getFiltersFromCommand } from "../core/discord/getFiltersFromCommand";
import { resolvePeriodFromButton } from '../core/discord/resolvePeriodFromButton'; import { resolvePeriodFromButton } from "../core/discord/resolvePeriodFromButton";
import { import {
ResolvedPeriod, type ResolvedPeriod,
resolvePeriodFromCommand, resolvePeriodFromCommand,
} from '../core/discord/resolvePeriodFromCommand'; } from "../core/discord/resolvePeriodFromCommand";
import { resolvePlayerFromButton } from '../core/discord/resolvePlayerFromButton'; import { resolvePlayerFromButton } from "../core/discord/resolvePlayerFromButton";
import { import {
ResolvedPlayer, type ResolvedPlayer,
resolvePlayerFromCommand, resolvePlayerFromCommand,
} from '../core/discord/resolvePlayerFromCommand'; } from "../core/discord/resolvePlayerFromCommand";
import { CommandRegistry } from '../events/interactionCreate'; import type { CommandRegistry } from "../events/interactionCreate";
async function render( async function render(
{ region, id }: ResolvedPlayer, { region, id }: ResolvedPlayer,
{ start, end, name }: ResolvedPeriod, { start, end, name }: ResolvedPeriod,
filters: StatFilters, filters: StatFilters,
locale: Locale, locale: Locale
) { ) {
const { nickname } = await getAccountInfo(region, id); const { nickname } = await getAccountInfo(region, id);
const clan = (await getClanAccountInfo(region, id, ['clan']))?.clan; const clan = (await getClanAccountInfo(region, id, ["clan"]))?.clan;
const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined; const clanImage = clan ? emblemURL(clan.emblem_set_id) : undefined;
const diffedTankStats = await getStatsInPeriod( const diffedTankStats = await getStatsInPeriod(
region, region,
id, id,
start, start,
end, end,
locale, locale
); );
const { stats, supplementary } = await filterStats(diffedTankStats, filters); const { stats, supplementary } = await filterStats(diffedTankStats, filters);
const filterDescriptions = await filtersToDescription(filters, locale); const filterDescriptions = await filtersToDescription(filters, locale);
@@ -72,8 +72,8 @@ async function render(
export const statsCommand = new Promise<CommandRegistry>(async (resolve) => { export const statsCommand = new Promise<CommandRegistry>(async (resolve) => {
resolve({ resolve({
command: await addPeriodicFilterOptions( command: await addPeriodicFilterOptions(
createLocalizedCommand('stats'), createLocalizedCommand("stats"),
(option) => option.addStringOption(addUsernameChoices), (option) => option.addStringOption(addUsernameChoices)
), ),
async handler(interaction) { async handler(interaction) {
+1 -1
View File
@@ -14,7 +14,7 @@ import { resolvePeriodFromButton } from '../core/discord/resolvePeriodFromButton
import { resolvePeriodFromCommand } from '../core/discord/resolvePeriodFromCommand'; import { resolvePeriodFromCommand } from '../core/discord/resolvePeriodFromCommand';
import { resolvePlayerFromButton } from '../core/discord/resolvePlayerFromButton'; import { resolvePlayerFromButton } from '../core/discord/resolvePlayerFromButton';
import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand'; import { resolvePlayerFromCommand } from '../core/discord/resolvePlayerFromCommand';
import { CommandRegistry } from '../events/interactionCreate'; import { type CommandRegistry } from '../events/interactionCreate';
import { renderBreakdown } from './breakdown/render'; import { renderBreakdown } from './breakdown/render';
export const todayCommand = new Promise<CommandRegistry>(async (resolve) => { export const todayCommand = new Promise<CommandRegistry>(async (resolve) => {
@@ -1,8 +1,8 @@
import { ComponentProps } from 'react'; import { type ComponentProps } from "react";
export interface GlowProps extends ComponentProps<'div'> { export interface GlowProps extends ComponentProps<"div"> {
color: string; color: string;
direction?: 'default' | 'reverse'; direction?: "default" | "reverse";
rotation?: number; rotation?: number;
startOpacity?: number; startOpacity?: number;
endOpacity?: number; endOpacity?: number;
@@ -12,7 +12,7 @@ const width = 16;
export function Glow({ export function Glow({
color, color,
direction = 'default', direction = "default",
rotation = 0, rotation = 0,
style, style,
startOpacity = 0, startOpacity = 0,
@@ -21,20 +21,20 @@ export function Glow({
}: GlowProps) { }: GlowProps) {
const color1 = `${color}${Math.round(endOpacity * 255) const color1 = `${color}${Math.round(endOpacity * 255)
.toString(16) .toString(16)
.padStart(2, '0')}`; .padStart(2, "0")}`;
const color2 = `${color}${Math.round(startOpacity * 255) const color2 = `${color}${Math.round(startOpacity * 255)
.toString(16) .toString(16)
.padStart(2, '0')}`; .padStart(2, "0")}`;
const background = `linear-gradient(${ const background = `linear-gradient(${
direction === 'default' ? 0 : 180 direction === "default" ? 0 : 180
}deg, ${color1} 0%, ${color2} 100%)`; }deg, ${color1} 0%, ${color2} 100%)`;
return ( return (
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: direction === 'default' ? 'flex-end' : 'flex-start', alignItems: direction === "default" ? "flex-end" : "flex-start",
justifyContent: 'center', justifyContent: "center",
transform: `rotate(${rotation}deg)`, transform: `rotate(${rotation}deg)`,
...style, ...style,
}} }}
@@ -1,7 +1,7 @@
import { import {
getWN8Percentile, getWN8Percentile,
Percentile, Percentile,
SupplementaryStats, type SupplementaryStats,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import { translator } from '../../core/localization/translator'; import { translator } from '../../core/localization/translator';
@@ -1,5 +1,5 @@
import { ReactNode } from 'react'; import { type ReactNode } from "react";
import { theme } from '../stitches.config'; import { theme } from "../stitches.config";
interface CommandWrapperProps { interface CommandWrapperProps {
children: ReactNode; children: ReactNode;
@@ -10,14 +10,14 @@ export function CommandWrapper({ children, fat }: CommandWrapperProps) {
return ( return (
<div <div
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
padding: `16px ${fat ? 0 : 16}px`, padding: `16px ${fat ? 0 : 16}px`,
gap: 16, gap: 16,
width: '100%', width: "100%",
color: theme.colors.textHighContrast, color: theme.colors.textHighContrast,
backgroundColor: theme.colors.appBackground1, backgroundColor: theme.colors.appBackground1,
position: 'relative', position: "relative",
}} }}
> >
{children} {children}
@@ -1,8 +1,8 @@
import { import {
BlitzStats, type BlitzStats,
getWN8Percentile, getWN8Percentile,
isNumber, isNumber,
SupplementaryStats, type SupplementaryStats,
} from '@blitzkit/core'; } from '@blitzkit/core';
import { Locale } from 'discord.js'; import { Locale } from 'discord.js';
import { translator } from '../../core/localization/translator'; import { translator } from '../../core/localization/translator';
@@ -1,6 +1,6 @@
import { times } from 'lodash-es'; import { times } from 'lodash-es';
import { theme } from '../../../../stitches.config'; import { theme } from '../../../../stitches.config';
import { MarginInputProps } from '../Root'; import { type MarginInputProps } from '../Root';
import { MarginOrientation } from './constants'; import { MarginOrientation } from './constants';
interface MarginProps extends MarginInputProps { interface MarginProps extends MarginInputProps {
@@ -1,7 +1,7 @@
import { ComponentProps } from 'react'; import { type ComponentProps } from "react";
import { theme } from '../../../stitches.config'; import { theme } from "../../../stitches.config";
interface ItemProps extends ComponentProps<'div'> { interface ItemProps extends ComponentProps<"div"> {
position: number; position: number;
deltaPosition?: number; deltaPosition?: number;
score?: number; score?: number;
@@ -25,15 +25,15 @@ export function Item({
<div <div
{...props} {...props}
style={{ style={{
cursor: 'pointer', cursor: "pointer",
display: 'flex', display: "flex",
padding: 8, padding: 8,
backgroundColor: highlight backgroundColor: highlight
? theme.colors.componentInteractive_blue ? theme.colors.componentInteractive_blue
: theme.colors.componentInteractive, : theme.colors.componentInteractive,
borderRadius: 4, borderRadius: 4,
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 8, gap: 8,
}} }}
> >
@@ -50,9 +50,9 @@ export function Item({
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
}} }}
> >
@@ -83,22 +83,22 @@ export function Item({
{deltaPosition !== undefined && deltaPosition !== 0 && ( {deltaPosition !== undefined && deltaPosition !== 0 && (
<div <div
style={{ style={{
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
gap: 4, gap: 4,
}} }}
> >
<img <img
alt={deltaPosition > 0 ? 'Increase' : 'Decrease'} alt={deltaPosition > 0 ? "Increase" : "Decrease"}
style={{ style={{
width: 8, width: 8,
height: 8, height: 8,
}} }}
src={ src={
deltaPosition > 0 deltaPosition > 0
? 'https://i.imgur.com/qbjiXa1.png' ? "https://i.imgur.com/qbjiXa1.png"
: 'https://i.imgur.com/3uyNhun.png' : "https://i.imgur.com/3uyNhun.png"
} }
/> />
<span <span
@@ -119,11 +119,11 @@ export function Item({
<div <div
style={{ style={{
display: 'flex', display: "flex",
gap: 4, gap: 4,
alignItems: 'center', alignItems: "center",
width: 96, width: 96,
justifyContent: 'flex-end', justifyContent: "flex-end",
}} }}
> >
{deltaScore !== 0 && deltaScore !== undefined && ( {deltaScore !== 0 && deltaScore !== undefined && (
@@ -140,15 +140,15 @@ export function Item({
)} )}
{deltaScore !== 0 && deltaScore !== undefined && ( {deltaScore !== 0 && deltaScore !== undefined && (
<img <img
alt={deltaScore > 0 ? 'Increase' : 'Decrease'} alt={deltaScore > 0 ? "Increase" : "Decrease"}
style={{ style={{
width: 8, width: 8,
height: 8, height: 8,
}} }}
src={ src={
deltaScore > 0 deltaScore > 0
? 'https://i.imgur.com/qbjiXa1.png' ? "https://i.imgur.com/qbjiXa1.png"
: 'https://i.imgur.com/3uyNhun.png' : "https://i.imgur.com/3uyNhun.png"
} }
/> />
)} )}
@@ -1,4 +1,4 @@
import { ReactNode } from 'react'; import { type ReactNode } from 'react';
interface ColumnProps { interface ColumnProps {
children: ReactNode; children: ReactNode;
@@ -1,4 +1,4 @@
import { ReactNode } from 'react'; import { type ReactNode } from "react";
interface RootProps { interface RootProps {
children: ReactNode; children: ReactNode;
@@ -8,8 +8,8 @@ export function Root({ children }: RootProps) {
return ( return (
<div <div
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
gap: 16, gap: 16,
}} }}
> >
@@ -1,4 +1,4 @@
import { ReactNode } from 'react'; import { type ReactNode } from "react";
interface RowProps { interface RowProps {
children: ReactNode; children: ReactNode;
@@ -8,7 +8,7 @@ export function Row({ children }: RowProps) {
return ( return (
<div <div
style={{ style={{
display: 'flex', display: "flex",
gap: 8, gap: 8,
}} }}
> >
+7 -7
View File
@@ -1,5 +1,5 @@
import { TierWeightsRecord } from '@blitzkit/core'; import type { TierWeightsRecord } from "@blitzkit/core";
import { theme } from '../stitches.config'; import { theme } from "../stitches.config";
interface TierWeightsProps { interface TierWeightsProps {
weights: TierWeightsRecord; weights: TierWeightsRecord;
@@ -7,7 +7,7 @@ interface TierWeightsProps {
export function TierWeights({ weights }: TierWeightsProps) { export function TierWeights({ weights }: TierWeightsProps) {
return ( return (
<div style={{ display: 'flex', gap: 8 }}> <div style={{ display: "flex", gap: 8 }}>
{Object.entries(weights).map(([tier, weight]) => ( {Object.entries(weights).map(([tier, weight]) => (
<div <div
key={tier} key={tier}
@@ -15,11 +15,11 @@ export function TierWeights({ weights }: TierWeightsProps) {
backgroundColor: theme.colors.appBackground1_light, backgroundColor: theme.colors.appBackground1_light,
flex: weight, flex: weight,
color: theme.colors.textHighContrast_light, color: theme.colors.textHighContrast_light,
display: 'flex', display: "flex",
alignItems: 'center', alignItems: "center",
justifyContent: 'center', justifyContent: "center",
fontSize: 16, fontSize: 16,
overflow: 'hidden', overflow: "hidden",
borderRadius: 8, borderRadius: 8,
minWidth: 16, minWidth: 16,
}} }}
+1 -1
View File
@@ -1,4 +1,4 @@
import { Vector3Tuple } from 'three'; import type { Vector3Tuple } from "three";
export const equipmentPriceMatrix: Record<number, Vector3Tuple> = { export const equipmentPriceMatrix: Record<number, Vector3Tuple> = {
1: [100, 200, 300], 1: [100, 200, 300],
+17 -17
View File
@@ -1,6 +1,6 @@
import { times } from 'lodash-es'; import { times } from "lodash-es";
import { Vector3Tuple, Vector4Tuple } from 'three'; import type { Vector3Tuple, Vector4Tuple } from "three";
import { WindowsReadStream } from './windows'; import { WindowsReadStream } from "./windows";
enum DxgiFormat { enum DxgiFormat {
UNKNOWN = 0, UNKNOWN = 0,
@@ -109,7 +109,7 @@ enum DxgiFormat {
NV12 = 103, NV12 = 103,
P010 = 104, P010 = 104,
P016 = 105, P016 = 105,
'420_OPAQUE' = 106, "420_OPAQUE" = 106,
YUY2 = 107, YUY2 = 107,
Y210 = 108, Y210 = 108,
Y216 = 109, Y216 = 109,
@@ -221,7 +221,7 @@ export class DdsReadStream extends WindowsReadStream {
default: default:
throw new TypeError( throw new TypeError(
`Unsupported DXGI format: ${DxgiFormat[dxgiFormat]} (${dxgiFormat})`, `Unsupported DXGI format: ${DxgiFormat[dxgiFormat]} (${dxgiFormat})`
); );
} }
} }
@@ -277,16 +277,16 @@ export class DdsReadStream extends WindowsReadStream {
resolveDxgiFormat(header: ReturnType<typeof this.header>) { resolveDxgiFormat(header: ReturnType<typeof this.header>) {
switch (header.pf.fourCC) { switch (header.pf.fourCC) {
case 'DXT1': case "DXT1":
return DxgiFormat.BC1_UNORM; return DxgiFormat.BC1_UNORM;
case 'DXT3': case "DXT3":
return DxgiFormat.BC2_UNORM; return DxgiFormat.BC2_UNORM;
case 'DXT5': case "DXT5":
return DxgiFormat.BC3_UNORM; return DxgiFormat.BC3_UNORM;
case 'DX10': case "DX10":
return this.headerDxt10().dxgiFormat; return this.headerDxt10().dxgiFormat;
default: default:
@@ -296,13 +296,13 @@ export class DdsReadStream extends WindowsReadStream {
assetFactor4(width: number, height: number) { assetFactor4(width: number, height: number) {
if (width % 4 !== 0 || height % 4 !== 0) { if (width % 4 !== 0 || height % 4 !== 0) {
throw new RangeError('Width and height must be divisible by 4'); throw new RangeError("Width and height must be divisible by 4");
} }
} }
iterateBlocks( iterateBlocks(
width: number, width: number,
height: number, height: number,
blockIterator: () => (index: number) => Vector4Tuple, blockIterator: () => (index: number) => Vector4Tuple
) { ) {
this.assetFactor4(width, height); this.assetFactor4(width, height);
const data = Buffer.alloc(width * height * 4); const data = Buffer.alloc(width * height * 4);
@@ -356,15 +356,15 @@ export class DdsReadStream extends WindowsReadStream {
const alpha = int0 < int1; const alpha = int0 < int1;
const color2 = alpha const color2 = alpha
? (color0.map( ? (color0.map(
(channel0, index) => (channel0 + color1[index]) / 2, (channel0, index) => (channel0 + color1[index]) / 2
) as Vector4Tuple) ) as Vector4Tuple)
: (color0.map( : (color0.map(
(channel0, index) => (2 * channel0 + color1[index]) / 3, (channel0, index) => (2 * channel0 + color1[index]) / 3
) as Vector4Tuple); ) as Vector4Tuple);
const color3 = alpha const color3 = alpha
? ([0, 0, 0, 0] as Vector4Tuple) ? ([0, 0, 0, 0] as Vector4Tuple)
: (color0.map( : (color0.map(
(channel0, index) => (channel0 + 2 * color1[index]) / 3, (channel0, index) => (channel0 + 2 * color1[index]) / 3
) as Vector4Tuple); ) as Vector4Tuple);
return { return {
@@ -415,17 +415,17 @@ export class DdsReadStream extends WindowsReadStream {
const m = buffer[6] & 0b1111; const m = buffer[6] & 0b1111;
return [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p].map( return [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p].map(
(alpha) => alpha / 15, (alpha) => alpha / 15
); );
} }
bc2ColorInterpolations() { bc2ColorInterpolations() {
const color0 = this.R5G6B5(); const color0 = this.R5G6B5();
const color1 = this.R5G6B5(); const color1 = this.R5G6B5();
const color2 = color0.map( const color2 = color0.map(
(channel0, index) => (2 * channel0 + color1[index]) / 3, (channel0, index) => (2 * channel0 + color1[index]) / 3
) as Vector3Tuple; ) as Vector3Tuple;
const color3 = color0.map( const color3 = color0.map(
(channel0, index) => (channel0 + 2 * color1[index]) / 3, (channel0, index) => (channel0 + 2 * color1[index]) / 3
) as Vector3Tuple; ) as Vector3Tuple;
return { return {
+1 -1
View File
@@ -1,4 +1,4 @@
import { Vector3Tuple, Vector4Tuple } from "three"; import type { Vector3Tuple, Vector4Tuple } from "three";
import { ScpgReadStream } from "./scpg"; import { ScpgReadStream } from "./scpg";
export interface SC2 { export interface SC2 {
@@ -1,7 +1,7 @@
import { import {
Armor, Armor,
AssaultRanges, AssaultRanges,
BlitzTankClass, type BlitzTankClass,
CamouflageDefinitions, CamouflageDefinitions,
Consumable, Consumable,
ConsumableDefinitions, ConsumableDefinitions,
@@ -35,15 +35,15 @@ import locales from "@blitzkit/i18n/locales.json";
import { readdir } from "fs/promises"; import { readdir } from "fs/promises";
import { deburr } from "lodash-es"; import { deburr } from "lodash-es";
import { parse as parsePath } from "path"; import { parse as parsePath } from "path";
import { Vector3Tuple } from "three"; import type { Vector3Tuple } from "three";
import { parse as parseYaml } from "yaml"; import { parse as parseYaml } from "yaml";
import { readStringDVPL } from "../core/blitz/readStringDVPL"; import { readStringDVPL } from "../core/blitz/readStringDVPL";
import { readXMLDVPL } from "../core/blitz/readXMLDVPL"; import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL"; import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { commitAssets } from "../core/github/commitAssets"; import { commitAssets } from "../core/github/commitAssets";
import { DATA } from "./constants"; import { DATA } from "./constants";
import { Avatar } from "./skillIcons"; import type { Avatar } from "./skillIcons";
import { TankParameters } from "./tankIcons"; import type { TankParameters } from "./tankIcons";
const nonAlphanumericRegex = /[^a-z0-9]/g; const nonAlphanumericRegex = /[^a-z0-9]/g;
const multipleDashesRegex = /--+/g; const multipleDashesRegex = /--+/g;
+14 -14
View File
@@ -1,10 +1,10 @@
import { TankClass } from '@blitzkit/core'; import { TankClass } from "@blitzkit/core";
import sharp from 'sharp'; import sharp from "sharp";
import { readDVPLFile } from '../core/blitz/readDVPLFile'; import { readDVPLFile } from "../core/blitz/readDVPLFile";
import { readXMLDVPL } from '../core/blitz/readXMLDVPL'; import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { commitAssets } from '../core/github/commitAssets'; import { commitAssets } from "../core/github/commitAssets";
import { FileChange } from '../core/github/commitMultipleFiles'; import type { FileChange } from "../core/github/commitMultipleFiles";
import { DATA } from './constants'; import { DATA } from "./constants";
interface SkillIcon { interface SkillIcon {
name: string; name: string;
@@ -20,22 +20,22 @@ export interface Avatar {
effectDescription: string; effectDescription: string;
tipDescription: string; tipDescription: string;
icon: SkillIcon | SkillIcon[]; icon: SkillIcon | SkillIcon[];
type: 'continuous' | 'trigger'; type: "continuous" | "trigger";
}; };
}; };
} }
export async function skillIcons() { export async function skillIcons() {
console.log('Building skill icons...'); console.log("Building skill icons...");
const avatar = await readXMLDVPL<{ root: Avatar }>( const avatar = await readXMLDVPL<{ root: Avatar }>(
`${DATA}/XML/item_defs/tankmen/avatar.xml`, `${DATA}/XML/item_defs/tankmen/avatar.xml`
); );
const changes = await Promise.all( const changes = await Promise.all(
Object.values(avatar.root.skills).map(async (skill) => { Object.values(avatar.root.skills).map(async (skill) => {
const icon = Array.isArray(skill.icon) ? skill.icon[0] : skill.icon; const icon = Array.isArray(skill.icon) ? skill.icon[0] : skill.icon;
const name = icon.name.split('/').at(-1)!.replace(/_\d$/, ''); const name = icon.name.split("/").at(-1)!.replace(/_\d$/, "");
const path = `${DATA}${icon.name.replace('~res:', '')}.packed.webp`; const path = `${DATA}${icon.name.replace("~res:", "")}.packed.webp`;
const image = sharp(await readDVPLFile(path)).trim(); const image = sharp(await readDVPLFile(path)).trim();
const content = await image.toBuffer(); const content = await image.toBuffer();
@@ -43,8 +43,8 @@ export async function skillIcons() {
content, content,
path: `icons/skills/${name}.webp`, path: `icons/skills/${name}.webp`,
} satisfies FileChange; } satisfies FileChange;
}), })
); );
commitAssets('skill icons', changes); commitAssets("skill icons", changes);
} }
+23 -23
View File
@@ -1,14 +1,14 @@
import { NATION_IDS } from '@blitzkit/core'; import { NATION_IDS } from "@blitzkit/core";
import { readdir } from 'fs/promises'; import { readdir } from "fs/promises";
import sharp from 'sharp'; import sharp from "sharp";
import { Vector3Tuple } from 'three'; import type { Vector3Tuple } from "three";
import { readDVPLFile } from '../core/blitz/readDVPLFile'; import { readDVPLFile } from "../core/blitz/readDVPLFile";
import { readXMLDVPL } from '../core/blitz/readXMLDVPL'; import { readXMLDVPL } from "../core/blitz/readXMLDVPL";
import { readYAMLDVPL } from '../core/blitz/readYAMLDVPL'; import { readYAMLDVPL } from "../core/blitz/readYAMLDVPL";
import { commitAssets } from '../core/github/commitAssets'; import { commitAssets } from "../core/github/commitAssets";
import { FileChange } from '../core/github/commitMultipleFiles'; import type { FileChange } from "../core/github/commitMultipleFiles";
import { DATA } from './constants'; import { DATA } from "./constants";
import { VehicleDefinitionList } from './definitions'; import type { VehicleDefinitionList } from "./definitions";
export interface TankParameters { export interface TankParameters {
resourcesPath: { resourcesPath: {
@@ -43,35 +43,35 @@ export interface TankParameters {
} }
export async function tankIcons() { export async function tankIcons() {
console.log('Building tank icons...'); console.log("Building tank icons...");
const changes: FileChange[] = []; const changes: FileChange[] = [];
const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then( const nations = await readdir(`${DATA}/XML/item_defs/vehicles`).then(
(nations) => nations.filter((nation) => nation !== 'common'), (nations) => nations.filter((nation) => nation !== "common")
); );
await Promise.all( await Promise.all(
nations.map(async (nation) => { nations.map(async (nation) => {
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>( const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>(
`${DATA}/XML/item_defs/vehicles/${nation}/list.xml`, `${DATA}/XML/item_defs/vehicles/${nation}/list.xml`
); );
await Promise.all( await Promise.all(
Object.entries(tanks.root).map(async ([tankKey, tank]) => { Object.entries(tanks.root).map(async ([tankKey, tank]) => {
if (tankKey.includes('tutorial_bot')) return; if (tankKey.includes("tutorial_bot")) return;
const nationVehicleId = tank.id; const nationVehicleId = tank.id;
const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1; const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1;
const parameters = await readYAMLDVPL<TankParameters>( const parameters = await readYAMLDVPL<TankParameters>(
`${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`, `${DATA}/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`
); );
const smallPath = `${DATA}/${parameters.resourcesPath.smallIconPath const smallPath = `${DATA}/${parameters.resourcesPath.smallIconPath
.replace(/~res:\//, '') .replace(/~res:\//, "")
.replace(/\..+/, '')}.packed.webp`; .replace(/\..+/, "")}.packed.webp`;
const bigPath = `${DATA}/${parameters.resourcesPath.bigIconPath const bigPath = `${DATA}/${parameters.resourcesPath.bigIconPath
.replace(/~res:\//, '') .replace(/~res:\//, "")
.replace(/\..+/, '')}.packed.webp`; .replace(/\..+/, "")}.packed.webp`;
const big = await sharp(await readDVPLFile(bigPath)) const big = await sharp(await readDVPLFile(bigPath))
.trim() .trim()
.toBuffer(); .toBuffer();
@@ -91,10 +91,10 @@ export async function tankIcons() {
path: `icons/tanks/small/${id}.webp`, path: `icons/tanks/small/${id}.webp`,
}); });
} }
}), })
); );
}), })
); );
await commitAssets('tank icons', changes); await commitAssets("tank icons", changes);
} }
@@ -1,8 +1,8 @@
import { asset } from '@blitzkit/core'; import { asset } from "@blitzkit/core";
import ProgressBar from 'progress'; import ProgressBar from "progress";
import { compareUint8Arrays } from './compareUint8Arrays'; import { compareUint8Arrays } from "./compareUint8Arrays";
import { GithubChangeBlob, createBlob } from './createBlob'; import { type GithubChangeBlob, createBlob } from "./createBlob";
import { octokit } from './octokit'; import { octokit } from "./octokit";
export interface FileChange { export interface FileChange {
path: string; path: string;
@@ -15,33 +15,33 @@ enum DiffStatus {
Unchanged, Unchanged,
} }
const heuristicFormats = ['glb', 'webp', 'jpg', 'png']; const heuristicFormats = ["glb", "webp", "jpg", "png"];
export async function commitMultipleFiles( export async function commitMultipleFiles(
repoRaw: string, repoRaw: string,
branch: string, branch: string,
message: string, message: string,
changesRaw: FileChange[], changesRaw: FileChange[]
) { ) {
const changes: FileChange[] = []; const changes: FileChange[] = [];
await Promise.all( await Promise.all(
changesRaw.map(async (change) => { changesRaw.map(async (change) => {
const response = await fetch(asset(change.path), { const response = await fetch(asset(change.path), {
headers: { 'Accept-Encoding': 'identity' }, headers: { "Accept-Encoding": "identity" },
}); });
let diff: { change: number; status: DiffStatus }; let diff: { change: number; status: DiffStatus };
if (response.status === 404) { if (response.status === 404) {
diff = { change: change.content.length, status: DiffStatus.New }; diff = { change: change.content.length, status: DiffStatus.New };
} else if ( } else if (
response.headers.has('Content-Length') && response.headers.has("Content-Length") &&
Number(response.headers.get('Content-Length')) !== change.content.length Number(response.headers.get("Content-Length")) !== change.content.length
) { ) {
diff = { diff = {
change: change:
change.content.length - change.content.length -
Number(response.headers.get('Content-Length')), Number(response.headers.get("Content-Length")),
status: DiffStatus.Changed, status: DiffStatus.Changed,
}; };
} else if (response.status === 200) { } else if (response.status === 200) {
@@ -68,7 +68,7 @@ export async function commitMultipleFiles(
} }
} else { } else {
throw new Error( throw new Error(
`Unexpected status code ${response.status} for ${change.path}`, `Unexpected status code ${response.status} for ${change.path}`
); );
} }
@@ -78,17 +78,17 @@ export async function commitMultipleFiles(
} else { } else {
console.log( console.log(
`${ `${
diff.status === DiffStatus.New ? '🟢' : '🟡' diff.status === DiffStatus.New ? "🟢" : "🟡"
} (${diff.change > 0 ? '+' : ''}${diff.change.toLocaleString()}B) ${change.path}`, } (${diff.change > 0 ? "+" : ""}${diff.change.toLocaleString()}B) ${change.path}`
); );
changes.push(change); changes.push(change);
} }
}), })
); );
if (changes.length === 0) return; if (changes.length === 0) return;
const [owner, repo] = repoRaw.split('/'); const [owner, repo] = repoRaw.split("/");
const latestCommitSha = ( const latestCommitSha = (
await octokit.git.getRef({ await octokit.git.getRef({
owner, owner,
@@ -104,7 +104,7 @@ export async function commitMultipleFiles(
}) })
).data.tree.sha; ).data.tree.sha;
const blobs: GithubChangeBlob[] = []; const blobs: GithubChangeBlob[] = [];
const bar = new ProgressBar('Blobs :bar', changes.length); const bar = new ProgressBar("Blobs :bar", changes.length);
for (const change of changes) { for (const change of changes) {
const createdBlob = await createBlob(owner, repo, change); const createdBlob = await createBlob(owner, repo, change);
+11 -11
View File
@@ -1,12 +1,12 @@
import { throttle } from 'lodash-es'; import { throttle } from "lodash-es";
import { FileChange } from './commitMultipleFiles'; import type { FileChange } from "./commitMultipleFiles";
import { octokit } from './octokit'; import { octokit } from "./octokit";
export interface GithubChangeBlob { export interface GithubChangeBlob {
sha: string; sha: string;
path: string; path: string;
mode: '100644'; mode: "100644";
type: 'blob'; type: "blob";
} }
const TIME_PER_BLOB = 2 ** 4 * 1000; const TIME_PER_BLOB = 2 ** 4 * 1000;
@@ -20,21 +20,21 @@ export const createBlob = throttle(
await octokit.git.createBlob({ await octokit.git.createBlob({
owner, owner,
repo, repo,
content: Buffer.from(change.content).toString('base64'), content: Buffer.from(change.content).toString("base64"),
encoding: 'base64', encoding: "base64",
}) })
).data; ).data;
return { return {
sha, sha,
path: change.path, path: change.path,
mode: '100644', mode: "100644",
type: 'blob', type: "blob",
} satisfies GithubChangeBlob; } satisfies GithubChangeBlob;
} catch (error) { } catch (error) {
console.warn( console.warn(
`Failed blob ${change.path}; retrying in ${TIME_PER_BLOB}ms...`, `Failed blob ${change.path}; retrying in ${TIME_PER_BLOB}ms...`,
error, error
); );
await new Promise((resolve) => setTimeout(resolve, TIME_PER_BLOB)); await new Promise((resolve) => setTimeout(resolve, TIME_PER_BLOB));
@@ -42,5 +42,5 @@ export const createBlob = throttle(
} }
}, },
(5000 / (60 * 60 * 1000)) * 0.9, (5000 / (60 * 60 * 1000)) * 0.9,
{ trailing: true }, { trailing: true }
); );