From f3500ffda96913e41708a6ca04ef9bbf07af74e4 Mon Sep 17 00:00:00 2001 From: Nila <43315617+nilathedragon@users.noreply.github.com> Date: Sat, 30 Mar 2024 02:28:47 +0100 Subject: [PATCH 01/19] fix: report progress out of 100% in CleanRemoteFilesProcessorService (#13633) * Report progress out of 100% in CleanRemoteFilesProcessorService * Add changelog entry --- CHANGELOG.md | 1 + .../src/queue/processors/CleanRemoteFilesProcessorService.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f41ff2171f..3cfbb5f9c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - Enhance: misskey-dev/summaly@5.1.0の取り込み(プレビュー生成処理の効率化) - Fix: フォローリクエストを作成する際に既存のものは削除するように (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/440) +- Fix: CleanRemoteFilesProcessorService report progress from 100% (#13632) ## 2024.3.1 diff --git a/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts b/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts index 917de8b72c..728fc9e72b 100644 --- a/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts +++ b/packages/backend/src/queue/processors/CleanRemoteFilesProcessorService.ts @@ -63,7 +63,7 @@ export class CleanRemoteFilesProcessorService { isLink: false, }); - job.updateProgress(deletedCount / total); + job.updateProgress(100 / total * deletedCount); } this.logger.succ('All cached remote files has been deleted.'); From b35ae97ba7b57ae2b04eb0cc25dd3360e321e537 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Sat, 30 Mar 2024 13:51:53 +0900 Subject: [PATCH 02/19] fix(backend): better `notes/translate` error response (#13631) * fix(backend): better `notes/translate` error response * Update CHANGELOG.md * test(backend): perform administrative operations as `root` --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + .../server/api/endpoints/notes/translate.ts | 13 ++- packages/backend/test/e2e/note.ts | 107 ++++++++++++++---- packages/misskey-js/src/autogen/types.ts | 4 + 4 files changed, 97 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cfbb5f9c8..5963549cc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - Enhance: misskey-dev/summaly@5.1.0の取り込み(プレビュー生成処理の効率化) - Fix: フォローリクエストを作成する際に既存のものは削除するように (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/440) +- Fix: エンドポイント`notes/translate`のエラーを改善 - Fix: CleanRemoteFilesProcessorService report progress from 100% (#13632) ## 2024.3.1 diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index 78812351f4..38a9660aa2 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -21,7 +21,7 @@ export const meta = { res: { type: 'object', - optional: false, nullable: false, + optional: true, nullable: false, properties: { sourceLang: { type: 'string' }, text: { type: 'string' }, @@ -39,6 +39,11 @@ export const meta = { code: 'NO_SUCH_NOTE', id: 'bea9b03f-36e0-49c5-a4db-627a029f8971', }, + cannotTranslateInvisibleNote: { + message: 'Cannot translate invisible note.', + code: 'CANNOT_TRANSLATE_INVISIBLE_NOTE', + id: 'ea29f2ca-c368-43b3-aaf1-5ac3e74bbe5d', + }, }, } as const; @@ -72,17 +77,17 @@ export default class extends Endpoint { // eslint- }); if (!(await this.noteEntityService.isVisibleForMe(note, me.id))) { - return 204; // TODO: 良い感じのエラー返す + throw new ApiError(meta.errors.cannotTranslateInvisibleNote); } if (note.text == null) { - return 204; + return; } const instance = await this.metaService.fetch(); if (instance.deeplAuthKey == null) { - return 204; // TODO: 良い感じのエラー返す + throw new ApiError(meta.errors.unavailable); } let targetLang = ps.targetLang; diff --git a/packages/backend/test/e2e/note.ts b/packages/backend/test/e2e/note.ts index 11016f58ae..bda31d9640 100644 --- a/packages/backend/test/e2e/note.ts +++ b/packages/backend/test/e2e/note.ts @@ -8,12 +8,13 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import { MiNote } from '@/models/Note.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; -import { api, initTestDb, post, signup, uploadFile, uploadUrl } from '../utils.js'; +import { api, initTestDb, post, role, signup, uploadFile, uploadUrl } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Note', () => { let Notes: any; + let root: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse; let tom: misskey.entities.SignupResponse; @@ -21,6 +22,7 @@ describe('Note', () => { beforeAll(async () => { const connection = await initTestDb(true); Notes = connection.getRepository(MiNote); + root = await signup({ username: 'root' }); alice = await signup({ username: 'alice' }); bob = await signup({ username: 'bob' }); tom = await signup({ username: 'tom', host: 'example.com' }); @@ -473,14 +475,14 @@ describe('Note', () => { value: true, }, } as any, - }, alice); + }, root); assert.strictEqual(res.status, 200); const assign = await api('admin/roles/assign', { userId: alice.id, roleId: res.body.id, - }, alice); + }, root); assert.strictEqual(assign.status, 204); assert.strictEqual(file.body!.isSensitive, false); @@ -508,11 +510,11 @@ describe('Note', () => { await api('admin/roles/unassign', { userId: alice.id, roleId: res.body.id, - }); + }, root); await api('admin/roles/delete', { roleId: res.body.id, - }, alice); + }, root); }); }); @@ -644,7 +646,7 @@ describe('Note', () => { sensitiveWords: [ 'test', ], - }, alice); + }, root); assert.strictEqual(sensitive.status, 204); @@ -663,7 +665,7 @@ describe('Note', () => { sensitiveWords: [ '/Test/i', ], - }, alice); + }, root); assert.strictEqual(sensitive.status, 204); @@ -680,7 +682,7 @@ describe('Note', () => { sensitiveWords: [ 'Test hoge', ], - }, alice); + }, root); assert.strictEqual(sensitive.status, 204); @@ -697,7 +699,7 @@ describe('Note', () => { prohibitedWords: [ 'test', ], - }, alice); + }, root); assert.strictEqual(prohibited.status, 204); @@ -716,7 +718,7 @@ describe('Note', () => { prohibitedWords: [ '/Test/i', ], - }, alice); + }, root); assert.strictEqual(prohibited.status, 204); @@ -733,7 +735,7 @@ describe('Note', () => { prohibitedWords: [ 'Test hoge', ], - }, alice); + }, root); assert.strictEqual(prohibited.status, 204); @@ -750,7 +752,7 @@ describe('Note', () => { prohibitedWords: [ 'test', ], - }, alice); + }, root); assert.strictEqual(prohibited.status, 204); @@ -785,7 +787,7 @@ describe('Note', () => { value: 0, }, } as any, - }, alice); + }, root); assert.strictEqual(res.status, 200); @@ -794,7 +796,7 @@ describe('Note', () => { const assign = await api('admin/roles/assign', { userId: alice.id, roleId: res.body.id, - }, alice); + }, root); assert.strictEqual(assign.status, 204); @@ -810,11 +812,11 @@ describe('Note', () => { await api('admin/roles/unassign', { userId: alice.id, roleId: res.body.id, - }); + }, root); await api('admin/roles/delete', { roleId: res.body.id, - }, alice); + }, root); }); test('ダイレクト投稿もエラーになる', async () => { @@ -839,7 +841,7 @@ describe('Note', () => { value: 0, }, } as any, - }, alice); + }, root); assert.strictEqual(res.status, 200); @@ -848,7 +850,7 @@ describe('Note', () => { const assign = await api('admin/roles/assign', { userId: alice.id, roleId: res.body.id, - }, alice); + }, root); assert.strictEqual(assign.status, 204); @@ -866,11 +868,11 @@ describe('Note', () => { await api('admin/roles/unassign', { userId: alice.id, roleId: res.body.id, - }); + }, root); await api('admin/roles/delete', { roleId: res.body.id, - }, alice); + }, root); }); test('ダイレクトの宛先とメンションが同じ場合は重複してカウントしない', async () => { @@ -895,7 +897,7 @@ describe('Note', () => { value: 1, }, } as any, - }, alice); + }, root); assert.strictEqual(res.status, 200); @@ -904,7 +906,7 @@ describe('Note', () => { const assign = await api('admin/roles/assign', { userId: alice.id, roleId: res.body.id, - }, alice); + }, root); assert.strictEqual(assign.status, 204); @@ -921,11 +923,11 @@ describe('Note', () => { await api('admin/roles/unassign', { userId: alice.id, roleId: res.body.id, - }); + }, root); await api('admin/roles/delete', { roleId: res.body.id, - }, alice); + }, root); }); }); @@ -960,4 +962,61 @@ describe('Note', () => { assert.strictEqual(mainNote.repliesCount, 0); }); }); + + describe('notes/translate', () => { + describe('翻訳機能の利用が許可されていない場合', () => { + let cannotTranslateRole: misskey.entities.Role; + + beforeAll(async () => { + cannotTranslateRole = await role(root, {}, { canUseTranslator: false }); + await api('admin/roles/assign', { roleId: cannotTranslateRole.id, userId: alice.id }, root); + }); + + test('翻訳機能の利用が許可されていない場合翻訳できない', async () => { + const aliceNote = await post(alice, { text: 'Hello' }); + const res = await api('notes/translate', { + noteId: aliceNote.id, + targetLang: 'ja', + }, alice); + + assert.strictEqual(res.status, 400); + assert.strictEqual(res.body.error.code, 'UNAVAILABLE'); + }); + + afterAll(async () => { + await api('admin/roles/unassign', { roleId: cannotTranslateRole.id, userId: alice.id }, root); + }); + }); + + test('存在しないノートは翻訳できない', async () => { + const res = await api('notes/translate', { noteId: 'foo', targetLang: 'ja' }, alice); + + assert.strictEqual(res.status, 400); + assert.strictEqual(res.body.error.code, 'NO_SUCH_NOTE'); + }); + + test('不可視なノートは翻訳できない', async () => { + const aliceNote = await post(alice, { visibility: 'followers', text: 'Hello' }); + const bobTranslateAttempt = await api('notes/translate', { noteId: aliceNote.id, targetLang: 'ja' }, bob); + + assert.strictEqual(bobTranslateAttempt.status, 400); + assert.strictEqual(bobTranslateAttempt.body.error.code, 'CANNOT_TRANSLATE_INVISIBLE_NOTE'); + }); + + test('text: null なノートを翻訳すると空のレスポンスが返ってくる', async () => { + const aliceNote = await post(alice, { text: null, poll: { choices: ['kinoko', 'takenoko'] } }); + const res = await api('notes/translate', { noteId: aliceNote.id, targetLang: 'ja' }, alice); + + assert.strictEqual(res.status, 204); + }); + + test('サーバーに DeepL 認証キーが登録されていない場合翻訳できない', async () => { + const aliceNote = await post(alice, { text: 'Hello' }); + const res = await api('notes/translate', { noteId: aliceNote.id, targetLang: 'ja' }, alice); + + // NOTE: デフォルトでは登録されていないので落ちる + assert.strictEqual(res.status, 400); + assert.strictEqual(res.body.error.code, 'UNAVAILABLE'); + }); + }); }); diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 4b2ad16b0f..b6b26c000c 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -21864,6 +21864,10 @@ export type operations = { }; }; }; + /** @description OK (without any results) */ + 204: { + content: never; + }; /** @description Client error */ 400: { content: { From 2a851437ffcd8778d157a6841875f03330c994b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?= <46447427+samunohito@users.noreply.github.com> Date: Sat, 30 Mar 2024 15:28:19 +0900 Subject: [PATCH 03/19] =?UTF-8?q?fix:=20misskey-js=E3=80=81bubble-game?= =?UTF-8?q?=E3=80=81reversi=E3=81=AE=E3=83=93=E3=83=AB=E3=83=89=E3=82=92es?= =?UTF-8?q?build=E3=81=AB=E7=B5=B1=E5=90=88=E3=81=99=E3=82=8B=20(#13600)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: ビルドが遅いパッケージのビルド速度を改善 * dependenciesの整理 * fix ci * ビルド開始時に古いファイルを消す * fix ci * fix ci --- .github/workflows/lint.yml | 2 +- package.json | 4 +- packages/backend/.swcrc | 3 +- packages/misskey-bubble-game/.eslintignore | 1 + packages/misskey-bubble-game/build.js | 114 ++++++++++--- packages/misskey-bubble-game/package.json | 26 ++- packages/misskey-bubble-game/src/index.ts | 6 +- packages/misskey-bubble-game/tsconfig.json | 2 +- packages/misskey-js/.eslintignore | 1 + packages/misskey-js/api-extractor.json | 2 +- packages/misskey-js/build.js | 105 ++++++++++++ packages/misskey-js/package.json | 29 ++-- packages/misskey-js/src/api.ts | 2 +- packages/misskey-js/src/index.ts | 15 +- packages/misskey-js/tsconfig.json | 2 +- packages/misskey-reversi/.eslintignore | 1 + packages/misskey-reversi/build.js | 114 ++++++++++--- packages/misskey-reversi/package.json | 26 ++- packages/misskey-reversi/tsconfig.json | 2 +- pnpm-lock.yaml | 188 ++++----------------- scripts/dev.mjs | 57 ++++--- 21 files changed, 421 insertions(+), 281 deletions(-) create mode 100644 packages/misskey-js/build.js diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 31e974edaa..9b3f85fe1d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -92,6 +92,6 @@ jobs: - run: pnpm i --frozen-lockfile - run: pnpm --filter misskey-js run build if: ${{ matrix.workspace == 'backend' }} - - run: pnpm --filter misskey-reversi run build:tsc + - run: pnpm --filter misskey-reversi run build if: ${{ matrix.workspace == 'backend' }} - run: pnpm --filter ${{ matrix.workspace }} run typecheck diff --git a/package.json b/package.json index 8f5ab0b124..84d6db5124 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,9 @@ "postcss": "8.4.35", "tar": "6.2.0", "terser": "5.28.1", - "typescript": "5.3.3" + "typescript": "5.3.3", + "esbuild": "0.19.11", + "glob": "10.3.10" }, "devDependencies": { "@types/node": "^20.11.28", diff --git a/packages/backend/.swcrc b/packages/backend/.swcrc index 0504a2d389..845190b5f4 100644 --- a/packages/backend/.swcrc +++ b/packages/backend/.swcrc @@ -19,5 +19,6 @@ }, "target": "es2022" }, - "minify": false + "minify": false, + "sourceMaps": "inline" } diff --git a/packages/misskey-bubble-game/.eslintignore b/packages/misskey-bubble-game/.eslintignore index f22128f047..52ea8b3362 100644 --- a/packages/misskey-bubble-game/.eslintignore +++ b/packages/misskey-bubble-game/.eslintignore @@ -5,3 +5,4 @@ node_modules /jest.config.ts /test /test-d +build.js diff --git a/packages/misskey-bubble-game/build.js b/packages/misskey-bubble-game/build.js index 4744dfaf7b..0b79f4b915 100644 --- a/packages/misskey-bubble-game/build.js +++ b/packages/misskey-bubble-game/build.js @@ -1,31 +1,105 @@ +import * as esbuild from "esbuild"; import { build } from "esbuild"; import { globSync } from "glob"; +import { execa } from "execa"; +import fs from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname } from "node:path"; + +const _filename = fileURLToPath(import.meta.url); +const _dirname = dirname(_filename); +const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); const entryPoints = globSync("./src/**/**.{ts,tsx}"); /** @type {import('esbuild').BuildOptions} */ const options = { - entryPoints, - minify: true, - outdir: "./built/esm", - target: "es2022", - platform: "browser", - format: "esm", + entryPoints, + minify: process.env.NODE_ENV === 'production', + outdir: "./built", + target: "es2022", + platform: "browser", + format: "esm", + sourcemap: 'linked', }; -if (process.env.WATCH === "true") { - options.watch = { - onRebuild(error, result) { - if (error) { - console.error("watch build failed:", error); - } else { - console.log("watch build succeeded:", result); - } - }, - }; +// built配下をすべて削除する +fs.rmSync('./built', { recursive: true, force: true }); + +if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) { + await watchSrc(); +} else { + await buildSrc(); } -build(options).catch((err) => { - process.stderr.write(err.stderr); - process.exit(1); -}); +async function buildSrc() { + console.log(`[${_package.name}] start building...`); + + await build(options) + .then(it => { + console.log(`[${_package.name}] build succeeded.`); + }) + .catch((err) => { + process.stderr.write(err.stderr); + process.exit(1); + }); + + if (process.env.NODE_ENV === 'production') { + console.log(`[${_package.name}] skip building d.ts because NODE_ENV is production.`); + } else { + await buildDts(); + } + + console.log(`[${_package.name}] finish building.`); +} + +function buildDts() { + return execa( + 'tsc', + [ + '--project', 'tsconfig.json', + '--outDir', 'built', + '--declaration', 'true', + '--emitDeclarationOnly', 'true', + ], + { + stdout: process.stdout, + stderr: process.stderr, + } + ); +} + +async function watchSrc() { + const plugins = [{ + name: 'gen-dts', + setup(build) { + build.onStart(() => { + console.log(`[${_package.name}] detect changed...`); + }); + build.onEnd(async result => { + if (result.errors.length > 0) { + console.error(`[${_package.name}] watch build failed:`, result); + return; + } + await buildDts(); + }); + }, + }]; + + console.log(`[${_package.name}] start watching...`) + + const context = await esbuild.context({ ...options, plugins }); + await context.watch(); + + await new Promise((resolve, reject) => { + process.on('SIGHUP', resolve); + process.on('SIGINT', resolve); + process.on('SIGTERM', resolve); + process.on('SIGKILL', resolve); + process.on('uncaughtException', reject); + process.on('exit', resolve); + }).finally(async () => { + await context.dispose(); + console.log(`[${_package.name}] finish watching.`); + }); +} diff --git a/packages/misskey-bubble-game/package.json b/packages/misskey-bubble-game/package.json index ddc4c2134b..a3aad147a9 100644 --- a/packages/misskey-bubble-game/package.json +++ b/packages/misskey-bubble-game/package.json @@ -2,24 +2,21 @@ "type": "module", "name": "misskey-bubble-game", "version": "0.0.1", - "types": "./built/dts/index.d.ts", + "main": "./built/index.js", + "types": "./built/index.d.ts", "exports": { ".": { - "import": "./built/esm/index.js", - "types": "./built/dts/index.d.ts" + "import": "./built/index.js", + "types": "./built/index.d.ts" }, "./*": { - "import": "./built/esm/*", - "types": "./built/dts/*" + "import": "./built/*", + "types": "./built/*" } }, "scripts": { "build": "node ./build.js", - "build:tsc": "npm run tsc", - "tsc": "npm run tsc-esm && npm run tsc-dts", - "tsc-esm": "tsc --outDir built/esm", - "tsc-dts": "tsc --outDir built/dts --declaration true --emitDeclarationOnly true --declarationMap true", - "watch": "nodemon -w src -e ts,js,cjs,mjs,json --exec \"pnpm run build:tsc\"", + "watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"", "eslint": "eslint . --ext .js,.jsx,.ts,.tsx", "typecheck": "tsc --noEmit", "lint": "pnpm typecheck && pnpm eslint" @@ -27,21 +24,22 @@ "devDependencies": { "@misskey-dev/eslint-plugin": "1.0.0", "@types/matter-js": "0.19.6", - "@types/node": "20.11.5", "@types/seedrandom": "3.0.8", + "@types/node": "20.11.5", "@typescript-eslint/eslint-plugin": "7.1.0", "@typescript-eslint/parser": "7.1.0", "eslint": "8.57.0", "nodemon": "3.0.2", - "typescript": "5.3.3" + "execa": "8.0.1", + "typescript": "5.3.3", + "esbuild": "0.19.11", + "glob": "10.3.10" }, "files": [ "built" ], "dependencies": { - "esbuild": "0.19.11", "eventemitter3": "5.0.1", - "glob": "^10.3.10", "matter-js": "0.19.0", "seedrandom": "3.0.5" } diff --git a/packages/misskey-bubble-game/src/index.ts b/packages/misskey-bubble-game/src/index.ts index 004a7d008e..c5f1f68062 100644 --- a/packages/misskey-bubble-game/src/index.ts +++ b/packages/misskey-bubble-game/src/index.ts @@ -6,5 +6,9 @@ import { DropAndFusionGame, Mono } from './game.js'; export { - DropAndFusionGame, Mono, + DropAndFusionGame, +}; + +export type { + Mono, }; diff --git a/packages/misskey-bubble-game/tsconfig.json b/packages/misskey-bubble-game/tsconfig.json index f56b65e868..6e34e332e0 100644 --- a/packages/misskey-bubble-game/tsconfig.json +++ b/packages/misskey-bubble-game/tsconfig.json @@ -6,7 +6,7 @@ "moduleResolution": "nodenext", "declaration": true, "declarationMap": true, - "sourceMap": true, + "sourceMap": false, "outDir": "./built/", "removeComments": true, "strict": true, diff --git a/packages/misskey-js/.eslintignore b/packages/misskey-js/.eslintignore index f22128f047..52ea8b3362 100644 --- a/packages/misskey-js/.eslintignore +++ b/packages/misskey-js/.eslintignore @@ -5,3 +5,4 @@ node_modules /jest.config.ts /test /test-d +build.js diff --git a/packages/misskey-js/api-extractor.json b/packages/misskey-js/api-extractor.json index f80d0f20a8..a95281a6d5 100644 --- a/packages/misskey-js/api-extractor.json +++ b/packages/misskey-js/api-extractor.json @@ -45,7 +45,7 @@ * * SUPPORTED TOKENS: , , */ - "mainEntryPointFilePath": "/built/dts/index.d.ts", + "mainEntryPointFilePath": "/built/index.d.ts", /** * A list of NPM package names whose exports should be treated as part of this package. diff --git a/packages/misskey-js/build.js b/packages/misskey-js/build.js new file mode 100644 index 0000000000..0b79f4b915 --- /dev/null +++ b/packages/misskey-js/build.js @@ -0,0 +1,105 @@ +import * as esbuild from "esbuild"; +import { build } from "esbuild"; +import { globSync } from "glob"; +import { execa } from "execa"; +import fs from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname } from "node:path"; + +const _filename = fileURLToPath(import.meta.url); +const _dirname = dirname(_filename); +const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); + +const entryPoints = globSync("./src/**/**.{ts,tsx}"); + +/** @type {import('esbuild').BuildOptions} */ +const options = { + entryPoints, + minify: process.env.NODE_ENV === 'production', + outdir: "./built", + target: "es2022", + platform: "browser", + format: "esm", + sourcemap: 'linked', +}; + +// built配下をすべて削除する +fs.rmSync('./built', { recursive: true, force: true }); + +if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) { + await watchSrc(); +} else { + await buildSrc(); +} + +async function buildSrc() { + console.log(`[${_package.name}] start building...`); + + await build(options) + .then(it => { + console.log(`[${_package.name}] build succeeded.`); + }) + .catch((err) => { + process.stderr.write(err.stderr); + process.exit(1); + }); + + if (process.env.NODE_ENV === 'production') { + console.log(`[${_package.name}] skip building d.ts because NODE_ENV is production.`); + } else { + await buildDts(); + } + + console.log(`[${_package.name}] finish building.`); +} + +function buildDts() { + return execa( + 'tsc', + [ + '--project', 'tsconfig.json', + '--outDir', 'built', + '--declaration', 'true', + '--emitDeclarationOnly', 'true', + ], + { + stdout: process.stdout, + stderr: process.stderr, + } + ); +} + +async function watchSrc() { + const plugins = [{ + name: 'gen-dts', + setup(build) { + build.onStart(() => { + console.log(`[${_package.name}] detect changed...`); + }); + build.onEnd(async result => { + if (result.errors.length > 0) { + console.error(`[${_package.name}] watch build failed:`, result); + return; + } + await buildDts(); + }); + }, + }]; + + console.log(`[${_package.name}] start watching...`) + + const context = await esbuild.context({ ...options, plugins }); + await context.watch(); + + await new Promise((resolve, reject) => { + process.on('SIGHUP', resolve); + process.on('SIGINT', resolve); + process.on('SIGTERM', resolve); + process.on('SIGKILL', resolve); + process.on('uncaughtException', reject); + process.on('exit', resolve); + }).finally(async () => { + await context.dispose(); + console.log(`[${_package.name}] finish watching.`); + }); +} diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 772f001c07..a9c75c95c2 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -3,23 +3,21 @@ "name": "misskey-js", "version": "2024.3.1", "description": "Misskey SDK for JavaScript", - "types": "./built/dts/index.d.ts", + "main": "./built/index.js", + "types": "./built/index.d.ts", "exports": { ".": { - "import": "./built/esm/index.js", - "types": "./built/dts/index.d.ts" + "import": "./built/index.js", + "types": "./built/index.d.ts" }, "./*": { - "import": "./built/esm/*", - "types": "./built/dts/*" + "import": "./built/*", + "types": "./built/*" } }, "scripts": { - "build": "npm run ts", - "ts": "npm run ts-esm && npm run ts-dts", - "ts-esm": "tsc --outDir built/esm", - "ts-dts": "tsc --outDir built/dts --declaration true --emitDeclarationOnly true --declarationMap true", - "watch": "nodemon -w src -e ts,js,cjs,mjs,json --exec \"pnpm run ts\"", + "build": "node ./build.js", + "watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"", "tsd": "tsd", "api": "pnpm api-extractor run --local --verbose", "api-prod": "pnpm api-extractor run --verbose", @@ -49,17 +47,16 @@ "mock-socket": "9.3.1", "ncp": "2.0.0", "nodemon": "3.1.0", + "execa": "8.0.1", "tsd": "0.30.7", - "typescript": "5.3.3" + "typescript": "5.3.3", + "esbuild": "0.19.11", + "glob": "10.3.10" }, "files": [ - "built", - "built/esm", - "built/dts" + "built" ], "dependencies": { - "@swc/cli": "0.1.63", - "@swc/core": "1.3.105", "eventemitter3": "5.0.1", "reconnecting-websocket": "4.4.0" } diff --git a/packages/misskey-js/src/api.ts b/packages/misskey-js/src/api.ts index 134ead0d79..959a634a74 100644 --- a/packages/misskey-js/src/api.ts +++ b/packages/misskey-js/src/api.ts @@ -3,7 +3,7 @@ import './autogen/apiClientJSDoc.js'; import { SwitchCaseResponseType } from './api.types.js'; import type { Endpoints } from './api.types.js'; -export { +export type { SwitchCaseResponseType, } from './api.types.js'; diff --git a/packages/misskey-js/src/index.ts b/packages/misskey-js/src/index.ts index 54cae8ec03..28007a8ade 100644 --- a/packages/misskey-js/src/index.ts +++ b/packages/misskey-js/src/index.ts @@ -1,17 +1,20 @@ -import { Endpoints } from './api.types.js'; +import { type Endpoints } from './api.types.js'; import Stream, { Connection } from './streaming.js'; -import { Channels } from './streaming.types.js'; -import { Acct } from './acct.js'; +import { type Channels } from './streaming.types.js'; +import { type Acct } from './acct.js'; import * as consts from './consts.js'; -export { +export type { Endpoints, - Stream, - Connection as ChannelConnection, Channels, Acct, }; +export { + Stream, + Connection as ChannelConnection, +}; + export const permissions = consts.permissions; export const notificationTypes = consts.notificationTypes; export const noteVisibilities = consts.noteVisibilities; diff --git a/packages/misskey-js/tsconfig.json b/packages/misskey-js/tsconfig.json index f56b65e868..6e34e332e0 100644 --- a/packages/misskey-js/tsconfig.json +++ b/packages/misskey-js/tsconfig.json @@ -6,7 +6,7 @@ "moduleResolution": "nodenext", "declaration": true, "declarationMap": true, - "sourceMap": true, + "sourceMap": false, "outDir": "./built/", "removeComments": true, "strict": true, diff --git a/packages/misskey-reversi/.eslintignore b/packages/misskey-reversi/.eslintignore index f22128f047..52ea8b3362 100644 --- a/packages/misskey-reversi/.eslintignore +++ b/packages/misskey-reversi/.eslintignore @@ -5,3 +5,4 @@ node_modules /jest.config.ts /test /test-d +build.js diff --git a/packages/misskey-reversi/build.js b/packages/misskey-reversi/build.js index 4744dfaf7b..0b79f4b915 100644 --- a/packages/misskey-reversi/build.js +++ b/packages/misskey-reversi/build.js @@ -1,31 +1,105 @@ +import * as esbuild from "esbuild"; import { build } from "esbuild"; import { globSync } from "glob"; +import { execa } from "execa"; +import fs from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname } from "node:path"; + +const _filename = fileURLToPath(import.meta.url); +const _dirname = dirname(_filename); +const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); const entryPoints = globSync("./src/**/**.{ts,tsx}"); /** @type {import('esbuild').BuildOptions} */ const options = { - entryPoints, - minify: true, - outdir: "./built/esm", - target: "es2022", - platform: "browser", - format: "esm", + entryPoints, + minify: process.env.NODE_ENV === 'production', + outdir: "./built", + target: "es2022", + platform: "browser", + format: "esm", + sourcemap: 'linked', }; -if (process.env.WATCH === "true") { - options.watch = { - onRebuild(error, result) { - if (error) { - console.error("watch build failed:", error); - } else { - console.log("watch build succeeded:", result); - } - }, - }; +// built配下をすべて削除する +fs.rmSync('./built', { recursive: true, force: true }); + +if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) { + await watchSrc(); +} else { + await buildSrc(); } -build(options).catch((err) => { - process.stderr.write(err.stderr); - process.exit(1); -}); +async function buildSrc() { + console.log(`[${_package.name}] start building...`); + + await build(options) + .then(it => { + console.log(`[${_package.name}] build succeeded.`); + }) + .catch((err) => { + process.stderr.write(err.stderr); + process.exit(1); + }); + + if (process.env.NODE_ENV === 'production') { + console.log(`[${_package.name}] skip building d.ts because NODE_ENV is production.`); + } else { + await buildDts(); + } + + console.log(`[${_package.name}] finish building.`); +} + +function buildDts() { + return execa( + 'tsc', + [ + '--project', 'tsconfig.json', + '--outDir', 'built', + '--declaration', 'true', + '--emitDeclarationOnly', 'true', + ], + { + stdout: process.stdout, + stderr: process.stderr, + } + ); +} + +async function watchSrc() { + const plugins = [{ + name: 'gen-dts', + setup(build) { + build.onStart(() => { + console.log(`[${_package.name}] detect changed...`); + }); + build.onEnd(async result => { + if (result.errors.length > 0) { + console.error(`[${_package.name}] watch build failed:`, result); + return; + } + await buildDts(); + }); + }, + }]; + + console.log(`[${_package.name}] start watching...`) + + const context = await esbuild.context({ ...options, plugins }); + await context.watch(); + + await new Promise((resolve, reject) => { + process.on('SIGHUP', resolve); + process.on('SIGINT', resolve); + process.on('SIGTERM', resolve); + process.on('SIGKILL', resolve); + process.on('uncaughtException', reject); + process.on('exit', resolve); + }).finally(async () => { + await context.dispose(); + console.log(`[${_package.name}] finish watching.`); + }); +} diff --git a/packages/misskey-reversi/package.json b/packages/misskey-reversi/package.json index 7bfc890fef..45a6120861 100644 --- a/packages/misskey-reversi/package.json +++ b/packages/misskey-reversi/package.json @@ -2,24 +2,21 @@ "type": "module", "name": "misskey-reversi", "version": "0.0.1", - "types": "./built/dts/index.d.ts", + "main": "./built/index.js", + "types": "./built/index.d.ts", "exports": { ".": { - "import": "./built/esm/index.js", - "types": "./built/dts/index.d.ts" + "import": "./built/index.js", + "types": "./built/index.d.ts" }, "./*": { - "import": "./built/esm/*", - "types": "./built/dts/*" + "import": "./built/*", + "types": "./built/*" } }, "scripts": { "build": "node ./build.js", - "build:tsc": "npm run tsc", - "tsc": "npm run tsc-esm && npm run tsc-dts", - "tsc-esm": "tsc --outDir built/esm", - "tsc-dts": "tsc --outDir built/dts --declaration true --emitDeclarationOnly true --declarationMap true", - "watch": "nodemon -w src -e ts,js,cjs,mjs,json --exec \"pnpm run build:tsc\"", + "watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"", "eslint": "eslint . --ext .js,.jsx,.ts,.tsx", "typecheck": "tsc --noEmit", "lint": "pnpm typecheck && pnpm eslint" @@ -30,15 +27,16 @@ "@typescript-eslint/eslint-plugin": "7.1.0", "@typescript-eslint/parser": "7.1.0", "eslint": "8.57.0", + "execa": "8.0.1", "nodemon": "3.0.2", - "typescript": "5.3.3" + "typescript": "5.3.3", + "esbuild": "0.19.11", + "glob": "10.3.10" }, "files": [ "built" ], "dependencies": { - "crc-32": "1.2.2", - "esbuild": "0.19.11", - "glob": "10.3.10" + "crc-32": "1.2.2" } } diff --git a/packages/misskey-reversi/tsconfig.json b/packages/misskey-reversi/tsconfig.json index f56b65e868..6e34e332e0 100644 --- a/packages/misskey-reversi/tsconfig.json +++ b/packages/misskey-reversi/tsconfig.json @@ -6,7 +6,7 @@ "moduleResolution": "nodenext", "declaration": true, "declarationMap": true, - "sourceMap": true, + "sourceMap": false, "outDir": "./built/", "removeComments": true, "strict": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 383b31b1f3..46512784c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,12 +15,18 @@ importers: cssnano: specifier: 6.0.5 version: 6.0.5(postcss@8.4.35) + esbuild: + specifier: 0.19.11 + version: 0.19.11 execa: specifier: 8.0.1 version: 8.0.1 fast-glob: specifier: 3.3.2 version: 3.3.2 + glob: + specifier: 10.3.10 + version: 10.3.10 ignore-walk: specifier: 6.0.4 version: 6.0.4 @@ -1037,15 +1043,9 @@ importers: packages/misskey-bubble-game: dependencies: - esbuild: - specifier: 0.19.11 - version: 0.19.11 eventemitter3: specifier: 5.0.1 version: 5.0.1 - glob: - specifier: ^10.3.10 - version: 10.3.10 matter-js: specifier: 0.19.0 version: 0.19.0 @@ -1071,9 +1071,18 @@ importers: '@typescript-eslint/parser': specifier: 7.1.0 version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) + esbuild: + specifier: 0.19.11 + version: 0.19.11 eslint: specifier: 8.57.0 version: 8.57.0 + execa: + specifier: 8.0.1 + version: 8.0.1 + glob: + specifier: 10.3.10 + version: 10.3.10 nodemon: specifier: 3.0.2 version: 3.0.2 @@ -1083,12 +1092,6 @@ importers: packages/misskey-js: dependencies: - '@swc/cli': - specifier: 0.1.63 - version: 0.1.63(@swc/core@1.3.105) - '@swc/core': - specifier: 1.3.105 - version: 1.3.105 eventemitter3: specifier: 5.0.1 version: 5.0.1 @@ -1104,7 +1107,7 @@ importers: version: 1.0.0(@typescript-eslint/eslint-plugin@7.1.0)(@typescript-eslint/parser@7.1.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) '@swc/jest': specifier: 0.2.31 - version: 0.2.31(@swc/core@1.3.105) + version: 0.2.31(@swc/core@1.3.107) '@types/jest': specifier: 29.5.12 version: 29.5.12 @@ -1117,9 +1120,18 @@ importers: '@typescript-eslint/parser': specifier: 7.1.0 version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) + esbuild: + specifier: 0.19.11 + version: 0.19.11 eslint: specifier: 8.57.0 version: 8.57.0 + execa: + specifier: 8.0.1 + version: 8.0.1 + glob: + specifier: 10.3.10 + version: 10.3.10 jest: specifier: 29.7.0 version: 29.7.0(@types/node@20.11.22) @@ -1186,12 +1198,6 @@ importers: crc-32: specifier: 1.2.2 version: 1.2.2 - esbuild: - specifier: 0.19.11 - version: 0.19.11 - glob: - specifier: 10.3.10 - version: 10.3.10 devDependencies: '@misskey-dev/eslint-plugin': specifier: 1.0.0 @@ -1205,9 +1211,18 @@ importers: '@typescript-eslint/parser': specifier: 7.1.0 version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) + esbuild: + specifier: 0.19.11 + version: 0.19.11 eslint: specifier: 8.57.0 version: 8.57.0 + execa: + specifier: 8.0.1 + version: 8.0.1 + glob: + specifier: 10.3.10 + version: 10.3.10 nodemon: specifier: 3.0.2 version: 3.0.2 @@ -6669,26 +6684,6 @@ packages: - supports-color dev: true - /@swc/cli@0.1.63(@swc/core@1.3.105): - resolution: {integrity: sha512-EM9oxxHzmmsprYRbGqsS2M4M/Gr5Gkcl0ROYYIdlUyTkhOiX822EQiRCpPCwdutdnzH2GyaTN7wc6i0Y+CKd3A==} - engines: {node: '>= 12.13'} - hasBin: true - peerDependencies: - '@swc/core': ^1.2.66 - chokidar: 3.5.3 - peerDependenciesMeta: - chokidar: - optional: true - dependencies: - '@mole-inc/bin-wrapper': 8.0.1 - '@swc/core': 1.3.105 - commander: 7.2.0 - fast-glob: 3.3.2 - semver: 7.5.4 - slash: 3.0.0 - source-map: 0.7.4 - dev: false - /@swc/cli@0.1.63(@swc/core@1.3.107)(chokidar@3.5.3): resolution: {integrity: sha512-EM9oxxHzmmsprYRbGqsS2M4M/Gr5Gkcl0ROYYIdlUyTkhOiX822EQiRCpPCwdutdnzH2GyaTN7wc6i0Y+CKd3A==} engines: {node: '>= 12.13'} @@ -6721,14 +6716,6 @@ packages: dev: false optional: true - /@swc/core-darwin-arm64@1.3.105: - resolution: {integrity: sha512-buWeweLVDXXmcnfIemH4PGnpjwsDTUGitnPchdftb0u1FU8zSSP/lw/pUCBDG/XvWAp7c/aFxgN4CyG0j7eayA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - /@swc/core-darwin-arm64@1.3.107: resolution: {integrity: sha512-47tD/5vSXWxPd0j/ZllyQUg4bqalbQTsmqSw0J4dDdS82MWqCAwUErUrAZPRjBkjNQ6Kmrf5rpCWaGTtPw+ngw==} engines: {node: '>=10'} @@ -6746,14 +6733,6 @@ packages: dev: false optional: true - /@swc/core-darwin-x64@1.3.105: - resolution: {integrity: sha512-hFmXPApqjA/8sy/9NpljHVaKi1OvL9QkJ2MbbTCCbJERuHMpMUeMBUWipHRfepGHFhU+9B9zkEup/qJaJR4XIg==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - /@swc/core-darwin-x64@1.3.107: resolution: {integrity: sha512-hwiLJ2ulNkBGAh1m1eTfeY1417OAYbRGcb/iGsJ+LuVLvKAhU/itzsl535CvcwAlt2LayeCFfcI8gdeOLeZa9A==} engines: {node: '>=10'} @@ -6782,14 +6761,6 @@ packages: dev: false optional: true - /@swc/core-linux-arm-gnueabihf@1.3.105: - resolution: {integrity: sha512-mwXyMC41oMKkKrPpL8uJpOxw7fyfQoVtIw3Y5p0Blabk+espNYqix0E8VymHdRKuLmM//z5wVmMsuHdGBHvZeg==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - /@swc/core-linux-arm-gnueabihf@1.3.107: resolution: {integrity: sha512-I2wzcC0KXqh0OwymCmYwNRgZ9nxX7DWnOOStJXV3pS0uB83TXAkmqd7wvMBuIl9qu4Hfomi9aDM7IlEEn9tumQ==} engines: {node: '>=10'} @@ -6807,14 +6778,6 @@ packages: dev: false optional: true - /@swc/core-linux-arm64-gnu@1.3.105: - resolution: {integrity: sha512-H7yEIVydnUtqBSUxwmO6vpIQn7j+Rr0DF6ZOORPyd/SFzQJK9cJRtmJQ3ZMzlJ1Bb+1gr3MvjgLEnmyCYEm2Hg==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - /@swc/core-linux-arm64-gnu@1.3.107: resolution: {integrity: sha512-HWgnn7JORYlOYnGsdunpSF8A+BCZKPLzLtEUA27/M/ZuANcMZabKL9Zurt7XQXq888uJFAt98Gy+59PU90aHKg==} engines: {node: '>=10'} @@ -6832,14 +6795,6 @@ packages: dev: false optional: true - /@swc/core-linux-arm64-musl@1.3.105: - resolution: {integrity: sha512-Jg7RTFT3pGFdGt5elPV6oDkinRy7q9cXpenjXnJnM2uvx3jOwnsAhexPyCDHom8SHL0j+9kaLLC66T3Gz1E4UA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - /@swc/core-linux-arm64-musl@1.3.107: resolution: {integrity: sha512-vfPF74cWfAm8hyhS8yvYI94ucMHIo8xIYU+oFOW9uvDlGQRgnUf/6DEVbLyt/3yfX5723Ln57U8uiMALbX5Pyw==} engines: {node: '>=10'} @@ -6857,14 +6812,6 @@ packages: dev: false optional: true - /@swc/core-linux-x64-gnu@1.3.105: - resolution: {integrity: sha512-DJghplpyusAmp1X5pW/y93MmS/u83Sx5GrpJxI6KLPa82+NItTgMcl8KBQmW5GYAJpVKZyaIvBanS5TdR8aN2w==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - /@swc/core-linux-x64-gnu@1.3.107: resolution: {integrity: sha512-uBVNhIg0ip8rH9OnOsCARUFZ3Mq3tbPHxtmWk9uAa5u8jQwGWeBx5+nTHpDOVd3YxKb6+5xDEI/edeeLpha/9g==} engines: {node: '>=10'} @@ -6882,14 +6829,6 @@ packages: dev: false optional: true - /@swc/core-linux-x64-musl@1.3.105: - resolution: {integrity: sha512-wD5jL2dZH/5nPNssBo6jhOvkI0lmWnVR4vnOXWjuXgjq1S0AJpO5jdre/6pYLmf26hft3M42bteDnjR4AAZ38w==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - /@swc/core-linux-x64-musl@1.3.107: resolution: {integrity: sha512-mvACkUvzSIB12q1H5JtabWATbk3AG+pQgXEN95AmEX2ZA5gbP9+B+mijsg7Sd/3tboHr7ZHLz/q3SHTvdFJrEw==} engines: {node: '>=10'} @@ -6907,14 +6846,6 @@ packages: dev: false optional: true - /@swc/core-win32-arm64-msvc@1.3.105: - resolution: {integrity: sha512-UqJtwILUHRw2+3UTPnRkZrzM/bGdQtbR4UFdp79mZQYfryeOUVNg7aJj/bWUTkKtLiZ3o+FBNrM/x2X1mJX5bA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - /@swc/core-win32-arm64-msvc@1.3.107: resolution: {integrity: sha512-J3P14Ngy/1qtapzbguEH41kY109t6DFxfbK4Ntz9dOWNuVY3o9/RTB841ctnJk0ZHEG+BjfCJjsD2n8H5HcaOA==} engines: {node: '>=10'} @@ -6932,14 +6863,6 @@ packages: dev: false optional: true - /@swc/core-win32-ia32-msvc@1.3.105: - resolution: {integrity: sha512-Z95C6vZgBEJ1snidYyjVKnVWiy/ZpPiIFIXGWkDr4ZyBgL3eZX12M6LzZ+NApHKffrbO4enbFyFomueBQgS2oA==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - /@swc/core-win32-ia32-msvc@1.3.107: resolution: {integrity: sha512-ZBUtgyjTHlz8TPJh7kfwwwFma+ktr6OccB1oXC8fMSopD0AxVnQasgun3l3099wIsAB9eEsJDQ/3lDkOLs1gBA==} engines: {node: '>=10'} @@ -6957,14 +6880,6 @@ packages: dev: false optional: true - /@swc/core-win32-x64-msvc@1.3.105: - resolution: {integrity: sha512-3J8fkyDPFsS3mszuYUY4Wfk7/B2oio9qXUwF3DzOs2MK+XgdyMLIptIxL7gdfitXJBH8k39uVjrIw1JGJDjyFA==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - /@swc/core-win32-x64-msvc@1.3.107: resolution: {integrity: sha512-Eyzo2XRqWOxqhE1gk9h7LWmUf4Bp4Xn2Ttb0ayAXFp6YSTxQIThXcT9kipXZqcpxcmDwoq8iWbbf2P8XL743EA==} engines: {node: '>=10'} @@ -6982,30 +6897,6 @@ packages: dev: false optional: true - /@swc/core@1.3.105: - resolution: {integrity: sha512-me2VZyr3OjqRpFrYQJJYy7x/zbFSl9nt+MAGnIcBtjDsN00iTVqEaKxBjPBFQV9BDAgPz2SRWes/DhhVm5SmMw==} - engines: {node: '>=10'} - requiresBuild: true - peerDependencies: - '@swc/helpers': ^0.5.0 - peerDependenciesMeta: - '@swc/helpers': - optional: true - dependencies: - '@swc/counter': 0.1.1 - '@swc/types': 0.1.5 - optionalDependencies: - '@swc/core-darwin-arm64': 1.3.105 - '@swc/core-darwin-x64': 1.3.105 - '@swc/core-linux-arm-gnueabihf': 1.3.105 - '@swc/core-linux-arm64-gnu': 1.3.105 - '@swc/core-linux-arm64-musl': 1.3.105 - '@swc/core-linux-x64-gnu': 1.3.105 - '@swc/core-linux-x64-musl': 1.3.105 - '@swc/core-win32-arm64-msvc': 1.3.105 - '@swc/core-win32-ia32-msvc': 1.3.105 - '@swc/core-win32-x64-msvc': 1.3.105 - /@swc/core@1.3.107: resolution: {integrity: sha512-zKhqDyFcTsyLIYK1iEmavljZnf4CCor5pF52UzLAz4B6Nu/4GLU+2LQVAf+oRHjusG39PTPjd2AlRT3f3QWfsQ==} engines: {node: '>=10'} @@ -7033,17 +6924,6 @@ packages: /@swc/counter@0.1.1: resolution: {integrity: sha512-xVRaR4u9hcYjFvcSg71Lz5Bo4//CyjAAfMxa7UsaDSYxAshflUkVJWiyVWrfxC59z2kP1IzI4/1BEpnhI9o3Mw==} - /@swc/jest@0.2.31(@swc/core@1.3.105): - resolution: {integrity: sha512-Gh0Ste380O8KUY1IqsKr+aOvqqs2Loa+WcWWVNwl+lhXqOWK1iTFAP1K0IDfLqAuFP68+D/PxcpBJn21e6Quvw==} - engines: {npm: '>= 7.0.0'} - peerDependencies: - '@swc/core': '*' - dependencies: - '@jest/create-cache-key-function': 29.7.0 - '@swc/core': 1.3.105 - jsonc-parser: 3.2.0 - dev: true - /@swc/jest@0.2.31(@swc/core@1.3.107): resolution: {integrity: sha512-Gh0Ste380O8KUY1IqsKr+aOvqqs2Loa+WcWWVNwl+lhXqOWK1iTFAP1K0IDfLqAuFP68+D/PxcpBJn21e6Quvw==} engines: {npm: '>= 7.0.0'} diff --git a/scripts/dev.mjs b/scripts/dev.mjs index 1ca2c6c2ea..bbb2547758 100644 --- a/scripts/dev.mjs +++ b/scripts/dev.mjs @@ -16,35 +16,36 @@ await execa('pnpm', ['clean'], { stderr: process.stderr, }); -await execa('pnpm', ['build-pre'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -}); +await Promise.all([ + execa('pnpm', ['build-pre'], { + cwd: _dirname + '/../', + stdout: process.stdout, + stderr: process.stderr, + }), + execa('pnpm', ['build-assets'], { + cwd: _dirname + '/../', + stdout: process.stdout, + stderr: process.stderr, + }), + execa('pnpm', ['--filter', 'misskey-js', 'build'], { + cwd: _dirname + '/../', + stdout: process.stdout, + stderr: process.stderr, + }), +]); -await execa('pnpm', ['build-assets'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -}); - -await execa('pnpm', ['--filter', 'misskey-js', 'ts'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -}); - -await execa('pnpm', ['--filter', 'misskey-reversi', 'build:tsc'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -}); - -await execa('pnpm', ['--filter', 'misskey-bubble-game', 'build:tsc'], { - cwd: _dirname + '/../', - stdout: process.stdout, - stderr: process.stderr, -}); +await Promise.all([ + execa('pnpm', ['--filter', 'misskey-reversi', 'build'], { + cwd: _dirname + '/../', + stdout: process.stdout, + stderr: process.stderr, + }), + execa('pnpm', ['--filter', 'misskey-bubble-game', 'build'], { + cwd: _dirname + '/../', + stdout: process.stdout, + stderr: process.stderr, + }), +]); execa('pnpm', ['build-pre', '--watch'], { cwd: _dirname + '/../', From 50da7d2a2728745bcf29cf71fb230c85a1845060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 30 Mar 2024 15:34:05 +0900 Subject: [PATCH 04/19] =?UTF-8?q?enhance(frontend):=202=E8=A6=81=E7=B4=A0?= =?UTF-8?q?=E8=AA=8D=E8=A8=BC=E3=82=BB=E3=83=83=E3=83=88=E3=82=A2=E3=83=83?= =?UTF-8?q?=E3=83=97=E3=82=A6=E3=82=A3=E3=82=B6=E3=83=BC=E3=83=89=E3=81=AB?= =?UTF-8?q?=E3=82=A2=E3=83=97=E3=83=AA=E3=82=92=E8=B5=B7=E5=8B=95=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92=E6=96=B0=E8=A8=AD?= =?UTF-8?q?=20(#13636)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance(frontend): 2要素認証セットアップウィザードにアプリを起動するボタンを新設 * add comment * use css module --- locales/index.d.ts | 10 +++++----- locales/ja-JP.yml | 4 ++-- packages/frontend/src/components/MkButton.vue | 2 ++ .../frontend/src/pages/settings/2fa.qrdialog.vue | 16 +++++++++++++--- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index e1250946f3..428cf9135c 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -4928,6 +4928,10 @@ export interface Locale extends ILocale { * バックアップコードを使う */ "useBackupCode": string; + /** + * アプリを起動 + */ + "launchApp": string; "_bubbleGame": { /** * 遊び方 @@ -7542,13 +7546,9 @@ export interface Locale extends ILocale { */ "step1": ParameterizedString<"a" | "b">; /** - * 次に、表示されているQRコードをアプリでスキャンします。 + * 次に、表示されているQRコードをアプリでスキャンするか、ボタンをクリックして端末上でアプリを開きます。 */ "step2": string; - /** - * QRコードをクリックすると、お使いの端末にインストールされている認証アプリやキーリングに登録できます。 - */ - "step2Click": string; /** * デスクトップアプリを使用する場合は次のURIを入力します */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 1c4df27d92..9e76e420c3 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1228,6 +1228,7 @@ gameRetry: "リトライ" notUsePleaseLeaveBlank: "使用しない場合は空欄にしてください" useTotp: "ワンタイムパスワードを使う" useBackupCode: "バックアップコードを使う" +launchApp: "アプリを起動" _bubbleGame: howToPlay: "遊び方" @@ -1983,8 +1984,7 @@ _2fa: alreadyRegistered: "既に設定は完了しています。" registerTOTP: "認証アプリの設定を開始" step1: "まず、{a}や{b}などの認証アプリをお使いのデバイスにインストールします。" - step2: "次に、表示されているQRコードをアプリでスキャンします。" - step2Click: "QRコードをクリックすると、お使いの端末にインストールされている認証アプリやキーリングに登録できます。" + step2: "次に、表示されているQRコードをアプリでスキャンするか、ボタンをクリックして端末上でアプリを開きます。" step2Uri: "デスクトップアプリを使用する場合は次のURIを入力します" step3Title: "確認コードを入力" step3: "アプリに表示されている確認コード(トークン)を入力します。" diff --git a/packages/frontend/src/components/MkButton.vue b/packages/frontend/src/components/MkButton.vue index 817f1aadf3..3489255b91 100644 --- a/packages/frontend/src/components/MkButton.vue +++ b/packages/frontend/src/components/MkButton.vue @@ -23,6 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only v-else class="_button" :class="[$style.root, { [$style.inline]: inline, [$style.primary]: primary, [$style.gradate]: gradate, [$style.danger]: danger, [$style.rounded]: rounded, [$style.full]: full, [$style.small]: small, [$style.large]: large, [$style.transparent]: transparent, [$style.asLike]: asLike }]" :to="to ?? '#'" + :behavior="linkBehavior" @mousedown="onMousedown" >
@@ -43,6 +44,7 @@ const props = defineProps<{ inline?: boolean; link?: boolean; to?: string; + linkBehavior?: null | 'window' | 'browser'; autofocus?: boolean; wait?: boolean; danger?: boolean; diff --git a/packages/frontend/src/pages/settings/2fa.qrdialog.vue b/packages/frontend/src/pages/settings/2fa.qrdialog.vue index 2ef664b9a3..73253b1ef4 100644 --- a/packages/frontend/src/pages/settings/2fa.qrdialog.vue +++ b/packages/frontend/src/pages/settings/2fa.qrdialog.vue @@ -33,8 +33,12 @@ SPDX-License-Identifier: AGPL-3.0-only Google Authenticator -
{{ i18n.ts._2fa.step2 }}
{{ i18n.ts._2fa.step2Click }}
- +
{{ i18n.ts._2fa.step2 }}
+
+ + +
{{ i18n.ts.launchApp }}
+
@@ -177,8 +181,14 @@ function allDone() { transform: translateX(-50px); } -.qr { +.qrRoot { + display: block; + margin: 0 auto; width: 200px; max-width: 100%; } + +.qr { + width: 100%; +} From b96d9c6973b1c861306fdb9f51256cee5325a2b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 30 Mar 2024 16:02:03 +0900 Subject: [PATCH 05/19] =?UTF-8?q?fix/enhance(frontend):=20=E6=98=A0?= =?UTF-8?q?=E5=83=8F=E3=83=BB=E9=9F=B3=E5=A3=B0=E5=91=A8=E3=82=8A=E3=81=AE?= =?UTF-8?q?=E6=94=B9=E4=BF=AE=20(#13206)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance(frontend): 映像・音声周りの改修 * fix * fix design * fix lint * キーボードショートカットを整備 * Update Changelog * fix * feat: ループ再生 * ネイティブの動作と同期されるように * Update Changelog * key指定を消す --- CHANGELOG.md | 3 + locales/index.d.ts | 18 +++ locales/ja-JP.yml | 7 + .../frontend/src/components/MkMediaAudio.vue | 112 ++++++++++++++- .../frontend/src/components/MkMediaVideo.vue | 131 +++++++++++++++++- packages/frontend/src/components/MkMenu.vue | 91 +++++++++++- .../src/components/MkSwitch.button.vue | 13 +- .../frontend/src/pages/settings/general.vue | 2 + packages/frontend/src/scripts/keycode.ts | 1 + packages/frontend/src/store.ts | 4 + packages/frontend/src/types/menu.ts | 10 +- 11 files changed, 373 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5963549cc6..ebf9320129 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ - Enhance: ページのデザインを変更 - Enhance: 2要素認証(ワンタイムパスワード)の入力欄を改善 - Enhance: 「今日誕生日のフォロー中ユーザー」ウィジェットを手動でリロードできるように +- Enhance: 映像・音声の再生にブラウザのネイティブプレイヤーを使用できるように +- Enhance: 映像・音声の再生メニューに「再生速度」「ループ再生」「ピクチャインピクチャ」を追加 +- Enhance: 映像・音声の再生にキーボードショートカットが使えるように - Fix: 一部のページ内リンクが正しく動作しない問題を修正 - Fix: 周年の実績が閏年を考慮しない問題を修正 - Fix: ローカルURLのプレビューポップアップが左上に表示される diff --git a/locales/index.d.ts b/locales/index.d.ts index 428cf9135c..3dbe46c7b2 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -4932,6 +4932,10 @@ export interface Locale extends ILocale { * アプリを起動 */ "launchApp": string; + /** + * 動画・音声の再生にブラウザのUIを使用する + */ + "useNativeUIForVideoAudioPlayer": string; "_bubbleGame": { /** * 遊び方 @@ -9834,6 +9838,20 @@ export interface Locale extends ILocale { */ "summaryProxyDescription2": string; }; + "_mediaControls": { + /** + * ピクチャインピクチャ + */ + "pip": string; + /** + * 再生速度 + */ + "playbackRate": string; + /** + * ループ再生 + */ + "loop": string; + }; } declare const locales: { [lang: string]: Locale; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 9e76e420c3..aa765d1310 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1229,6 +1229,7 @@ notUsePleaseLeaveBlank: "使用しない場合は空欄にしてください" useTotp: "ワンタイムパスワードを使う" useBackupCode: "バックアップコードを使う" launchApp: "アプリを起動" +useNativeUIForVideoAudioPlayer: "動画・音声の再生にブラウザのUIを使用する" _bubbleGame: howToPlay: "遊び方" @@ -2619,3 +2620,9 @@ _urlPreviewSetting: summaryProxy: "プレビューを生成するプロキシのエンドポイント" summaryProxyDescription: "Misskey本体ではなく、サマリープロキシを使用してプレビューを生成します。" summaryProxyDescription2: "プロキシには下記パラメータがクエリ文字列として連携されます。プロキシ側がこれらをサポートしない場合、設定値は無視されます。" + +_mediaControls: + pip: "ピクチャインピクチャ" + playbackRate: "再生速度" + loop: "ループ再生" + \ No newline at end of file diff --git a/packages/frontend/src/components/MkMediaAudio.vue b/packages/frontend/src/components/MkMediaAudio.vue index 96c9b9fd66..5d2edf467e 100644 --- a/packages/frontend/src/components/MkMediaAudio.vue +++ b/packages/frontend/src/components/MkMediaAudio.vue @@ -5,11 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only