From 0a5c9f79e57a4625cce4a0fa0ef9ae9eb1f85908 Mon Sep 17 00:00:00 2001 From: Hazelnoot Date: Sun, 5 Oct 2025 23:59:31 -0400 Subject: [PATCH] modernize frontend-embed to target the same ES and TS standards as the rest of the app --- packages/frontend-embed/eslint.config.js | 32 +++++++--- packages/frontend-embed/package.json | 8 ++- .../src/components/EmPagination.vue | 6 +- .../frontend-embed/src/workers/tsconfig.json | 2 +- packages/frontend-embed/tsconfig.json | 61 ++----------------- packages/frontend-embed/tsconfig.scripts.json | 24 ++++++++ packages/frontend-embed/tsconfig.vue.json | 30 +++++++++ packages/frontend-embed/vite.config.ts | 20 ++++-- packages/frontend-embed/vite.json5.ts | 5 +- 9 files changed, 109 insertions(+), 79 deletions(-) create mode 100644 packages/frontend-embed/tsconfig.scripts.json create mode 100644 packages/frontend-embed/tsconfig.vue.json diff --git a/packages/frontend-embed/eslint.config.js b/packages/frontend-embed/eslint.config.js index 8e603ab8e3..054b8b7d75 100644 --- a/packages/frontend-embed/eslint.config.js +++ b/packages/frontend-embed/eslint.config.js @@ -15,7 +15,7 @@ export default [ }, ...pluginVue.configs['flat/recommended'], { - files: ['{src,test,js,@types}/**/*.{ts,vue}'], + files: ['{src,test,js,@types}/**/*.{ts,vue}', 'vue-shims.d.ts'], plugins: { sharkey: { rules: { locale: localeRule } } }, languageOptions: { globals: { @@ -41,7 +41,7 @@ export default [ parserOptions: { extraFileExtensions: ['.vue'], parser: tsParser, - project: ['./tsconfig.json'], + project: ['./tsconfig.vue.json'], sourceType: 'module', tsconfigRootDir: import.meta.dirname, }, @@ -98,14 +98,28 @@ export default [ 'vue/attribute-hyphenation': ['error', 'never'], }, }, + { + files: ['*.js', '*.ts'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.scripts.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + 'import/no-default-export': 'off', + }, + }, { ignores: [ - "**/lib/", - "**/temp/", - "**/built/", - "**/coverage/", - "**/node_modules/", - "*.*", - ] + '**/lib/', + '**/temp/', + '**/built/', + '**/coverage/', + '**/node_modules/', + 'vue-shims.d.ts' + ], }, ]; diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json index 75a1becc77..06e7e05037 100644 --- a/packages/frontend-embed/package.json +++ b/packages/frontend-embed/package.json @@ -5,8 +5,11 @@ "scripts": { "watch": "vite", "build": "vite build", - "typecheck": "vue-tsc --noEmit", - "eslint": "eslint --quiet \"{src,test,js,@types}/**/*.{js,jsx,ts,tsx,vue}\" --cache", + "typecheck-all": "pnpm run --no-bail typecheck:vue && pnpm run --no-bail typecheck:scripts", + "typecheck": "pnpm run typecheck:vue && pnpm run typecheck:scripts", + "typecheck:vue": "vue-tsc -p tsconfig.vue.json --noEmit", + "typecheck:scripts": "tsc -p tsconfig.scripts.json --noEmit", + "eslint": "eslint --quiet --cache -c eslint.config.js .", "lint": "pnpm typecheck && pnpm eslint" }, "dependencies": { @@ -24,6 +27,7 @@ "vue": "3.5.21" }, "devDependencies": { + "@misskey-dev/eslint-plugin": "2.1.0", "@misskey-dev/summaly": "npm:@transfem-org/summaly@5.2.3", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-replace": "6.0.2", diff --git a/packages/frontend-embed/src/components/EmPagination.vue b/packages/frontend-embed/src/components/EmPagination.vue index 94a91305f4..998b4e0a21 100644 --- a/packages/frontend-embed/src/components/EmPagination.vue +++ b/packages/frontend-embed/src/components/EmPagination.vue @@ -195,7 +195,7 @@ async function init(): Promise { fetching.value = true; const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; await misskeyApi(props.pagination.endpoint, { - ...params, + ...params as object, limit: props.pagination.limit ?? 10, allowPartial: true, }).then(res => { @@ -231,7 +231,7 @@ const fetchMore = async (): Promise => { moreFetching.value = true; const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; await misskeyApi(props.pagination.endpoint, { - ...params, + ...params as object, limit: SECOND_FETCH_LIMIT, ...(props.pagination.offsetMode ? { offset: offset.value, @@ -295,7 +295,7 @@ const fetchMoreAhead = async (): Promise => { moreFetching.value = true; const params = props.pagination.params ? isRef(props.pagination.params) ? props.pagination.params.value : props.pagination.params : {}; await misskeyApi(props.pagination.endpoint, { - ...params, + ...params as object, limit: SECOND_FETCH_LIMIT, ...(props.pagination.offsetMode ? { offset: offset.value, diff --git a/packages/frontend-embed/src/workers/tsconfig.json b/packages/frontend-embed/src/workers/tsconfig.json index 39ba45ddbb..19d498d537 100644 --- a/packages/frontend-embed/src/workers/tsconfig.json +++ b/packages/frontend-embed/src/workers/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "lib": ["esnext", "webworker"], + "lib": ["ES2022", "WebWorker", "Webworker.Iterable"], "incremental": true } } diff --git a/packages/frontend-embed/tsconfig.json b/packages/frontend-embed/tsconfig.json index 8db5776c91..77e8ba1be6 100644 --- a/packages/frontend-embed/tsconfig.json +++ b/packages/frontend-embed/tsconfig.json @@ -1,58 +1,9 @@ { - "compilerOptions": { - "allowJs": true, - "noEmitOnError": false, - "noImplicitAny": false, - "noImplicitReturns": true, - "noUnusedParameters": false, - "noUnusedLocals": false, - "noFallthroughCasesInSwitch": true, - "declaration": false, - "sourceMap": false, - "target": "ES2022", - "module": "ES2022", - "moduleResolution": "Bundler", - "removeComments": false, - "noLib": false, - "strict": true, - "strictNullChecks": true, - "experimentalDecorators": true, - "resolveJsonModule": true, - "allowSyntheticDefaultImports": true, - "isolatedModules": true, - "useDefineForClassFields": true, - "verbatimModuleSyntax": true, - "skipLibCheck": true, - "incremental": true, - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"], - "@@/*": ["../frontend-shared/*"] - }, - "typeRoots": [ - "./@types", - "./node_modules/@types", - "./node_modules/@vue-macros", - "./node_modules" - ], - "types": [ - "vite/client" - ], - "lib": [ - "esnext", - "dom", - "dom.iterable" - ], - "jsx": "preserve" - }, - "compileOnSave": false, - "include": [ - "./src/**/*.ts", - "./src/**/*.vue", - "./@types/**/*.ts" - ], - "exclude": [ - "node_modules", - ".storybook/**/*" + "$schema": "https://json.schemastore.org/tsconfig", + "files": [], + // WebStorm only reads one tsconfig per directory, so this tricks it into loading both. + "references": [ + { "path": "./tsconfig.scripts.json" }, + { "path": "./tsconfig.vue.json" } ] } diff --git a/packages/frontend-embed/tsconfig.scripts.json b/packages/frontend-embed/tsconfig.scripts.json new file mode 100644 index 0000000000..5a3683ac4d --- /dev/null +++ b/packages/frontend-embed/tsconfig.scripts.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../shared/tsconfig.node.json", + "compilerOptions": { + "noImplicitAny": false, + "typeRoots": [ + "./@types", + "./node_modules/@vue-macros", + "./node_modules/@types", + "./node_modules" + ], + "types": [ + "vite/client", + ] + }, + "include": [ + "*.js", + "*.ts" + ], + "exclude": [ + "node_modules", + "vue-shims.d.ts" + ] +} diff --git a/packages/frontend-embed/tsconfig.vue.json b/packages/frontend-embed/tsconfig.vue.json new file mode 100644 index 0000000000..6a6c38baff --- /dev/null +++ b/packages/frontend-embed/tsconfig.vue.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../shared/tsconfig.web.json", + "compilerOptions": { + "paths": { + "@/*": ["./src/*"], + "@@/*": ["../frontend-shared/*"] + }, + "typeRoots": [ + "./@types", + "./node_modules/@types", + "./node_modules/@vue-macros", + "./node_modules" + ], + "types": [ + "vite/client" + ], + "jsx": "preserve" + }, + "include": [ + "./src/**/*.ts", + "./src/**/*.vue", + "./@types/**/*.ts", + "./vue-shims.d.ts" + ], + "exclude": [ + "node_modules", + ".storybook/**/*" + ] +} diff --git a/packages/frontend-embed/vite.config.ts b/packages/frontend-embed/vite.config.ts index 1cd47b2754..3fdabc4eaa 100644 --- a/packages/frontend-embed/vite.config.ts +++ b/packages/frontend-embed/vite.config.ts @@ -1,13 +1,14 @@ import path from 'path'; import pluginVue from '@vitejs/plugin-vue'; import { type UserConfig, defineConfig } from 'vite'; +import { pluginReplaceIcons } from 'frontend-shared/util/vite.replaceIcons.js'; import { localesVersion } from '../../locales/version.js'; - import locales from '../../locales/index.js'; -import meta from '../../package.json'; +import meta from '../../package.json' with { type: 'json' }; import packageInfo from './package.json' with { type: 'json' }; +import tsconfigVue from './tsconfig.vue.json' with { type: 'json' }; import pluginJson5 from './vite.json5.js'; -import { pluginReplaceIcons } from '../frontend/vite.replaceIcons.js'; +import type { TsconfigRaw } from 'esbuild'; const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue']; @@ -85,13 +86,13 @@ export function getConfig(): UserConfig { '@/': __dirname + '/src/', '@@/': __dirname + '/../frontend-shared/', '/client-assets/': __dirname + '/assets/', - '/static-assets/': __dirname + '/../backend/assets/' + '/static-assets/': __dirname + '/../backend/assets/', }, }, css: { modules: { - generateScopedName(name, filename, _css): string { + generateScopedName(name, filename): string { const id = (path.relative(__dirname, filename.split('?')[0]) + '-' + name).replace(/[\\\/\.\?&=]/g, '-').replace(/(src-|vue-)/g, ''); const shortId = id.replace(/^(components(-global)?|widgets|ui(-_common_)?)-/, ''); return shortId + '-' + toBase62(hash(id)).substring(0, 4); @@ -99,6 +100,7 @@ export function getConfig(): UserConfig { }, preprocessorOptions: { scss: { + // @ts-expect-error not sure why this happens api: 'modern-compiler', }, }, @@ -115,6 +117,12 @@ export function getConfig(): UserConfig { __VUE_PROD_DEVTOOLS__: false, }, + esbuild: { + // https://github.com/vitejs/vite/discussions/8483#discussioncomment-14485974 + // https://esbuild.github.io/api/#tsconfig-raw + tsconfigRaw: tsconfigVue as TsconfigRaw, + }, + build: { target: [ 'chrome116', @@ -163,6 +171,6 @@ export function getConfig(): UserConfig { }; } -const config = defineConfig(({ command, mode }) => getConfig()); +const config = defineConfig(() => getConfig()); export default config; diff --git a/packages/frontend-embed/vite.json5.ts b/packages/frontend-embed/vite.json5.ts index 87b67c2142..54dd5e4d84 100644 --- a/packages/frontend-embed/vite.json5.ts +++ b/packages/frontend-embed/vite.json5.ts @@ -1,9 +1,9 @@ // Original: https://github.com/rollup/plugins/tree/8835dd2aed92f408d7dc72d7cc25a9728e16face/packages/json import JSON5 from 'json5'; -import { Plugin } from 'rollup'; import { createFilter, dataToEsm } from '@rollup/pluginutils'; -import { RollupJsonOptions } from '@rollup/plugin-json'; +import type { Plugin } from 'rollup'; +import type { RollupJsonOptions } from '@rollup/plugin-json'; // json5 extends SyntaxError with additional fields (without subclassing) // https://github.com/json5/json5/blob/de344f0619bda1465a6e25c76f1c0c3dda8108d9/lib/parse.js#L1111-L1112 @@ -19,7 +19,6 @@ export default function json5(options: RollupJsonOptions = {}): Plugin { return { name: 'json5', - // eslint-disable-next-line no-shadow transform(json, id) { if (id.slice(-6) !== '.json5' || !filter(id)) return null;