Added typescript to workspace devdeps, removed no unused var rules from

tsconfig, made i18n not use top-level await, upgraded packages/made sure
they were on compatible versions
This commit is contained in:
Benjamin Singleton 2026-04-17 20:18:41 -05:00
parent 20a1b867f5
commit 2c63701152
7 changed files with 591 additions and 389 deletions

View file

@ -18,9 +18,8 @@
"axios": "^1.11.0", "axios": "^1.11.0",
"bulma": "^1.0.4", "bulma": "^1.0.4",
"tailwindcss": "^4.1.6", "tailwindcss": "^4.1.6",
"vue": "^3.5.13",
"vue-i18n": "^11.1.3", "vue-i18n": "^11.1.3",
"vue-router": "^4.5.1" "vue-router": "^5.0.4"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.2", "@eslint/js": "^9.39.2",
@ -34,10 +33,11 @@
"sass": "^1.87.0", "sass": "^1.87.0",
"typescript": "~5.8.3", "typescript": "~5.8.3",
"typescript-eslint": "^8.55.0", "typescript-eslint": "^8.55.0",
"unplugin-vue-router": "^0.12.0", "unplugin-vue-router": "^0.19.2",
"vite": "^6.3.5", "vite": "^6.3.5",
"vue": "^3.5.32",
"vue-eslint-parser": "^10.2.0", "vue-eslint-parser": "^10.2.0",
"vue-tsc": "^2.2.8" "vue-tsc": "^3.2.6"
}, },
"packageManager": "pnpm@10.11.0" "packageManager": "pnpm@10.11.0"
} }

View file

@ -13,6 +13,7 @@ import vpVlFtlSrc from "@/assets/locale/vp_VL.ftl";
import wpVlFtlSrc from "@/assets/locale/wp_VL.ftl"; import wpVlFtlSrc from "@/assets/locale/wp_VL.ftl";
import type { FluentBundle } from "@fluent/bundle"; import type { FluentBundle } from "@fluent/bundle";
import { compileLocale } from "@/vi18n-lib/compile"; import { compileLocale } from "@/vi18n-lib/compile";
import type { ComputedRef } from "vue";
export const LOCALE_IDS = ["en-US", "vp-VL", "wp-VL"] as const; export const LOCALE_IDS = ["en-US", "vp-VL", "wp-VL"] as const;
@ -143,42 +144,71 @@ function deepReadonly<T>(value: T): DeepReadonly<T> {
return value as DeepReadonly<T>; return value as DeepReadonly<T>;
} }
const DEFAULT_LOCALE_BUNDLE = unwrap(await loadLocale("en-US", enUsFtlSrc)); interface I18n {
const DEFAULT_LOCALE = unwrap( useLocale: (opt?: UseLocaleOptions) => ComputedRef<DeepReadonly<Locale>>;
setupLocale(DEFAULT_LOCALE_ID, DEFAULT_LOCALE_BUNDLE, undefined), }
);
const doItAllForLocale = async ( async function initI18n(): Promise<I18n> {
const defaultLocaleBundle = unwrap(await loadLocale("en-US", enUsFtlSrc));
const defaultLocale = unwrap(
setupLocale(DEFAULT_LOCALE_ID, defaultLocaleBundle, undefined),
);
const doItAllForLocale = async (
localeId: LocaleId, localeId: LocaleId,
localeFtlSrc: string, localeFtlSrc: string,
): Promise<DeepReadonly<Locale>> => ): Promise<DeepReadonly<Locale>> =>
deepReadonly( deepReadonly(
unwrap( unwrap(
setupLocale( setupLocale(
localeId, localeId,
unwrap(await loadLocale(localeId, localeFtlSrc)), unwrap(await loadLocale(localeId, localeFtlSrc)),
{ bundle: DEFAULT_LOCALE_BUNDLE, locale: DEFAULT_LOCALE }, { bundle: defaultLocaleBundle, locale: defaultLocale },
), ),
), ),
); );
const [vpVl, wpVl] = await Promise.all([ const [vpVl, wpVl] = await Promise.all([
doItAllForLocale("vp-VL", vpVlFtlSrc), doItAllForLocale("vp-VL", vpVlFtlSrc),
doItAllForLocale("wp-VL", wpVlFtlSrc), doItAllForLocale("wp-VL", wpVlFtlSrc),
]); ]);
const localeIdToLocale = { const localeIdToLocale = {
"en-US": deepReadonly(DEFAULT_LOCALE), "en-US": deepReadonly(defaultLocale),
"vp-VL": vpVl, "vp-VL": vpVl,
"wp-VL": wpVl, "wp-VL": wpVl,
} as const satisfies Record<LocaleId, DeepReadonly<Locale>>; } as const satisfies Record<LocaleId, DeepReadonly<Locale>>;
const useLocale = (opt: UseLocaleOptions = {}) =>
computed<DeepReadonly<Locale>>(() => {
const localLocaleId = opt.locale ?? localeId.value;
return localeIdToLocale[localLocaleId];
});
return { useLocale };
}
export interface UseLocaleOptions { export interface UseLocaleOptions {
locale?: LocaleId; locale?: LocaleId;
} }
export const useLocale = (opt: UseLocaleOptions = {}) => const initI18nPromise = initI18n();
computed<DeepReadonly<Locale>>(() => { let i18n: I18n | null = null;
const localLocaleId = opt.locale ?? localeId.value;
return localeIdToLocale[localLocaleId]; initI18nPromise.then((x) => {
}); i18n = x;
});
export const onI18nInit = (f: () => void) => {
initI18nPromise.then(f);
};
export const useLocale = (
opt: UseLocaleOptions = {},
): ComputedRef<DeepReadonly<Locale>> => {
if (i18n === null) {
throw new Error("Cannot use i18n before initialized!");
}
return i18n.useLocale(opt);
};

View file

@ -1,5 +1,8 @@
import { createApp } from "vue"; import { createApp } from "vue";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import { onI18nInit } from "./i18n";
createApp(App).use(router).mount("#app"); onI18nInit(() => {
createApp(App).use(router).mount("#app");
});

View file

@ -1,10 +1,15 @@
/* eslint-disable */ /* eslint-disable */
/* prettier-ignore */ /* prettier-ignore */
// @ts-nocheck // @ts-nocheck
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️ // noinspection ES6UnusedImports
// Generated by unplugin-vue-router. !! DO NOT MODIFY THIS FILE !!
// It's recommended to commit this file. // It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry. // Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
declare module 'vue-router/auto-resolver' {
export type ParamParserCustom = never
}
declare module 'vue-router/auto-routes' { declare module 'vue-router/auto-routes' {
import type { import type {
RouteRecordInfo, RouteRecordInfo,
@ -18,9 +23,81 @@ declare module 'vue-router/auto-routes' {
* Route name map generated by unplugin-vue-router * Route name map generated by unplugin-vue-router
*/ */
export interface RouteNamedMap { export interface RouteNamedMap {
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>, '/': RouteRecordInfo<
'/discord/rules': RouteRecordInfo<'/discord/rules', '/discord/rules', Record<never, never>, Record<never, never>>, '/',
'/kotoba': RouteRecordInfo<'/kotoba', '/kotoba', Record<never, never>, Record<never, never>>, '/',
'/resources': RouteRecordInfo<'/resources', '/resources', Record<never, never>, Record<never, never>>, Record<never, never>,
Record<never, never>,
| never
>,
'/discord/rules': RouteRecordInfo<
'/discord/rules',
'/discord/rules',
Record<never, never>,
Record<never, never>,
| never
>,
'/kotoba': RouteRecordInfo<
'/kotoba',
'/kotoba',
Record<never, never>,
Record<never, never>,
| never
>,
'/resources': RouteRecordInfo<
'/resources',
'/resources',
Record<never, never>,
Record<never, never>,
| never
>,
} }
/**
* Route file to route info map by unplugin-vue-router.
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
*
* Each key is a file path relative to the project root with 2 properties:
* - routes: union of route names of the possible routes when in this page (passed to useRoute<...>())
* - views: names of nested views (can be passed to <RouterView name="...">)
*
* @internal
*/
export interface _RouteFileInfoMap {
'pages/index.vue': {
routes:
| '/'
views:
| never
}
'pages/discord/rules.vue': {
routes:
| '/discord/rules'
views:
| never
}
'pages/kotoba.vue': {
routes:
| '/kotoba'
views:
| never
}
'pages/resources.vue': {
routes:
| '/resources'
views:
| never
}
}
/**
* Get a union of possible route names in a certain route component file.
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
*
* @internal
*/
export type _RouteNamesForFilePath<FilePath extends string> =
_RouteFileInfoMap extends Record<FilePath, infer Info>
? Info['routes']
: keyof RouteNamedMap
} }

View file

@ -4,8 +4,8 @@
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
/* Linting */ /* Linting */
"strict": true, "strict": true,
"noUnusedLocals": true, // "noUnusedLocals": true,
"noUnusedParameters": true, // "noUnusedParameters": true,
"erasableSyntaxOnly": true, "erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true, "noUncheckedSideEffectImports": true,
@ -13,24 +13,11 @@
"module": "esnext", "module": "esnext",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"target": "esnext", "target": "esnext",
"lib": [ "lib": ["ESNext", "DOM"],
"ESNext",
"DOM",
],
"rootDir": "src", "rootDir": "src",
"paths": { "paths": { "@/*": ["./src/*"] },
"@/*": [
"./src/*"
]
}, },
}, "vueCompilerOptions": { "strictTemplates": true },
"vueCompilerOptions": { "include": ["src"],
"strictTemplates": true, "exclude": ["./eslint.config.js"],
},
"include": [
"src",
],
"exclude": [
"./eslint.config.js"
]
} }

View file

@ -1,6 +1,7 @@
{ {
"devDependencies": { "devDependencies": {
"turbo": "^2.5.4" "turbo": "^2.5.4",
"typescript": "~5.8.3"
}, },
"packageManager": "pnpm@10.11.0", "packageManager": "pnpm@10.11.0",
"scripts": { "scripts": {

732
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff