From b0493abe93f25d00b3a9ae2c2bdee1fbf0e319eb Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Wed, 30 Jul 2025 12:32:24 +0900 Subject: chore: continue backend E2E test even if fail with minimum Node.js version (#16324) * chore: continue backend E2E test even if fail with minimum Node.js version * chore: disable `fail-fast` --- .github/workflows/test-backend.yml | 1 + 1 file changed, 1 insertion(+) (limited to '.github/workflows') diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index e4b139ef63..5358df3dc4 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -109,6 +109,7 @@ jobs: name: E2E tests (backend) runs-on: ubuntu-latest strategy: + fail-fast: false matrix: node-version-file: - .node-version -- cgit v1.2.3-freya From adb3ad6b7f2e4705d563ecdea65879db929a1971 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Fri, 8 Aug 2025 18:47:35 +0900 Subject: Follow up per locale bundle (#16381) * fix docker build * enable check spdx license id in frontend-builder * fix eslint config * run eslint for frontend-builder in ci * fix eslint * add license headers * fix unnecessary comments * update changelog * fix generateDts * fix tsx --- .github/workflows/check-spdx-license-id.yml | 1 + .github/workflows/lint.yml | 3 + CHANGELOG.md | 1 + Dockerfile | 1 + locales/generateDTS.js | 28 ++++--- locales/index.d.ts | 4 +- packages/frontend-builder/README.txt | 2 - packages/frontend-builder/eslint.config.js | 48 +---------- packages/frontend-builder/locale-inliner.ts | 14 +++- .../locale-inliner/apply-with-locale.ts | 41 +++++---- .../locale-inliner/collect-modifications.ts | 96 ++++++++++++---------- packages/frontend-builder/logger.ts | 13 ++- .../rollup-plugin-remove-unref-i18n.ts | 12 +-- packages/frontend-builder/utils.ts | 5 ++ packages/frontend-embed/vite.config.ts | 2 +- packages/frontend-shared/js/i18n.ts | 3 +- packages/frontend/vite.config.ts | 2 +- 17 files changed, 133 insertions(+), 143 deletions(-) (limited to '.github/workflows') diff --git a/.github/workflows/check-spdx-license-id.yml b/.github/workflows/check-spdx-license-id.yml index e40a4557df..cf1fd6007d 100644 --- a/.github/workflows/check-spdx-license-id.yml +++ b/.github/workflows/check-spdx-license-id.yml @@ -50,6 +50,7 @@ jobs: "packages/backend/test" "packages/frontend-shared/@types" "packages/frontend-shared/js" + "packages/frontend-builder" "packages/frontend/.storybook" "packages/frontend/@types" "packages/frontend/lib" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 235faeb807..550438e308 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,6 +9,7 @@ on: - packages/backend/** - packages/frontend/** - packages/frontend-shared/** + - packages/frontend-builder/** - packages/frontend-embed/** - packages/icons-subsetter/** - packages/sw/** @@ -22,6 +23,7 @@ on: - packages/backend/** - packages/frontend/** - packages/frontend-shared/** + - packages/frontend-builder/** - packages/frontend-embed/** - packages/icons-subsetter/** - packages/sw/** @@ -56,6 +58,7 @@ jobs: - backend - frontend - frontend-shared + - frontend-builder - frontend-embed - icons-subsetter - sw diff --git a/CHANGELOG.md b/CHANGELOG.md index 4734033c54..a1dc3e2fe9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Feat: ページのタブバーを下部に表示できるように - Enhance: コントロールパネルを検索できるように - Enhance: トルコ語 (tr-TR) に対応 +- Enhance: 言語別のスクリプトバンドルを生成するように - Fix: 投稿フォームでファイルのアップロードが中止または失敗した際のハンドリングを修正 - Fix: 一部の設定検索結果が存在しないパスになる問題を修正 (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1171) diff --git a/Dockerfile b/Dockerfile index 62b737c084..370bed5751 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,7 @@ COPY --link ["packages/backend/package.json", "./packages/backend/"] COPY --link ["packages/frontend-shared/package.json", "./packages/frontend-shared/"] COPY --link ["packages/frontend/package.json", "./packages/frontend/"] COPY --link ["packages/frontend-embed/package.json", "./packages/frontend-embed/"] +COPY --link ["packages/frontend-builder/package.json", "./packages/frontend-builder/"] COPY --link ["packages/icons-subsetter/package.json", "./packages/icons-subsetter/"] COPY --link ["packages/sw/package.json", "./packages/sw/"] COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"] diff --git a/locales/generateDTS.js b/locales/generateDTS.js index 49807144ec..ab0613cc82 100644 --- a/locales/generateDTS.js +++ b/locales/generateDTS.js @@ -73,7 +73,7 @@ export default function generateDTS() { ts.NodeFlags.Const, ), ), - ts.factory.createInterfaceDeclaration( + ts.factory.createTypeAliasDeclaration( [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier('ParameterizedString'), [ @@ -84,20 +84,22 @@ export default function generateDTS() { ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), ), ], - undefined, - [ - ts.factory.createPropertySignature( - undefined, - ts.factory.createComputedPropertyName( - ts.factory.createIdentifier('kParameters'), - ), - undefined, - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier('T'), + ts.factory.createIntersectionTypeNode([ + ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), + ts.factory.createTypeLiteralNode([ + ts.factory.createPropertySignature( undefined, + ts.factory.createComputedPropertyName( + ts.factory.createIdentifier('kParameters'), + ), + undefined, + ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier('T'), + undefined, + ), ), - ), - ], + ]) + ]), ), ts.factory.createInterfaceDeclaration( [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], diff --git a/locales/index.d.ts b/locales/index.d.ts index cafa9012b9..b0a15e0ad1 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2,9 +2,9 @@ // This file is generated by locales/generateDTS.js // Do not edit this file directly. declare const kParameters: unique symbol; -export interface ParameterizedString { +export type ParameterizedString = string & { [kParameters]: T; -} +}; export interface ILocale { [_: string]: string | ParameterizedString | ILocale; } diff --git a/packages/frontend-builder/README.txt b/packages/frontend-builder/README.txt index db878ffa83..428166e792 100644 --- a/packages/frontend-builder/README.txt +++ b/packages/frontend-builder/README.txt @@ -1,3 +1 @@ This package contains the common scripts that are used to build the frontend and frontend-embed packages. - - diff --git a/packages/frontend-builder/eslint.config.js b/packages/frontend-builder/eslint.config.js index 5805c9924d..a13490c97f 100644 --- a/packages/frontend-builder/eslint.config.js +++ b/packages/frontend-builder/eslint.config.js @@ -1,20 +1,13 @@ import globals from 'globals'; import tsParser from '@typescript-eslint/parser'; -import pluginMisskey from '@misskey-dev/eslint-plugin'; import sharedConfig from '../shared/eslint.config.js'; // eslint-disable-next-line import/no-default-export export default [ ...sharedConfig, - { - files: ['**/*.vue'], - ...pluginMisskey.configs.typescript, - }, { files: [ - '@types/**/*.ts', - 'js/**/*.ts', - '**/*.vue', + '**/*.ts', ], languageOptions: { globals: { @@ -50,45 +43,6 @@ export default [ // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため 'id-denylist': ['error', 'window', 'e'], 'no-shadow': ['warn'], - 'vue/attributes-order': ['error', { - alphabetical: false, - }], - 'vue/no-use-v-if-with-v-for': ['error', { - allowUsingIterationVar: false, - }], - 'vue/no-ref-as-operand': 'error', - 'vue/no-multi-spaces': ['error', { - ignoreProperties: false, - }], - 'vue/no-v-html': 'warn', - 'vue/order-in-components': 'error', - 'vue/html-indent': ['warn', 'tab', { - attribute: 1, - baseIndent: 0, - closeBracket: 0, - alignAttributesVertically: true, - ignores: [], - }], - 'vue/html-closing-bracket-spacing': ['warn', { - startTag: 'never', - endTag: 'never', - selfClosingTag: 'never', - }], - 'vue/multi-word-component-names': 'warn', - 'vue/require-v-for-key': 'warn', - 'vue/no-unused-components': 'warn', - 'vue/no-unused-vars': 'warn', - 'vue/no-dupe-keys': 'warn', - 'vue/valid-v-for': 'warn', - 'vue/return-in-computed-property': 'warn', - 'vue/no-setup-props-reactivity-loss': 'warn', - 'vue/max-attributes-per-line': 'off', - 'vue/html-self-closing': 'off', - 'vue/singleline-html-element-content-newline': 'off', - 'vue/v-on-event-hyphenation': ['error', 'never', { - autofix: true, - }], - 'vue/attribute-hyphenation': ['error', 'never'], }, }, { diff --git a/packages/frontend-builder/locale-inliner.ts b/packages/frontend-builder/locale-inliner.ts index ce3f59a81c..75bcdc5b3f 100644 --- a/packages/frontend-builder/locale-inliner.ts +++ b/packages/frontend-builder/locale-inliner.ts @@ -1,11 +1,17 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + import * as fs from 'fs/promises'; import * as path from 'node:path'; -import { type Locale } from '../../locales/index.js'; -import type { Manifest as ViteManifest } from 'vite'; import MagicString from 'magic-string'; import { collectModifications } from './locale-inliner/collect-modifications.js'; import { applyWithLocale } from './locale-inliner/apply-with-locale.js'; -import { blankLogger, type Logger } from './logger.js'; +import { blankLogger } from './logger.js'; +import type { Logger } from './logger.js'; +import type { Locale } from '../../locales/index.js'; +import type { Manifest as ViteManifest } from 'vite'; export class LocaleInliner { outputDir: string; @@ -70,7 +76,7 @@ export class LocaleInliner { async saveLocale(localeName: string, localeJson: Locale) { // create directory await fs.mkdir(path.join(this.outputDir, localeName), { recursive: true }); - const localeLogger = localeName == 'ja-JP' ? this.logger : blankLogger; // we want to log for single locale only + const localeLogger = localeName === 'ja-JP' ? this.logger : blankLogger; // we want to log for single locale only for (const chunk of this.chunks) { if (!chunk.sourceCode || !chunk.modifications) { throw new Error(`Source code or modifications for ${chunk.fileName} is not available.`); diff --git a/packages/frontend-builder/locale-inliner/apply-with-locale.ts b/packages/frontend-builder/locale-inliner/apply-with-locale.ts index a79ebb4253..5e601cdf12 100644 --- a/packages/frontend-builder/locale-inliner/apply-with-locale.ts +++ b/packages/frontend-builder/locale-inliner/apply-with-locale.ts @@ -1,6 +1,11 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + import MagicString from 'magic-string'; -import type { Locale } from '../../../locales/index.js'; import { assertNever } from '../utils.js'; +import type { Locale, ILocale } from '../../../locales/index.js'; import type { TextModification } from '../locale-inliner.js'; import type { Logger } from '../logger.js'; @@ -13,16 +18,16 @@ export function applyWithLocale( ) { for (const modification of modifications) { switch (modification.type) { - case "delete": + case 'delete': sourceCode.remove(modification.begin, modification.end); break; - case "insert": + case 'insert': sourceCode.appendRight(modification.begin, modification.text); break; - case "replace": + case 'replace': sourceCode.update(modification.begin, modification.end, modification.text); break; - case "localized": { + case 'localized': { const accessed = getPropertyByPath(localeJson, modification.localizationKey); if (accessed == null) { fileLogger.warn(`Cannot find localization key ${modification.localizationKey.join('.')}`); @@ -30,7 +35,7 @@ export function applyWithLocale( sourceCode.update(modification.begin, modification.end, JSON.stringify(accessed)); break; } - case "parameterized-function": { + case 'parameterized-function': { const accessed = getPropertyByPath(localeJson, modification.localizationKey); let replacement: string; if (typeof accessed === 'string') { @@ -44,33 +49,33 @@ export function applyWithLocale( sourceCode.update(modification.begin, modification.end, replacement); break; - function formatFunction(accessed: string): string { + function formatFunction(format: string): string { const params = new Set(); const components: string[] = []; let lastIndex = 0; - for (const match of accessed.matchAll(/\{(.+?)}/g)) { + for (const match of format.matchAll(/\{(.+?)}/g)) { const [fullMatch, paramName] = match; if (lastIndex < match.index) { - components.push(JSON.stringify(accessed.slice(lastIndex, match.index))); + components.push(JSON.stringify(format.slice(lastIndex, match.index))); } params.add(paramName); components.push(paramName); lastIndex = match.index + fullMatch.length; } - components.push(JSON.stringify(accessed.slice(lastIndex))); + components.push(JSON.stringify(format.slice(lastIndex))); // we replace with `(({name,count})=>(name+count+"some"))` const paramList = Array.from(params).join(','); - let body = components.filter(x => x != '""').join('+'); - if (body == '') body = '""'; // if the body is empty, we return empty string + let body = components.filter(x => x !== '""').join('+'); + if (body === '') body = '""'; // if the body is empty, we return empty string return `(({${paramList}})=>(${body}))`; } } - case "locale-name": { + case 'locale-name': { sourceCode.update(modification.begin, modification.end, modification.literal ? JSON.stringify(localeName) : localeName); break; } - case "locale-json": { + case 'locale-json': { // locale-json is inlined to place where initialize module-level variable which is executed only once. // In such case we can use JSON.parse to speed up the parsing script. // https://v8.dev/blog/cost-of-javascript-2019#json @@ -84,14 +89,14 @@ export function applyWithLocale( } } -function getPropertyByPath(localeJson: any, localizationKey: string[]): string | object | null { +function getPropertyByPath(localeJson: ILocale, localizationKey: string[]): string | object | null { if (localizationKey.length === 0) return localeJson; - let current: any = localeJson; + let current: ILocale | string = localeJson; for (const key of localizationKey) { - if (typeof current !== 'object' || current === null || !(key in current)) { + if (typeof current !== 'object' || !(key in current)) { return null; // Key not found } current = current[key]; } - return current ?? null; + return current; } diff --git a/packages/frontend-builder/locale-inliner/collect-modifications.ts b/packages/frontend-builder/locale-inliner/collect-modifications.ts index 0cbf6a504e..59e5d96517 100644 --- a/packages/frontend-builder/locale-inliner/collect-modifications.ts +++ b/packages/frontend-builder/locale-inliner/collect-modifications.ts @@ -1,10 +1,15 @@ -import type { AstNode, ProgramNode } from 'rollup'; +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + import { parseAst } from 'vite'; import * as estreeWalker from 'estree-walker'; +import { assertNever, assertType } from '../utils.js'; +import type { AstNode, ProgramNode } from 'rollup'; import type * as estree from 'estree'; import type { LocaleInliner, TextModification } from '../locale-inliner.js'; -import type { Logger } from '../logger.js' -import { assertNever, assertType } from '../utils.js'; +import type { Logger } from '../logger.js'; // WalkerContext is not exported from estree-walker, so we define it here interface WalkerContext { @@ -15,12 +20,12 @@ export function collectModifications(sourceCode: string, fileName: string, fileL let programNode: ProgramNode; try { programNode = parseAst(sourceCode); - } catch (e) { - fileLogger.error(`Failed to parse source code: ${e}`); + } catch (err) { + fileLogger.error(`Failed to parse source code: ${err}`); return []; } if (programNode.sourceType !== 'module') { - fileLogger.error(`Source code is not a module.`); + fileLogger.error('Source code is not a module.'); return []; } @@ -32,7 +37,7 @@ export function collectModifications(sourceCode: string, fileName: string, fileL // 3) replace all `await window.fetch(`/assets/locales/${d}.${x}.json`).then(u=>u.json())` with `localeJson` variable estreeWalker.walk(programNode, { enter(this: WalkerContext, node: Node) { - assertType(node) + assertType(node); if (node.type === 'Literal' && typeof node.value === 'string' && node.raw) { if (node.raw.substring(1).startsWith(inliner.scriptsDir)) { @@ -46,7 +51,7 @@ export function collectModifications(sourceCode: string, fileName: string, fileL localizedOnly: true, }); } - if (node.raw.substring(1, node.raw.length - 1) == `${inliner.scriptsDir}/${inliner.i18nFileName}`) { + if (node.raw.substring(1, node.raw.length - 1) === `${inliner.scriptsDir}/${inliner.i18nFileName}`) { // we find `scripts/i18n.ts` literal. // This is tipically in depmap and replace with this file name to avoid unnecessary loading i18n script fileLogger.debug(`${lineCol(sourceCode, node)}: found ${inliner.i18nFileName} path literal ${node.raw}`); @@ -81,17 +86,17 @@ export function collectModifications(sourceCode: string, fileName: string, fileL localizedOnly: true, }); } - } - }) + }, + }); const importSpecifierResult = findImportSpecifier(programNode, inliner.i18nFileName, 'i18n'); switch (importSpecifierResult.type) { case 'no-import': - fileLogger.debug(`No import of i18n found, skipping inlining.`); + fileLogger.debug('No import of i18n found, skipping inlining.'); return modifications; case 'no-specifiers': - fileLogger.debug(`Importing i18n without specifiers, removing the import.`); + fileLogger.debug('Importing i18n without specifiers, removing the import.'); modifications.push({ type: 'delete', begin: importSpecifierResult.importNode.start, @@ -115,17 +120,18 @@ export function collectModifications(sourceCode: string, fileName: string, fileL let isSupported = true; estreeWalker.walk(programNode, { enter(node) { - if (node.type == 'VariableDeclaration') { + if (node.type === 'VariableDeclaration') { assertType(node); - for (let id of node.declarations.flatMap(x => declsOfPattern(x.id))) { - if (id == localI18nIdentifier) { + for (const id of node.declarations.flatMap(x => declsOfPattern(x.id))) { + if (id === localI18nIdentifier) { isSupported = false; } } } - } - }) + }, + }); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!isSupported) { fileLogger.error(`Duplicated identifier "${localI18nIdentifier}" in variable declaration. Skipping inlining.`); return modifications; @@ -141,8 +147,8 @@ export function collectModifications(sourceCode: string, fileName: string, fileL toSkip.add(i18nImport); estreeWalker.walk(programNode, { enter(this: WalkerContext, node, parent, property) { - assertType(node) - assertType(parent) + assertType(node); + assertType(parent); if (toSkip.has(node)) { // This is the import specifier, skip processing it this.skip(); @@ -150,23 +156,23 @@ export function collectModifications(sourceCode: string, fileName: string, fileL } // We don't care original name part of the import declaration - if (node.type == 'ImportDeclaration') this.skip(); + if (node.type === 'ImportDeclaration') this.skip(); if (node.type === 'Identifier') { - assertType(node) - assertType(parent) - if (parent.type === 'Property' && !parent.computed && property == 'key') return; // we don't care 'id' part of { id: expr } - if (parent.type === 'MemberExpression' && !parent.computed && property == 'property') return; // we don't care 'id' part of { id: expr } - if (parent.type === 'ExportSpecifier' && property == 'exported') return; // we don't care 'id' part of { id: expr } - if (node.name == localI18nIdentifier) { + assertType(node); + assertType(parent); + if (parent.type === 'Property' && !parent.computed && property === 'key') return; // we don't care 'id' part of { id: expr } + if (parent.type === 'MemberExpression' && !parent.computed && property === 'property') return; // we don't care 'id' part of { id: expr } + if (parent.type === 'ExportSpecifier' && property === 'exported') return; // we don't care 'id' part of { id: expr } + if (node.name === localI18nIdentifier) { fileLogger.error(`${lineCol(sourceCode, node)}: Using i18n identifier "${localI18nIdentifier}" directly. Skipping inlining.`); preserveI18nImport = true; } } else if (node.type === 'MemberExpression') { assertType(node); const i18nPath = parseI18nPropertyAccess(node); - if (i18nPath != null && i18nPath.length >= 2 && i18nPath[0] == 'ts') { - if (parent.type === 'CallExpression' && property == 'callee') return; // we don't want to process `i18n.ts.property.stringBuiltinMethod()` + if (i18nPath != null && i18nPath.length >= 2 && i18nPath[0] === 'ts') { + if (parent.type === 'CallExpression' && property === 'callee') return; // we don't want to process `i18n.ts.property.stringBuiltinMethod()` if (i18nPath.at(-1)?.startsWith('_')) fileLogger.debug(`found i18n grouped property access ${i18nPath.join('.')}`); else fileLogger.debug(`${lineCol(sourceCode, node)}: found i18n property access ${i18nPath.join('.')}`); // it's i18n.ts.propertyAccess @@ -179,7 +185,7 @@ export function collectModifications(sourceCode: string, fileName: string, fileL localizedOnly: true, }); this.skip(); - } else if (i18nPath != null && i18nPath.length >= 2 && i18nPath[0] == 'tsx') { + } else if (i18nPath != null && i18nPath.length >= 2 && i18nPath[0] === 'tsx') { // it's parameterized locale substitution (`i18n.tsx.property(parameters)`) // we expect the parameter to be an object literal fileLogger.debug(`${lineCol(sourceCode, node)}: found i18n function access (object) ${i18nPath.join('.')}`); @@ -197,11 +203,12 @@ export function collectModifications(sourceCode: string, fileName: string, fileL // If there is 'i18n' in the parameters, we care interior of the function if (node.params.flatMap(param => declsOfPattern(param)).includes(localI18nIdentifier)) this.skip(); } - } - }) + }, + }); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!preserveI18nImport) { - fileLogger.debug(`removing i18n import statement`); + fileLogger.debug('removing i18n import statement'); modifications.push({ type: 'delete', begin: i18nImport.start, @@ -211,7 +218,7 @@ export function collectModifications(sourceCode: string, fileName: string, fileL } function parseI18nPropertyAccess(node: estree.Expression | estree.Super): string[] | null { - if (node.type === 'Identifier' && node.name == localI18nIdentifier) return []; // i18n itself + if (node.type === 'Identifier' && node.name === localI18nIdentifier) return []; // i18n itself if (node.type !== 'MemberExpression') return null; // super.* if (node.object.type === 'Super') return null; @@ -219,7 +226,6 @@ export function collectModifications(sourceCode: string, fileName: string, fileL // i18n?.property is not supported if (node.optional) return null; - let id: string | null = null; if (node.computed) { if (node.property.type === 'Literal' && typeof node.property.value === 'string') { @@ -243,10 +249,10 @@ export function collectModifications(sourceCode: string, fileName: string, fileL function declsOfPattern(pattern: estree.Pattern | null): string[] { if (pattern == null) return []; - switch (pattern?.type) { - case "Identifier": + switch (pattern.type) { + case 'Identifier': return [pattern.name]; - case "ObjectPattern": + case 'ObjectPattern': return pattern.properties.flatMap(prop => { switch (prop.type) { case 'Property': @@ -254,16 +260,16 @@ function declsOfPattern(pattern: estree.Pattern | null): string[] { case 'RestElement': return declsOfPattern(prop.argument); default: - assertNever(prop) + assertNever(prop); } }); - case "ArrayPattern": + case 'ArrayPattern': return pattern.elements.flatMap(p => declsOfPattern(p)); - case "RestElement": + case 'RestElement': return declsOfPattern(pattern.argument); - case "AssignmentPattern": + case 'AssignmentPattern': return declsOfPattern(pattern.left); - case "MemberExpression": + case 'MemberExpression': // assignment pattern so no new variable is declared return []; default: @@ -375,15 +381,15 @@ type SpecifierResult = function findImportSpecifier(programNode: ProgramNode, i18nFileName: string, i18nSymbol: string): SpecifierResult { const imports = programNode.body.filter(x => x.type === 'ImportDeclaration'); - const importNode = imports.find(x => x.source.value === `./${i18nFileName}`) as estree.ImportDeclaration; + const importNode = imports.find(x => x.source.value === `./${i18nFileName}`) as estree.ImportDeclaration | undefined; if (!importNode) return { type: 'no-import' }; assertType(importNode); - if (importNode.specifiers.length == 0) { + if (importNode.specifiers.length === 0) { return { type: 'no-specifiers', importNode }; } - if (importNode.specifiers.length != 1) { + if (importNode.specifiers.length !== 1) { return { type: 'unexpected-specifiers', importNode }; } const i18nImportSpecifier = importNode.specifiers[0]; diff --git a/packages/frontend-builder/logger.ts b/packages/frontend-builder/logger.ts index a3f66730e2..c619882380 100644 --- a/packages/frontend-builder/logger.ts +++ b/packages/frontend-builder/logger.ts @@ -1,4 +1,11 @@ -const debug = false; +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import * as process from 'node:process'; + +const debug = process.env.BUILDER_DEBUG !== undefined && process.env.BUILDER_DEBUG !== '0'; export interface Logger { debug(message: string): void; @@ -27,7 +34,7 @@ export function createLogger(): RootLogger { type LogContext = { warningCount: number; errorCount: number; -} +}; function loggerFactory(prefix: string, context: LogContext): RootLogger { return { @@ -63,4 +70,4 @@ export const blankLogger: Logger = { error: () => void 0, info: () => void 0, prefixed: () => blankLogger, -} +}; diff --git a/packages/frontend-builder/rollup-plugin-remove-unref-i18n.ts b/packages/frontend-builder/rollup-plugin-remove-unref-i18n.ts index 9010e6910c..4a2bfa67d9 100644 --- a/packages/frontend-builder/rollup-plugin-remove-unref-i18n.ts +++ b/packages/frontend-builder/rollup-plugin-remove-unref-i18n.ts @@ -4,18 +4,18 @@ */ import * as estreeWalker from 'estree-walker'; -import type { Plugin } from 'vite'; -import type { CallExpression, Expression, Program, } from 'estree'; import MagicString from 'magic-string'; -import type { AstNode } from 'rollup'; import { assertType } from './utils.js'; +import type { Plugin } from 'vite'; +import type { CallExpression, Expression, Program } from 'estree'; +import type { AstNode } from 'rollup'; // This plugin transforms `unref(i18n)` to `i18n` in the code, which is useful for removing unnecessary unref calls // and helps locale inliner runs after vite build to inline the locale data into the final build. // // locale inliner cannot know minifiedSymbol(i18n) is 'unref(i18n)' or 'otherFunctionsWithEffect(i18n)' so // it is necessary to remove unref calls before minification. -export default function pluginRemoveUnrefI18n( +export function pluginRemoveUnrefI18n( { i18nSymbolName = 'i18n', }: { @@ -42,12 +42,12 @@ export default function pluginRemoveUnrefI18n( magicString.remove(arg.end, node.end); } } - } + }, }); return { code: magicString.toString(), map: magicString.generateMap({ hires: true }), - } + }; }, }; } diff --git a/packages/frontend-builder/utils.ts b/packages/frontend-builder/utils.ts index 1ce9f7fc76..71ffebe03e 100644 --- a/packages/frontend-builder/utils.ts +++ b/packages/frontend-builder/utils.ts @@ -1,5 +1,10 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ export function assertNever(x: never): never { + // eslint-disable-next-line @typescript-eslint/no-explicit-any throw new Error(`Unexpected type: ${(x as any)?.type ?? x}`); } diff --git a/packages/frontend-embed/vite.config.ts b/packages/frontend-embed/vite.config.ts index eb57db9774..3ddee9b8a9 100644 --- a/packages/frontend-embed/vite.config.ts +++ b/packages/frontend-embed/vite.config.ts @@ -8,7 +8,7 @@ import locales from '../../locales/index.js'; import meta from '../../package.json'; import packageInfo from './package.json' with { type: 'json' }; import pluginJson5 from './vite.json5.js'; -import pluginRemoveUnrefI18n from '../frontend-builder/rollup-plugin-remove-unref-i18n'; +import { pluginRemoveUnrefI18n } from '../frontend-builder/rollup-plugin-remove-unref-i18n'; const url = process.env.NODE_ENV === 'development' ? yaml.load(await fsp.readFile('../../.config/default.yml', 'utf-8')).url : null; const host = url ? (new URL(url)).hostname : undefined; diff --git a/packages/frontend-shared/js/i18n.ts b/packages/frontend-shared/js/i18n.ts index bd9ba0922a..3b103c4714 100644 --- a/packages/frontend-shared/js/i18n.ts +++ b/packages/frontend-shared/js/i18n.ts @@ -28,7 +28,8 @@ type ParametersOf = { - readonly [K in keyof T as T[K] extends string ? never : K]: T[K] extends ParameterizedString + // `string extends T[K] ? never : K` part removes non-parameterized string keys from Tsx type. + readonly [K in keyof T as string extends T[K] ? never : K]: T[K] extends ParameterizedString ? (arg: { readonly [_ in P]: string | number }) => string // @ts-expect-error -- 証明省略 : Tsx; diff --git a/packages/frontend/vite.config.ts b/packages/frontend/vite.config.ts index e9707d13d1..9b54014b54 100644 --- a/packages/frontend/vite.config.ts +++ b/packages/frontend/vite.config.ts @@ -14,7 +14,7 @@ import pluginJson5 from './vite.json5.js'; import pluginCreateSearchIndex from './lib/vite-plugin-create-search-index.js'; import type { Options as SearchIndexOptions } from './lib/vite-plugin-create-search-index.js'; import pluginWatchLocales from './lib/vite-plugin-watch-locales.js'; -import pluginRemoveUnrefI18n from '../frontend-builder/rollup-plugin-remove-unref-i18n.js'; +import { pluginRemoveUnrefI18n } from '../frontend-builder/rollup-plugin-remove-unref-i18n.js'; const url = process.env.NODE_ENV === 'development' ? yaml.load(await fsp.readFile('../../.config/default.yml', 'utf-8')).url : null; const host = url ? (new URL(url)).hostname : undefined; -- cgit v1.2.3-freya From f24289238298e42aecb0073b25b86798c2dc5ab8 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:54:06 +0900 Subject: fix(workflow): correct references to built image's ID (#16391) --- .github/workflows/dockle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to '.github/workflows') diff --git a/.github/workflows/dockle.yml b/.github/workflows/dockle.yml index 3054607913..f006a45ea4 100644 --- a/.github/workflows/dockle.yml +++ b/.github/workflows/dockle.yml @@ -25,7 +25,7 @@ jobs: cp ./compose_example.yml ./compose.yml - run: | docker compose up -d web - docker tag "$(docker compose images web | awk 'OFS=":" {print $4}' | tail -n +2)" misskey-web:latest + docker tag "$(docker compose images --format json web | jq -r '.[] | .ID')" misskey-web:latest - run: | cmd="dockle --exit-code 1 misskey-web:latest ${image_name}" echo "> ${cmd}" -- cgit v1.2.3-freya From 857a87d4b6fbad10ae6b4bf4a593343ed642f259 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 11:53:23 +0900 Subject: chore(deps): update [github actions] update dependencies (#16447) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/api-misskey-js.yml | 2 +- .github/workflows/changelog-check.yml | 2 +- .github/workflows/check-misskey-js-autogen.yml | 4 ++-- .github/workflows/check-misskey-js-version.yml | 2 +- .github/workflows/check-spdx-license-id.yml | 2 +- .github/workflows/check_copyright_year.yml | 2 +- .github/workflows/deploy-test-environment.yml | 2 +- .github/workflows/docker-develop.yml | 2 +- .github/workflows/docker.yml | 2 +- .github/workflows/dockle.yml | 2 +- .github/workflows/get-api-diff.yml | 2 +- .github/workflows/lint.yml | 8 ++++---- .github/workflows/locale.yml | 2 +- .github/workflows/on-release-created.yml | 2 +- .github/workflows/storybook.yml | 4 ++-- .github/workflows/test-backend.yml | 6 +++--- .github/workflows/test-frontend.yml | 4 ++-- .github/workflows/test-misskey-js.yml | 2 +- .github/workflows/test-production.yml | 2 +- .github/workflows/validate-api-json.yml | 2 +- 20 files changed, 28 insertions(+), 28 deletions(-) (limited to '.github/workflows') diff --git a/.github/workflows/api-misskey-js.yml b/.github/workflows/api-misskey-js.yml index 6117e69c03..76a0bae8cc 100644 --- a/.github/workflows/api-misskey-js.yml +++ b/.github/workflows/api-misskey-js.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 diff --git a/.github/workflows/changelog-check.yml b/.github/workflows/changelog-check.yml index 5ca27749bb..f4abedd960 100644 --- a/.github/workflows/changelog-check.yml +++ b/.github/workflows/changelog-check.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout head - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Setup Node.js uses: actions/setup-node@v4.4.0 with: diff --git a/.github/workflows/check-misskey-js-autogen.yml b/.github/workflows/check-misskey-js-autogen.yml index 22d500c306..05034ea0f4 100644 --- a/.github/workflows/check-misskey-js-autogen.yml +++ b/.github/workflows/check-misskey-js-autogen.yml @@ -18,7 +18,7 @@ jobs: if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }} steps: - name: checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 with: submodules: true persist-credentials: false @@ -66,7 +66,7 @@ jobs: if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }} steps: - name: checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 with: submodules: true persist-credentials: false diff --git a/.github/workflows/check-misskey-js-version.yml b/.github/workflows/check-misskey-js-version.yml index 2b15cbee53..0e336a1551 100644 --- a/.github/workflows/check-misskey-js-version.yml +++ b/.github/workflows/check-misskey-js-version.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Check version run: | if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then diff --git a/.github/workflows/check-spdx-license-id.yml b/.github/workflows/check-spdx-license-id.yml index cf1fd6007d..d0b1be4991 100644 --- a/.github/workflows/check-spdx-license-id.yml +++ b/.github/workflows/check-spdx-license-id.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Check run: | counter=0 diff --git a/.github/workflows/check_copyright_year.yml b/.github/workflows/check_copyright_year.yml index eaf922d4bc..d891a538c6 100644 --- a/.github/workflows/check_copyright_year.yml +++ b/.github/workflows/check_copyright_year.yml @@ -10,7 +10,7 @@ jobs: check_copyright_year: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 - run: | if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then echo "Please change copyright year!" diff --git a/.github/workflows/deploy-test-environment.yml b/.github/workflows/deploy-test-environment.yml index 46baf7421b..d838bc35e5 100644 --- a/.github/workflows/deploy-test-environment.yml +++ b/.github/workflows/deploy-test-environment.yml @@ -28,7 +28,7 @@ jobs: wait_time: ${{ steps.get-wait-time.outputs.wait_time }} steps: - name: Checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Check allowed users id: check-allowed-users diff --git a/.github/workflows/docker-develop.yml b/.github/workflows/docker-develop.yml index 56dedf273d..e24ef00d78 100644 --- a/.github/workflows/docker-develop.yml +++ b/.github/workflows/docker-develop.yml @@ -27,7 +27,7 @@ jobs: platform=${{ matrix.platform }} echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Check out the repo - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Docker Hub diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index eb98273ba0..991fb85d85 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -32,7 +32,7 @@ jobs: platform=${{ matrix.platform }} echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Check out the repo - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Docker meta diff --git a/.github/workflows/dockle.yml b/.github/workflows/dockle.yml index f006a45ea4..1c0863e274 100644 --- a/.github/workflows/dockle.yml +++ b/.github/workflows/dockle.yml @@ -15,7 +15,7 @@ jobs: DOCKER_CONTENT_TRUST: 1 DOCKLE_VERSION: 0.4.14 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 - name: Download and install dockle v${{ env.DOCKLE_VERSION }} run: | curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit.deb" diff --git a/.github/workflows/get-api-diff.yml b/.github/workflows/get-api-diff.yml index 933404dfa5..1cd1ef0ebd 100644 --- a/.github/workflows/get-api-diff.yml +++ b/.github/workflows/get-api-diff.yml @@ -25,7 +25,7 @@ jobs: ref: refs/pull/${{ github.event.number }}/merge steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: ref: ${{ matrix.ref }} submodules: true diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 550438e308..91813cebc3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,7 +36,7 @@ jobs: pnpm_install: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: fetch-depth: 0 submodules: true @@ -69,7 +69,7 @@ jobs: eslint-cache-version: v1 eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }} steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: fetch-depth: 0 submodules: true @@ -81,7 +81,7 @@ jobs: cache: 'pnpm' - run: pnpm i --frozen-lockfile - name: Restore eslint cache - uses: actions/cache@v4.2.3 + uses: actions/cache@v4.2.4 with: path: ${{ env.eslint-cache-path }} key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }} @@ -99,7 +99,7 @@ jobs: - sw - misskey-js steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: fetch-depth: 0 submodules: true diff --git a/.github/workflows/locale.yml b/.github/workflows/locale.yml index 68e45fdf61..63702c8bc7 100644 --- a/.github/workflows/locale.yml +++ b/.github/workflows/locale.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: fetch-depth: 0 submodules: true diff --git a/.github/workflows/on-release-created.yml b/.github/workflows/on-release-created.yml index 7787d6055b..f36eb0037d 100644 --- a/.github/workflows/on-release-created.yml +++ b/.github/workflows/on-release-created.yml @@ -16,7 +16,7 @@ jobs: id-token: write steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true - name: Setup pnpm diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index b1d95c1b33..7f964ef1d7 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -22,12 +22,12 @@ jobs: NODE_OPTIONS: "--max_old_space_size=7168" steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 if: github.event_name != 'pull_request_target' with: fetch-depth: 0 submodules: true - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 if: github.event_name == 'pull_request_target' with: fetch-depth: 0 diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index 5358df3dc4..e9791ac95e 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -50,7 +50,7 @@ jobs: - 56312:6379 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true - name: Setup pnpm @@ -129,7 +129,7 @@ jobs: - 56312:6379 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true - name: Setup pnpm @@ -173,7 +173,7 @@ jobs: POSTGRES_HOST_AUTH_METHOD: trust steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true - name: Setup pnpm diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml index 94e43cf91e..da3c9255f2 100644 --- a/.github/workflows/test-frontend.yml +++ b/.github/workflows/test-frontend.yml @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true - name: Setup pnpm @@ -76,7 +76,7 @@ jobs: - 56312:6379 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true # https://github.com/cypress-io/cypress-docker-images/issues/150 diff --git a/.github/workflows/test-misskey-js.yml b/.github/workflows/test-misskey-js.yml index f6d16bbd76..0fad57f8da 100644 --- a/.github/workflows/test-misskey-js.yml +++ b/.github/workflows/test-misskey-js.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v4.3.0 - name: Setup pnpm uses: pnpm/action-setup@v4.1.0 diff --git a/.github/workflows/test-production.yml b/.github/workflows/test-production.yml index 751c374608..08289dfd3b 100644 --- a/.github/workflows/test-production.yml +++ b/.github/workflows/test-production.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true - name: Setup pnpm diff --git a/.github/workflows/validate-api-json.yml b/.github/workflows/validate-api-json.yml index edff7dbecb..25353e4d29 100644 --- a/.github/workflows/validate-api-json.yml +++ b/.github/workflows/validate-api-json.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@v4.3.0 with: submodules: true - name: Setup pnpm -- cgit v1.2.3-freya