diff --git a/.github/ISSUE_TEMPLATE/01_bug-report.yml b/.github/ISSUE_TEMPLATE/01_bug-report.yml index 959a5871e6..161508c2df 100644 --- a/.github/ISSUE_TEMPLATE/01_bug-report.yml +++ b/.github/ISSUE_TEMPLATE/01_bug-report.yml @@ -54,7 +54,7 @@ body: * Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4 * Browser: Chrome 113.0.5672.126 * Server URL: cherrypick.example.com - * CherryPick: 4.x.x (Misskey: 2025.x.x) + * CherryPick: 4.x.x (Misskey: 2026.x.x) value: | * Model and OS of the device(s): * Browser: @@ -74,7 +74,7 @@ body: Examples: * Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "CherryPick install shell script", development environment - * CherryPick: 4.x.x (Misskey: 2025.x.x) + * CherryPick: 4.x.x (Misskey: 2026.x.x) * Node: 20.x.x * PostgreSQL: 18.x.x * Redis: 7.x.x diff --git a/COPYING b/COPYING index 1cefed924f..9599e09108 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ Unless otherwise stated this repository is -Copyright © 2014-2025 syuilo & noridev and contributors +Copyright © 2014-2026 syuilo & noridev and contributors And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE. diff --git a/package.json b/package.json index 642123923b..4a8f99dccd 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/kokonect-link/cherrypick.git" }, - "packageManager": "pnpm@10.25.0", + "packageManager": "pnpm@10.30.3", "workspaces": [ "packages/cherrypick-js", "packages/i18n", @@ -61,30 +61,30 @@ }, "dependencies": { "cssnano": "7.1.2", - "esbuild": "0.27.1", + "esbuild": "0.27.3", "execa": "9.6.1", "ignore-walk": "8.0.0", "js-yaml": "4.1.1", "postcss": "8.5.6", - "tar": "7.5.2", - "terser": "5.44.1", + "tar": "7.5.10", + "terser": "5.46.0", "typescript": "5.9.3" }, "devDependencies": { "@biomejs/biome": "2.3.11", - "@eslint/js": "9.39.1", + "@eslint/js": "9.39.3", "@misskey-dev/eslint-plugin": "2.2.0", "@types/js-yaml": "4.0.9", - "@types/node": "24.10.2", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", + "@types/node": "24.11.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", "cross-env": "10.1.0", - "cypress": "15.7.1", - "eslint": "9.39.1", - "globals": "16.5.0", + "cypress": "15.11.0", + "eslint": "9.39.3", + "globals": "17.4.0", "ncp": "2.0.0", - "pnpm": "10.25.0", - "start-server-and-test": "2.1.3" + "pnpm": "10.30.3", + "start-server-and-test": "2.1.5" }, "optionalDependencies": { "@tensorflow/tfjs-core": "4.22.0" diff --git a/packages/backend/migration/1767787474213-Fix.js b/packages/backend/migration/1767787474213-Fix.js new file mode 100644 index 0000000000..c7836a0e03 --- /dev/null +++ b/packages/backend/migration/1767787474213-Fix.js @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: noridev and cherrypick-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class Fix1767787474213 { + name = 'Fix1767787474213' + + async up(queryRunner) { + await queryRunner.query(`DELETE FROM "renote_muting" WHERE "muteeId" NOT IN (SELECT "id" FROM "user")`); + await queryRunner.query(`DELETE FROM "renote_muting" WHERE "muterId" NOT IN (SELECT "id" FROM "user")`); + await queryRunner.query(`ALTER TABLE "poll_vote" DROP CONSTRAINT "FK_poll_vote_poll"`); + await queryRunner.query(`DROP INDEX "public"."IDX_2cd3b2a6b4cf0b910b260afe08"`); + await queryRunner.query(`DROP INDEX "public"."IDX_renote_muting_muteeId"`); + await queryRunner.query(`DROP INDEX "public"."IDX_renote_muting_muterId"`); + await queryRunner.query(`COMMENT ON COLUMN "ad"."startsAt" IS 'The expired date of the Ad.'`); + await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "lastUsedAt" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "mascotImageUrl" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{ "admin", "administrator", "root", "system", "maintainer", "host", "mod", "moderator", "owner", "superuser", "staff", "auth", "i", "me", "everyone", "all", "mention", "mentions", "example", "user", "users", "account", "accounts", "official", "help", "helps", "support", "supports", "info", "information", "informations", "announce", "announces", "announcement", "announcements", "notice", "notification", "notifications", "dev", "developer", "developers", "tech", "misskey" }'`); + await queryRunner.query(`COMMENT ON COLUMN "renote_muting"."muteeId" IS 'The mutee user ID.'`); + await queryRunner.query(`COMMENT ON COLUMN "renote_muting"."muterId" IS 'The muter user ID.'`); + await queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b"`); + await queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "UQ_da851e06d0dfe2ef397d8b1bf1b"`); + await queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c"`); + await queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "UQ_e263909ca4fe5d57f8d4230dd5c"`); + await queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6"`); + await queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "UQ_f4853eb41ab722fe05f81cedeb6"`); + await queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9"`); + await queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "UQ_51cb79b5555effaf7d69ba1cff9"`); + await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "FK_10c146e4b39b443ede016f6736d"`); + await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "UQ_10c146e4b39b443ede016f6736d"`); + await queryRunner.query(`CREATE INDEX "IDX_3fcc2c589eaefc205e0714b99c" ON "ad" ("startsAt") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_c71faf11f0a28a5c0bb506203c" ON "channel_favorite" ("userId", "channelId") `); + await queryRunner.query(`CREATE INDEX "IDX_f7b9d338207e40e768e4a5265a" ON "instance" ("firstRetrievedAt") `); + await queryRunner.query(`CREATE INDEX "IDX_7eac97594bcac5ffcf2068089b" ON "renote_muting" ("muteeId") `); + await queryRunner.query(`CREATE INDEX "IDX_7aa72a5fe76019bfe8e5e0e8b7" ON "renote_muting" ("muterId") `); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0d801c609cec4e9eb4b6b4490c" ON "renote_muting" ("muterId", "muteeId") `); + await queryRunner.query(`ALTER TABLE "renote_muting" ADD CONSTRAINT "FK_7eac97594bcac5ffcf2068089b6" FOREIGN KEY ("muteeId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "renote_muting" ADD CONSTRAINT "FK_7aa72a5fe76019bfe8e5e0e8b7d" FOREIGN KEY ("muterId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "FK_10c146e4b39b443ede016f6736d" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_publickey" DROP CONSTRAINT "FK_10c146e4b39b443ede016f6736d"`); + await queryRunner.query(`ALTER TABLE "user_profile" DROP CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9"`); + await queryRunner.query(`ALTER TABLE "user_keypair" DROP CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6"`); + await queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c"`); + await queryRunner.query(`ALTER TABLE "poll" DROP CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b"`); + await queryRunner.query(`ALTER TABLE "renote_muting" DROP CONSTRAINT "FK_7aa72a5fe76019bfe8e5e0e8b7d"`); + await queryRunner.query(`ALTER TABLE "renote_muting" DROP CONSTRAINT "FK_7eac97594bcac5ffcf2068089b6"`); + await queryRunner.query(`DROP INDEX "public"."IDX_0d801c609cec4e9eb4b6b4490c"`); + await queryRunner.query(`DROP INDEX "public"."IDX_7aa72a5fe76019bfe8e5e0e8b7"`); + await queryRunner.query(`DROP INDEX "public"."IDX_7eac97594bcac5ffcf2068089b"`); + await queryRunner.query(`DROP INDEX "public"."IDX_f7b9d338207e40e768e4a5265a"`); + await queryRunner.query(`DROP INDEX "public"."IDX_c71faf11f0a28a5c0bb506203c"`); + await queryRunner.query(`DROP INDEX "public"."IDX_3fcc2c589eaefc205e0714b99c"`); + await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "UQ_10c146e4b39b443ede016f6736d" UNIQUE ("userId")`); + await queryRunner.query(`ALTER TABLE "user_publickey" ADD CONSTRAINT "FK_10c146e4b39b443ede016f6736d" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "UQ_51cb79b5555effaf7d69ba1cff9" UNIQUE ("userId")`); + await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "FK_51cb79b5555effaf7d69ba1cff9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "UQ_f4853eb41ab722fe05f81cedeb6" UNIQUE ("userId")`); + await queryRunner.query(`ALTER TABLE "user_keypair" ADD CONSTRAINT "FK_f4853eb41ab722fe05f81cedeb6" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "UQ_e263909ca4fe5d57f8d4230dd5c" UNIQUE ("noteId")`); + await queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "UQ_da851e06d0dfe2ef397d8b1bf1b" UNIQUE ("noteId")`); + await queryRunner.query(`ALTER TABLE "poll" ADD CONSTRAINT "FK_da851e06d0dfe2ef397d8b1bf1b" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); + await queryRunner.query(`COMMENT ON COLUMN "renote_muting"."muterId" IS NULL`); + await queryRunner.query(`COMMENT ON COLUMN "renote_muting"."muteeId" IS NULL`); + await queryRunner.query(`COMMENT ON COLUMN "renote_muting"."createdAt" IS NULL`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{admin,administrator,root,system,maintainer,host,mod,moderator,owner,superuser,staff,auth,i,me,everyone,all,mention,mentions,example,user,users,account,accounts,official,help,helps,support,supports,info,information,informations,announce,announces,announcement,announcements,notice,notification,notifications,dev,developer,developers,tech,misskey}'`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "mascotImageUrl" SET DEFAULT '/assets/ai.png'`); + await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "lastUsedAt" SET DEFAULT '2023-04-25 06:51:20.985478+00'`); + await queryRunner.query(`COMMENT ON COLUMN "ad"."startsAt" IS NULL`); + await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muterId" ON "muting" ("muterId") `); + await queryRunner.query(`CREATE INDEX "IDX_renote_muting_muteeId" ON "muting" ("muteeId") `); + await queryRunner.query(`CREATE INDEX "IDX_2cd3b2a6b4cf0b910b260afe08" ON "instance" ("firstRetrievedAt") `); + await queryRunner.query(`ALTER TABLE "poll_vote" ADD CONSTRAINT "FK_poll_vote_poll" FOREIGN KEY ("noteId") REFERENCES "poll"("noteId") ON DELETE CASCADE ON UPDATE NO ACTION`); + } +} diff --git a/packages/backend/migration/1767792212399-MigrationCleanup.js b/packages/backend/migration/1767792212399-MigrationCleanup.js new file mode 100644 index 0000000000..5447602709 --- /dev/null +++ b/packages/backend/migration/1767792212399-MigrationCleanup.js @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: noridev and cherrypick-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class MigrationCleanup1767792212399 { + name = 'MigrationCleanup1767792212399' + + async up(queryRunner) { + await queryRunner.query(`COMMENT ON COLUMN "abuse_report_resolver"."updatedAt" IS 'The updated date of the AbuseReportResolver.'`); + await queryRunner.query(`COMMENT ON COLUMN "abuse_report_resolver"."expirationDate" IS 'The expiration date of the AbuseReportResolver'`); + await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "canChat" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "color" SET DEFAULT '#ffbcdc'`); + await queryRunner.query(`ALTER TABLE "note" ALTER COLUMN "deliveryTargets" SET DEFAULT '{}'`); + await queryRunner.query(`COMMENT ON COLUMN "event"."metadata" IS 'metadata object describing the event. Follows https://schema.org/Event'`); + await queryRunner.query(`ALTER TABLE "event" ALTER COLUMN "metadata" SET DEFAULT '{"@context":"https://schema.org/","@type":"Event"}'`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "remoteObjectStorageUseSSL" SET NOT NULL`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "remoteObjectStorageUseProxy" SET NOT NULL`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{admin,administrator,root,system,maintainer,host,mod,moderator,owner,superuser,staff,auth,i,me,everyone,all,mention,mentions,example,user,users,account,accounts,official,help,helps,support,supports,info,information,informations,announce,announces,announcement,announcements,notice,notification,notifications,dev,developer,developers,tech,misskey,cherrypick}'`); + await queryRunner.query(`COMMENT ON COLUMN "meta"."trustedLinkUrlPatterns" IS 'An array of URL strings or regex that can be used to omit warnings about redirects to external sites. Separate them with spaces to specify AND, and enclose them with slashes to specify regular expressions. Each item is regarded as an OR.'`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "hasEvent" SET NOT NULL`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "disableRightClick" SET NOT NULL`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventStart" IS 'The start time of the event'`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventEnd" IS 'The end of the event'`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventTitle" IS 'short name of event'`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" SET NOT NULL`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventMetadata" IS 'metadata object describing the event. Follows https://schema.org/Event'`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" SET DEFAULT '{"@context":"https://schema.org/","@type":"Event"}'`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "deliveryTargets" SET DEFAULT '{}'`); + await queryRunner.query(`CREATE INDEX "IDX_72689e25ff8131746cb31ef9a1" ON "note_draft" ("eventStart") `); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_72689e25ff8131746cb31ef9a1"`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "deliveryTargets" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" SET DEFAULT '{}'`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventMetadata" IS NULL`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" DROP NOT NULL`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventTitle" IS NULL`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventEnd" IS NULL`); + await queryRunner.query(`COMMENT ON COLUMN "note_draft"."eventStart" IS NULL`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "disableRightClick" DROP NOT NULL`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "hasEvent" DROP NOT NULL`); + await queryRunner.query(`COMMENT ON COLUMN "meta"."trustedLinkUrlPatterns" IS NULL`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{admin,administrator,root,system,maintainer,host,mod,moderator,owner,superuser,staff,auth,i,me,everyone,all,mention,mentions,example,user,users,account,accounts,official,help,helps,support,supports,info,information,informations,announce,announces,announcement,announcements,notice,notification,notifications,dev,developer,developers,tech,misskey}'`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "remoteObjectStorageUseProxy" DROP NOT NULL`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "remoteObjectStorageUseSSL" DROP NOT NULL`); + await queryRunner.query(`ALTER TABLE "event" ALTER COLUMN "metadata" SET DEFAULT '{}'`); + await queryRunner.query(`COMMENT ON COLUMN "event"."metadata" IS 'metadata mapping for event with more user configurable optional information'`); + await queryRunner.query(`ALTER TABLE "note" ALTER COLUMN "deliveryTargets" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "color" SET DEFAULT '#86b300'`); + await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "canChat" SET DEFAULT true`); + await queryRunner.query(`COMMENT ON COLUMN "abuse_report_resolver"."expirationDate" IS 'The expiration date of AbuseReportResolver'`); + await queryRunner.query(`COMMENT ON COLUMN "abuse_report_resolver"."updatedAt" IS 'The updated date of AbuseReportResolver'`); + } +} diff --git a/packages/backend/migration/1769162192635-NoteDraft-EventMetadata-Nullable.js b/packages/backend/migration/1769162192635-NoteDraft-EventMetadata-Nullable.js new file mode 100644 index 0000000000..e736702c02 --- /dev/null +++ b/packages/backend/migration/1769162192635-NoteDraft-EventMetadata-Nullable.js @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project, noridev and cherryPick-project, yojo-art team + * SPDX-License-Identifier: AGPL-3.0-only + */ +export class NoteDraftEventMetadataNullable1769162192635 { + name = 'NoteDraftEventMetadataNullable1769162192635' + + /** + * @param {QueryRunner} queryRunner + */ + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "proxyRemoteFiles" SET DEFAULT true`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" DROP NOT NULL`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" DROP DEFAULT`); + } + + /** + * @param {QueryRunner} queryRunner + */ + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" SET DEFAULT '{"@type": "Event", "@context": "https://schema.org/"}'`); + await queryRunner.query(`ALTER TABLE "note_draft" ALTER COLUMN "eventMetadata" SET NOT NULL`); + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "proxyRemoteFiles" SET DEFAULT false`); + } +} diff --git a/packages/backend/migration/1773490771475-AddUserPendingOriginIp.js b/packages/backend/migration/1773490771475-AddUserPendingOriginIp.js new file mode 100644 index 0000000000..4dc649d248 --- /dev/null +++ b/packages/backend/migration/1773490771475-AddUserPendingOriginIp.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: noridev and cherrypick-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class AddUserPendingOriginIp1773490771475 { + name = 'AddUserPendingOriginIp1773490771475' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_pending" ADD "requestOriginIp" character varying(128) NULL`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "user_pending" DROP COLUMN "requestOriginIp"`); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index 431e14bdb1..7ba54dd930 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -74,32 +74,32 @@ "utf-8-validate": "6.0.5" }, "dependencies": { - "@aws-sdk/client-s3": "3.948.0", - "@aws-sdk/lib-storage": "3.948.0", + "@aws-sdk/client-s3": "3.1000.0", + "@aws-sdk/lib-storage": "3.1000.0", "@discordapp/twemoji": "16.0.1", "@fastify/accepts": "5.0.4", "@fastify/cors": "11.2.0", - "@fastify/express": "4.0.2", + "@fastify/express": "4.0.4", "@fastify/http-proxy": "11.4.1", "@fastify/multipart": "9.3.0", "@fastify/static": "8.3.0", + "@google-cloud/logging": "^11.2.1", + "@google-cloud/translate": "^9.3.0", "@kitajs/html": "4.2.11", - "@google-cloud/logging": "^10.5.0", - "@google-cloud/translate": "^7.2.1", "@misskey-dev/sharp-read-bmp": "1.2.0", "@misskey-dev/summaly": "5.2.5", - "@napi-rs/canvas": "0.1.84", + "@napi-rs/canvas": "0.1.95", "@nestjs/common": "11.1.9", "@nestjs/core": "11.1.9", "@nestjs/testing": "11.1.9", "@peertube/http-signature": "1.7.0", - "@sentry/node": "10.29.0", - "@sentry/profiling-node": "10.29.0", - "@simplewebauthn/server": "13.2.2", - "@sinonjs/fake-timers": "15.0.0", - "@smithy/node-http-handler": "4.4.5", + "@sentry/node": "10.40.0", + "@sentry/profiling-node": "10.40.0", + "@simplewebauthn/server": "13.2.3", + "@sinonjs/fake-timers": "15.1.0", + "@smithy/node-http-handler": "4.4.12", "@swc/cli": "0.7.9", - "@swc/core": "1.15.3", + "@swc/core": "1.15.17", "@twemoji/parser": "16.0.0", "@types/redis-info": "3.0.3", "@vitalets/google-translate-api": "9.2.1", @@ -121,7 +121,7 @@ "content-disposition": "1.0.1", "date-fns": "4.1.0", "deep-email-validator": "0.1.21", - "fastify": "5.6.2", + "fastify": "5.8.1", "fastify-raw-body": "5.0.0", "feed": "5.1.0", "file-type": "21.1.1", @@ -174,7 +174,7 @@ "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", "strip-ansi": "^7.1.0", - "systeminformation": "5.27.14", + "systeminformation": "5.31.4", "tinycolor2": "1.6.0", "tmp": "0.2.5", "tsc-alias": "1.8.16", @@ -191,7 +191,7 @@ "@jest/globals": "29.7.0", "@kitajs/ts-html-plugin": "4.1.3", "@nestjs/platform-express": "11.1.9", - "@sentry/vue": "10.29.0", + "@sentry/vue": "10.40.0", "@simplewebauthn/types": "12.0.0", "@swc/jest": "0.2.39", "@types/accepts": "1.3.7", @@ -205,8 +205,8 @@ "@types/jsonld": "1.5.15", "@types/mime-types": "3.0.1", "@types/ms": "2.1.0", - "@types/node": "24.10.2", - "@types/nodemailer": "7.0.4", + "@types/node": "24.11.0", + "@types/nodemailer": "7.0.11", "@types/oauth2orize": "1.11.5", "@types/oauth2orize-pkce": "0.1.2", "@types/pg": "8.15.6", @@ -224,8 +224,8 @@ "@types/vary": "1.1.3", "@types/web-push": "3.6.4", "@types/ws": "8.18.1", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", "aws-sdk-client-mock": "4.1.0", "cbor": "10.0.11", "cross-env": "10.1.0", diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts index 10ff4d410a..77ab3789c0 100644 --- a/packages/backend/src/core/WebhookTestService.ts +++ b/packages/backend/src/core/WebhookTestService.ts @@ -68,6 +68,8 @@ function generateDummyUser(override?: Partial): MiUser { autoDeleteNotesAfterDays: null, autoDeleteKeepFavorites: true, canChat: null, + approved: true, + signupReason: null, ...override, }; } @@ -484,6 +486,7 @@ export class WebhookTestService { followingVisibility: 'public', chatScope: 'mutual', canChat: true, + approved: undefined, twoFactorEnabled: false, usePasswordLessLogin: false, securityKeys: false, diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index 3f7674397a..8c3478c40e 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -249,8 +249,8 @@ export class NoteEntityService implements OnModuleInit { const event = await this.eventsRepository.findOneByOrFail({ noteId: note.id }); return { title: event.title, - start: event.start, - end: event.end, + start: event.start.toISOString(), + end: event.end ? event.end.toISOString() : null, metadata: event.metadata, }; } diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index 7c2699d28a..71c5ceef44 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -24,6 +24,7 @@ import type { UserGroupInvitationEntityService } from './UserGroupInvitationEnti const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set([ 'note', + 'note:grouped', 'mention', 'reply', 'renote', diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 7f7147ea49..a9fef27834 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -533,7 +533,6 @@ export class UserEntityService implements OnModuleInit { ) : undefined, setFederationAvatarShape: user.setFederationAvatarShape ?? undefined, isSquareAvatars: user.isSquareAvatars ?? undefined, - approved: user.approved, ...(isDetailed ? { url: profile!.url, @@ -646,7 +645,6 @@ export class UserEntityService implements OnModuleInit { }, }) : [], - signupReason: user.signupReason, } : {}), ...(relation ? { diff --git a/packages/backend/src/models/Event.ts b/packages/backend/src/models/Event.ts index a53fe4dcce..52b46307ab 100644 --- a/packages/backend/src/models/Event.ts +++ b/packages/backend/src/models/Event.ts @@ -30,7 +30,7 @@ export class MiEvent { comment: 'The end of the event', nullable: true, }) - public end: Date; + public end: Date | null; @Column({ type: 'varchar', diff --git a/packages/backend/src/models/Note.ts b/packages/backend/src/models/Note.ts index 808a3b532d..10803a1dee 100644 --- a/packages/backend/src/models/Note.ts +++ b/packages/backend/src/models/Note.ts @@ -43,6 +43,7 @@ export class MiNote { }) public deleteAt: Date | null; + @Index('IDX_note_deliveryTargets', { synchronize: false }) @Column('jsonb', { nullable: true, default: {}, diff --git a/packages/backend/src/models/NoteDraft.ts b/packages/backend/src/models/NoteDraft.ts index cc4710c7a5..940261f273 100644 --- a/packages/backend/src/models/NoteDraft.ts +++ b/packages/backend/src/models/NoteDraft.ts @@ -199,19 +199,17 @@ export class MiNoteDraft { public eventTitle: string | null; @Column('jsonb', { - default: { - '@context': 'https://schema.org/', - '@type': 'Event', - }, comment: 'metadata object describing the event. Follows https://schema.org/Event', + nullable: true, }) - public eventMetadata: Event.EventSchema; + public eventMetadata: Event.EventSchema | null; @Column('timestamp with time zone', { nullable: true, }) public deleteAt: Date | null; + @Index('IDX_note_draft_deliveryTargets', { synchronize: false }) @Column('jsonb', { nullable: true, default: {}, diff --git a/packages/backend/src/models/UserPending.ts b/packages/backend/src/models/UserPending.ts index 961ae344f1..8c0ded2030 100644 --- a/packages/backend/src/models/UserPending.ts +++ b/packages/backend/src/models/UserPending.ts @@ -34,6 +34,13 @@ export class MiUserPending { @Column('varchar', { length: 1000, + nullable: true, }) public reason: string; + + @Column('varchar', { + length: 128, + nullable: true, + }) + public requestOriginIp: string; } diff --git a/packages/backend/src/models/json-schema/note-history.ts b/packages/backend/src/models/json-schema/note-history.ts index c164f921aa..763217b490 100644 --- a/packages/backend/src/models/json-schema/note-history.ts +++ b/packages/backend/src/models/json-schema/note-history.ts @@ -77,6 +77,21 @@ export const packedNoteHistorySchema = { }, metadata: { type: 'object', + optional: true, nullable: false, + properties: { + '@type': { + type: 'string', + optional: true, nullable: false, + }, + location: { + type: 'string', + optional: true, nullable: false, + }, + description: { + type: 'string', + optional: true, nullable: false, + }, + }, }, }, }, diff --git a/packages/backend/src/models/json-schema/note.ts b/packages/backend/src/models/json-schema/note.ts index 377baeb6a5..20ac005273 100644 --- a/packages/backend/src/models/json-schema/note.ts +++ b/packages/backend/src/models/json-schema/note.ts @@ -182,6 +182,39 @@ export const packedNoteSchema = { event: { type: 'object', optional: true, nullable: true, + properties: { + title: { + type: 'string', + optional: false, nullable: false, + }, + start: { + type: 'string', + format: 'date-time', + }, + end: { + type: 'string', + format: 'date-time', + nullable: true, + }, + metadata: { + type: 'object', + optional: true, nullable: false, + properties: { + '@type': { + type: 'string', + optional: true, nullable: false, + }, + location: { + type: 'string', + optional: true, nullable: false, + }, + description: { + type: 'string', + optional: true, nullable: false, + }, + }, + }, + }, }, channelId: { type: 'string', diff --git a/packages/backend/src/models/json-schema/notification.ts b/packages/backend/src/models/json-schema/notification.ts index 077e14ccae..ba46ef7e66 100644 --- a/packages/backend/src/models/json-schema/notification.ts +++ b/packages/backend/src/models/json-schema/notification.ts @@ -468,6 +468,33 @@ export const packedNotificationSchema = { }, }, }, + }, { + type: 'object', + properties: { + ...baseSchema.properties, + type: { + type: 'string', + optional: false, nullable: false, + enum: ['note:grouped'], + }, + noteIds: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'string', + optional: true, nullable: true, + }, + }, + users: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'object', + ref: 'UserLite', + optional: false, nullable: false, + }, + }, + }, }, { type: 'object', properties: { diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index fc46dc3b60..80a522d033 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -462,6 +462,14 @@ export const packedUserDetailedNotMeOnlySchema = { type: 'boolean', nullable: false, optional: true, }, + approved: { + type: 'boolean', + nullable: false, optional: true, + }, + signupReason: { + type: 'string', + nullable: false, optional: true, + }, //#endregion }, } as const; diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index 7aa0db2566..075077f915 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -565,7 +565,7 @@ export class QueueProcessorService implements OnApplicationShutdown { //#region scheduled note delete { this.scheduledNoteDeleteQueueWorker = new Bull.Worker(QUEUE.SCHEDULED_NOTE_DELETE, (job) => { - if (this.config.sentryForBackend) { + if (this.config.sentryForBackend && Sentry != null) { return Sentry.startSpan({ name: 'Queue: ScheduledNoteDelete' }, () => this.scheduledNoteDeleteProcessorService.process(job)); } else { return this.scheduledNoteDeleteProcessorService.process(job); diff --git a/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts b/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts index 4f40df0e4d..6ebfdae366 100644 --- a/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts +++ b/packages/backend/src/queue/processors/DeleteAccountProcessorService.ts @@ -160,7 +160,7 @@ export class DeleteAccountProcessorService { await this.usersRepository.delete(job.data.user.id); // Trigger CacheService - this.globalEventService.publishInternalEvent('remoteUserUpdated', { id: job.data.user.id }); + //this.globalEventService.publishInternalEvent('remoteUserUpdated', { id: job.data.user.id }); } return `[${job.data.user.id}] Account deleted`; diff --git a/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts b/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts index aa034f5038..772048cad1 100644 --- a/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts +++ b/packages/backend/src/queue/processors/PostScheduledNoteProcessorService.ts @@ -59,7 +59,9 @@ export class PostScheduledNoteProcessorService { title: draft.eventTitle, start: new Date(draft.eventStart), end: draft.eventEnd ? new Date(draft.eventEnd) : null, - metadata: draft.eventMetadata, + metadata: draft.eventMetadata ?? { + '@type': 'Event', + }, } : null, deleteAt: draft.deleteAt ? new Date(draft.deleteAt) : null, }); diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index 358908289b..1e3f450bb5 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -218,7 +218,7 @@ export class SignupApiService { username: username, password: hash, reason: reason, - requestOriginIp: this.meta.enableIpLogging ? request.ip : null, + requestOriginIp: this.meta.enableIpLogging ? request.ip : undefined, }); const link = `${this.config.url}/signup-complete/${code}`; diff --git a/packages/backend/src/server/api/endpoint-list.ts b/packages/backend/src/server/api/endpoint-list.ts index d0144ce44a..15e7d05e2d 100644 --- a/packages/backend/src/server/api/endpoint-list.ts +++ b/packages/backend/src/server/api/endpoint-list.ts @@ -15,10 +15,10 @@ export * as 'admin/abuse-report/notification-recipient/delete' from './endpoints export * as 'admin/abuse-report/notification-recipient/list' from './endpoints/admin/abuse-report/notification-recipient/list.js'; export * as 'admin/abuse-report/notification-recipient/show' from './endpoints/admin/abuse-report/notification-recipient/show.js'; export * as 'admin/abuse-report/notification-recipient/update' from './endpoints/admin/abuse-report/notification-recipient/update.js'; -export * as 'admin/abuse-report-resolver/create' from '@/server/api/endpoints/admin/abuse-report-resolver/create.js'; -export * as 'admin/abuse-report-resolver/delete' from '@/server/api/endpoints/admin/abuse-report-resolver/delete.js'; -export * as 'admin/abuse-report-resolver/list' from '@/server/api/endpoints/admin/abuse-report-resolver/list.js'; -export * as 'admin/abuse-report-resolver/update' from '@/server/api/endpoints/admin/abuse-report-resolver/update.js'; +export * as 'admin/abuse-report-resolver/create' from './endpoints/admin/abuse-report-resolver/create.js'; +export * as 'admin/abuse-report-resolver/delete' from './endpoints/admin/abuse-report-resolver/delete.js'; +export * as 'admin/abuse-report-resolver/list' from './endpoints/admin/abuse-report-resolver/list.js'; +export * as 'admin/abuse-report-resolver/update' from './endpoints/admin/abuse-report-resolver/update.js'; export * as 'admin/abuse-user-reports' from './endpoints/admin/abuse-user-reports.js'; export * as 'admin/accounts/create' from './endpoints/admin/accounts/create.js'; export * as 'admin/accounts/delete' from './endpoints/admin/accounts/delete.js'; diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report-resolver/list.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report-resolver/list.ts index a5a6f3c54c..ee62abd885 100644 --- a/packages/backend/src/server/api/endpoints/admin/abuse-report-resolver/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/abuse-report-resolver/list.ts @@ -18,9 +18,17 @@ export const meta = { res: { type: 'array', + optional: false, nullable: false, items: { type: 'object', + optional: false, nullable: false, properties: { + id: { + type: 'string', + nullable: false, optional: false, + format: 'id', + example: 'xxxxxxxxxx', + }, name: { type: 'string', nullable: false, optional: false, @@ -60,8 +68,8 @@ export const paramDef = { required: [], } as const; -@Injectable() // eslint-disable-next-line import/no-default-export -export default class extends Endpoint { +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( @Inject(DI.abuseReportResolversRepository) private abuseReportResolversRepository: AbuseReportResolversRepository, diff --git a/packages/backend/src/server/api/endpoints/notes/update.ts b/packages/backend/src/server/api/endpoints/notes/update.ts index ba4979e16b..c17446bf7f 100644 --- a/packages/backend/src/server/api/endpoints/notes/update.ts +++ b/packages/backend/src/server/api/endpoints/notes/update.ts @@ -69,7 +69,7 @@ export const paramDef = { type: 'string', minLength: 1, maxLength: MAX_NOTE_TEXT_LENGTH, - nullable: false, + nullable: true, }, fileIds: { type: 'array', diff --git a/packages/backend/src/server/web/views/bios.tsx b/packages/backend/src/server/web/views/bios.tsx index ca36b7c9fc..5b663020d5 100644 --- a/packages/backend/src/server/web/views/bios.tsx +++ b/packages/backend/src/server/web/views/bios.tsx @@ -5,6 +5,7 @@ export function BiosPage(props: { version: string; + basedMisskeyVersion: string; }) { return ( <> diff --git a/packages/backend/src/server/web/views/cli.tsx b/packages/backend/src/server/web/views/cli.tsx index e9c991a724..f7b55ea4ba 100644 --- a/packages/backend/src/server/web/views/cli.tsx +++ b/packages/backend/src/server/web/views/cli.tsx @@ -5,6 +5,7 @@ export function CliPage(props: { version: string; + basedMisskeyVersion: string; }) { return ( <> diff --git a/packages/backend/test/unit/ActivityPubAccessControlService.ts b/packages/backend/test/unit/ActivityPubAccessControlService.ts index 6f67e57735..7aa2e632dd 100644 --- a/packages/backend/test/unit/ActivityPubAccessControlService.ts +++ b/packages/backend/test/unit/ActivityPubAccessControlService.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { jest } from '@jest/globals'; import { Test, TestingModule } from '@nestjs/testing'; import { describe, test, expect, beforeEach } from '@jest/globals'; import type { FastifyRequest } from 'fastify'; diff --git a/packages/backend/test/unit/FileInfoService.ts b/packages/backend/test/unit/FileInfoService.ts index 1211ce3b4b..edab35e175 100644 --- a/packages/backend/test/unit/FileInfoService.ts +++ b/packages/backend/test/unit/FileInfoService.ts @@ -292,8 +292,8 @@ describe('FileInfoService', () => { size: 9817, md5: '74c9279a4abe98789565f1dc1a541a42', type: { - mime: 'video/mp4', - ext: 'mp4', + mime: 'audio/mp4', + ext: 'm4a', }, }); }); @@ -308,7 +308,7 @@ describe('FileInfoService', () => { size: 8879, md5: '53bc1adcb6acbbda67ff9bd484896438', type: { - mime: 'video/webm', + mime: 'audio/webm', ext: 'webm', }, }); diff --git a/packages/cherrypick-js/LICENSE b/packages/cherrypick-js/LICENSE index d9dc05607d..4ec6ade0bc 100644 --- a/packages/cherrypick-js/LICENSE +++ b/packages/cherrypick-js/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 syuilo and noridev and other contributors +Copyright (c) 2021-2026 syuilo and noridev and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/cherrypick-js/generator/package.json b/packages/cherrypick-js/generator/package.json index 7d3accee7c..776b16d47b 100644 --- a/packages/cherrypick-js/generator/package.json +++ b/packages/cherrypick-js/generator/package.json @@ -8,15 +8,15 @@ }, "devDependencies": { "@readme/openapi-parser": "5.2.1", - "@types/node": "24.10.2", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", + "@types/node": "24.11.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", + "eslint": "9.39.3", "openapi-types": "12.1.3", "openapi-typescript": "7.10.1", "ts-case-convert": "2.1.0", "tsx": "4.21.0", - "typescript": "5.9.3", - "eslint": "9.39.1" + "typescript": "5.9.3" }, "files": [ "built" diff --git a/packages/cherrypick-js/package.json b/packages/cherrypick-js/package.json index e24136504f..6e8720ff44 100644 --- a/packages/cherrypick-js/package.json +++ b/packages/cherrypick-js/package.json @@ -43,11 +43,11 @@ "devDependencies": { "@biomejs/biome": "2.3.11", "@microsoft/api-extractor": "7.55.2", - "@types/node": "24.10.2", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", + "@types/node": "24.11.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", "@vitest/coverage-v8": "4.0.15", - "esbuild": "0.27.1", + "esbuild": "0.27.3", "execa": "9.6.1", "ncp": "2.0.0", "nodemon": "3.1.11", diff --git a/packages/cherrypick-js/src/autogen/types.ts b/packages/cherrypick-js/src/autogen/types.ts index 5b35bb5c82..e367ddd9e9 100644 --- a/packages/cherrypick-js/src/autogen/types.ts +++ b/packages/cherrypick-js/src/autogen/types.ts @@ -4431,6 +4431,8 @@ export type components = { /** @enum {string} */ notify?: 'normal' | 'none'; withReplies?: boolean; + approved?: boolean; + signupReason?: string; }; MeDetailedOnly: { /** Format: id */ @@ -4791,7 +4793,18 @@ export type components = { emojis?: { [key: string]: string; }; - event?: Record | null; + event?: { + title: string; + /** Format: date-time */ + start: string; + /** Format: date-time */ + end: string | null; + metadata?: { + '@type'?: string; + location?: string; + description?: string; + }; + } | null; /** * Format: id * @example xxxxxxxxxx @@ -5124,6 +5137,15 @@ export type components = { type: 'renote:grouped'; note: components['schemas']['Note']; users: components['schemas']['UserLite'][]; + } | { + /** Format: id */ + id: string; + /** Format: date-time */ + createdAt: string; + /** @enum {string} */ + type: 'note:grouped'; + noteIds: (string | null)[]; + users: components['schemas']['UserLite'][]; } | { /** Format: id */ id: string; @@ -6094,7 +6116,11 @@ export type components = { start: string; /** Format: date-time */ end: string | null; - metadata: Record; + metadata?: { + '@type'?: string; + location?: string; + description?: string; + }; } | null; fileIds?: string[]; files?: components['schemas']['DriveFile'][]; @@ -6276,6 +6302,11 @@ export interface operations { }; content: { 'application/json': { + /** + * Format: id + * @example xxxxxxxxxx + */ + id: string; name: string; targetUserPattern: string | null; reporterPattern: string | null; @@ -33782,7 +33813,7 @@ export interface operations { 'application/json': { /** Format: misskey:id */ noteId: string; - text: string; + text: string | null; fileIds?: string[]; mediaIds?: string[]; poll?: { diff --git a/packages/frontend-builder/package.json b/packages/frontend-builder/package.json index 16da842986..a3e3993bd0 100644 --- a/packages/frontend-builder/package.json +++ b/packages/frontend-builder/package.json @@ -12,15 +12,15 @@ "devDependencies": { "@biomejs/biome": "2.3.11", "@types/estree": "1.0.8", - "@types/node": "24.10.2", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", - "rollup": "4.53.3", + "@types/node": "24.11.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", + "rollup": "4.59.0", "typescript": "5.9.3" }, "dependencies": { - "i18n": "workspace:*", "estree-walker": "3.0.3", + "i18n": "workspace:*", "magic-string": "0.30.21", "vite": "7.2.7" } diff --git a/packages/frontend-embed/package.json b/packages/frontend-embed/package.json index 62a479f80b..8117c7aa9a 100644 --- a/packages/frontend-embed/package.json +++ b/packages/frontend-embed/package.json @@ -14,7 +14,6 @@ }, "dependencies": { "@discordapp/twemoji": "16.0.1", - "i18n": "workspace:*", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-replace": "6.0.3", "@rollup/pluginutils": "5.3.0", @@ -24,18 +23,19 @@ "cherrypick-js": "workspace:*", "estree-walker": "3.0.3", "frontend-shared": "workspace:*", + "i18n": "workspace:*", "icons-subsetter": "workspace:*", "json5": "2.2.3", "mfc-js": "0.1.0", "punycode.js": "2.3.1", - "rollup": "4.53.3", + "rollup": "4.59.0", "sass": "1.95.1", "shiki": "3.19.0", "temml": "0.13.1", "tinycolor2": "1.6.0", "uuid": "13.0.0", "vite": "7.2.7", - "vue": "3.5.25" + "vue": "3.5.29" }, "devDependencies": { "@biomejs/biome": "2.3.11", @@ -44,14 +44,14 @@ "@testing-library/vue": "8.1.0", "@types/estree": "1.0.8", "@types/micromatch": "4.0.10", - "@types/node": "24.10.2", + "@types/node": "24.11.0", "@types/punycode.js": "npm:@types/punycode@2.1.4", "@types/tinycolor2": "1.4.6", "@types/ws": "8.18.1", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", "@vitest/coverage-v8": "4.0.15", - "@vue/runtime-core": "3.5.25", + "@vue/runtime-core": "3.5.29", "acorn": "8.15.0", "cross-env": "10.1.0", "eslint-plugin-import": "2.32.0", @@ -62,12 +62,12 @@ "msw": "2.12.4", "nodemon": "3.1.11", "prettier": "3.7.4", - "start-server-and-test": "2.1.3", + "start-server-and-test": "2.1.5", "tsx": "4.21.0", "typescript": "5.9.3", "vite-plugin-turbosnap": "1.0.3", - "vue-component-type-helpers": "3.1.8", + "vue-component-type-helpers": "3.2.5", "vue-eslint-parser": "10.2.0", - "vue-tsc": "3.1.8" + "vue-tsc": "3.2.5" } } diff --git a/packages/frontend-shared/package.json b/packages/frontend-shared/package.json index f3074e1754..0f32526f23 100644 --- a/packages/frontend-shared/package.json +++ b/packages/frontend-shared/package.json @@ -25,10 +25,10 @@ }, "devDependencies": { "@biomejs/biome": "2.3.11", - "@types/node": "24.10.2", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", - "esbuild": "0.27.1", + "@types/node": "24.11.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", + "esbuild": "0.27.3", "eslint-plugin-vue": "10.6.2", "nodemon": "3.1.11", "typescript": "5.9.3", @@ -38,8 +38,8 @@ "js-built" ], "dependencies": { - "i18n": "workspace:*", "cherrypick-js": "workspace:*", - "vue": "3.5.25" + "i18n": "workspace:*", + "vue": "3.5.29" } } diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 33e8eb21d3..c896d92cdd 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -24,12 +24,11 @@ "@discordapp/twemoji": "16.0.1", "@github/webauthn-json": "2.1.1", "@mcaptcha/vanilla-glue": "0.1.0-rc2", - "i18n": "workspace:*", "@misskey-dev/browser-image-resizer": "2024.1.0", "@rollup/plugin-json": "6.1.0", "@rollup/plugin-replace": "6.0.3", "@rollup/pluginutils": "5.3.0", - "@sentry/vue": "10.29.0", + "@sentry/vue": "10.40.0", "@syuilo/aiscript": "1.2.0", "@syuilo/aiscript-0-19-0": "npm:@syuilo/aiscript@^0.19.0", "@twemoji/parser": "16.0.0", @@ -54,6 +53,7 @@ "execa": "9.6.1", "exifreader": "4.33.1", "frontend-shared": "workspace:*", + "i18n": "workspace:*", "icons-subsetter": "workspace:*", "idb-keyval": "6.2.2", "insert-text-at-cursor": "0.3.0", @@ -71,7 +71,7 @@ "punycode.js": "2.3.1", "qr-code-styling": "1.9.2", "qr-scanner": "1.4.2", - "rollup": "4.53.3", + "rollup": "4.59.0", "sanitize-html": "2.17.0", "sass": "1.95.1", "shiki": "3.19.0", @@ -83,7 +83,7 @@ "tinyld": "^1.3.4", "v-code-diff": "1.13.1", "vite": "7.2.7", - "vue": "3.5.25", + "vue": "3.5.29", "vue-prism-editor": "2.0.0-alpha.2", "vuedraggable": "next", "wanakana": "5.3.1" @@ -115,21 +115,21 @@ "@types/estree": "1.0.8", "@types/matter-js": "0.20.2", "@types/micromatch": "4.0.10", - "@types/node": "24.10.2", + "@types/node": "24.11.0", "@types/prismjs": "1.26.5", "@types/punycode.js": "npm:@types/punycode@2.1.4", "@types/sanitize-html": "2.16.0", "@types/seedrandom": "3.0.8", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", - "@typescript-eslint/eslint-plugin": "8.49.0", - "@typescript-eslint/parser": "8.49.0", + "@typescript-eslint/eslint-plugin": "8.56.1", + "@typescript-eslint/parser": "8.56.1", "@vitest/coverage-v8": "4.0.15", - "@vue/compiler-core": "3.5.25", + "@vue/compiler-core": "3.5.29", "acorn": "8.15.0", "astring": "1.9.0", "cross-env": "10.1.0", - "cypress": "15.7.1", + "cypress": "15.11.0", "eslint-plugin-import": "2.32.0", "eslint-plugin-storybook": "10.1.4", "eslint-plugin-vue": "10.6.2", @@ -146,8 +146,8 @@ "react": "19.2.1", "react-dom": "19.2.1", "seedrandom": "3.0.5", - "start-server-and-test": "2.1.3", - "storybook": "10.1.5", + "start-server-and-test": "2.1.5", + "storybook": "10.2.13", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", "tsx": "4.21.0", "typescript": "5.9.3", @@ -155,8 +155,8 @@ "vite-plugin-turbosnap": "1.0.3", "vitest": "4.0.15", "vitest-fetch-mock": "0.4.5", - "vue-component-type-helpers": "3.1.8", + "vue-component-type-helpers": "3.2.5", "vue-eslint-parser": "10.2.0", - "vue-tsc": "3.1.8" + "vue-tsc": "3.2.5" } } diff --git a/packages/frontend/src/aiscript/api.ts b/packages/frontend/src/aiscript/api.ts index c34db82fa7..feca7a8f74 100644 --- a/packages/frontend/src/aiscript/api.ts +++ b/packages/frontend/src/aiscript/api.ts @@ -191,8 +191,9 @@ export function createAiScriptEnv(opts: { storageKey: string, token?: string }) throw new Error(`Invalid type. expected string but got ${typeof val}`); } return val; - }).filter(val => MkPermissions.includes(val)); - return await new Promise(async (resolve: any) => { + }).filter(val => MkPermissions.includes(val as any)); + + return await new Promise(async (resolve: (v: values.Value) => void) => { await os.popup(defineAsyncComponent(() => import('@/components/MkFlashRequestTokenDialog.vue')), { permissions, }, { @@ -208,7 +209,7 @@ export function createAiScriptEnv(opts: { storageKey: string, token?: string }) closed: () => { resolve(values.FALSE); }, - }, 'closed'); + }); }); }), 'Mk:nyaize': values.FN_NATIVE(([text]) => { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 77178417ba..7ddf64892e 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -389,12 +389,12 @@ export async function mainBoot() { // 프로필 아이콘 모양 설정 연합 초기화 if ($i.policies.canSetFederationAvatarShape && prefer.s.setFederationAvatarShape) { - await misskeyApi('i/update', { + misskeyApi('i/update', { setFederationAvatarShape: true, isSquareAvatars: prefer.s.squareAvatars, }); } else if (!$i.policies.canSetFederationAvatarShape && prefer.s.setFederationAvatarShape) { - await misskeyApi('i/update', { + misskeyApi('i/update', { setFederationAvatarShape: false, isSquareAvatars: prefer.s.squareAvatars, }); diff --git a/packages/frontend/src/components/MkApprovalUser.vue b/packages/frontend/src/components/MkApprovalUser.vue index 4092ce6d01..6b8f0643aa 100644 --- a/packages/frontend/src/components/MkApprovalUser.vue +++ b/packages/frontend/src/components/MkApprovalUser.vue @@ -57,8 +57,8 @@ function getReason() { return misskeyApi('admin/show-user', { userId: props.user.id, }).then(info => { - reason.value = info?.signupReason; - email.value = info?.email; + reason.value = info.signupReason ?? ''; + email.value = info.email ?? ''; }); } diff --git a/packages/frontend/src/components/MkEvent.stories.impl.ts b/packages/frontend/src/components/MkEvent.stories.impl.ts index 200b93dd13..6070799d55 100644 --- a/packages/frontend/src/components/MkEvent.stories.impl.ts +++ b/packages/frontend/src/components/MkEvent.stories.impl.ts @@ -41,15 +41,19 @@ export const Default = { renoteCount: 0, repliesCount: 0, reactionCount: 0, + reactionAcceptance: null, + reactionEmojis: {}, + reactions: {}, + hasDeliveryTargets: false, event: { - title: 'Come on a Tea Party!' as any, - start: new Date('2017-10-25T15:00:00+0900').getTime() as any, - end: new Date('2017-10-25T18:00:00+0900').getTime() as any, + title: 'Come on a Tea Party!', + start: new Date('2017-10-25T15:00:00+0900').toISOString(), + end: new Date('2017-10-25T18:00:00+0900').toISOString(), metadata: { '@type': 'Event', location: 'Kawasaki, Japan', description: 'Let\'s have a tea party!', - } as any, + }, }, }, }, diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 0dc2c7109d..5caaf22851 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +