diff --git a/packages/backend/eslint.config.js b/packages/backend/eslint.config.js index f900352ff1..02985d776b 100644 --- a/packages/backend/eslint.config.js +++ b/packages/backend/eslint.config.js @@ -151,7 +151,7 @@ export default [ }, parserOptions: { parser: tsParser, - project: ['./jsconfig.frontend.json'], + project: ['./tsconfig.frontend.json'], sourceType: 'module', tsconfigRootDir: import.meta.dirname, }, diff --git a/packages/backend/package.json b/packages/backend/package.json index 5fb88f5e72..e6999aafb3 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -26,7 +26,7 @@ "typecheck": "pnpm --filter megalodon build && pnpm run typecheck:scripts && pnpm run typecheck:backend && pnpm run typecheck:frontend && pnpm run typecheck:test && pnpm run typecheck:test-federation && pnpm run typecheck:test-server", "typecheck:scripts": "tsc -p tsconfig.scripts.json --noEmit", "typecheck:backend": "tsc -p tsconfig.backend.json --noEmit", - "typecheck:frontend": "tsc -p jsconfig.frontend.json --noEmit", + "typecheck:frontend": "tsc -p tsconfig.frontend.json --noEmit", "typecheck:test": "tsc -p test/tsconfig.json --noEmit", "typecheck:test-federation": "tsc -p test-federation/tsconfig.json --noEmit", "typecheck:test-server": "tsc -p test-server/tsconfig.json --noEmit", diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index cffbb65461..94289f237d 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -767,7 +767,7 @@ export class DriveService { @bindThis public async deleteFileSync(file: MiDriveFile, isExpired = false, deleter?: { id: string }) { - const promises = []; + const promises: Promise[] = []; if (file.storedInternal) { promises.push(this.deleteLocalFile(file.accessKey!)); diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index 0d80bfbdca..49eed40ee1 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -299,7 +299,7 @@ export class MfmService { (note that the `rp` are to be ignored, they only exist for browsers who don't understand ruby) */ - let nonRtNodes = []; + let nonRtNodes: ChildNode[] = []; // scan children, ignore `rp`, split on `rt` for (const child of node.childNodes) { if (isText(child)) { diff --git a/packages/backend/src/core/ReactionsBufferingService.ts b/packages/backend/src/core/ReactionsBufferingService.ts index d1f13d6304..7cb5120306 100644 --- a/packages/backend/src/core/ReactionsBufferingService.ts +++ b/packages/backend/src/core/ReactionsBufferingService.ts @@ -147,7 +147,7 @@ export class ReactionsBufferingService implements OnApplicationShutdown { // TODO: scanは重い可能性があるので、別途 bufferedNoteIds を直接Redis上に持っておいてもいいかもしれない @bindThis public async bake(): Promise { - const bufferedNoteIds = []; + const bufferedNoteIds: string[] = []; let cursor = '0'; do { // https://github.com/redis/ioredis#transparent-key-prefixing diff --git a/packages/backend/src/core/entities/FlashEntityService.ts b/packages/backend/src/core/entities/FlashEntityService.ts index 7b0150f5b6..c2575e69aa 100644 --- a/packages/backend/src/core/entities/FlashEntityService.ts +++ b/packages/backend/src/core/entities/FlashEntityService.ts @@ -40,7 +40,7 @@ export class FlashEntityService { // { schema: 'UserDetailed' } すると無限ループするので注意 const user = hint?.packedUser ?? await this.userEntityService.pack(flash.user ?? flash.userId, me); - let isLiked = undefined; + let isLiked: boolean | undefined = undefined; if (meId) { isLiked = hint?.likedFlashIds ? hint.likedFlashIds.includes(flash.id) diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts index 05a4a80862..ed1df73569 100644 --- a/packages/backend/src/core/entities/MetaEntityService.ts +++ b/packages/backend/src/core/entities/MetaEntityService.ts @@ -51,8 +51,8 @@ export class MetaEntityService { .getMany(); // クライアントの手間を減らすためあらかじめJSONに変換しておく - let defaultLightTheme = null; - let defaultDarkTheme = null; + let defaultLightTheme: string | null = null; + let defaultDarkTheme: string | null = null; if (instance.defaultLightTheme) { try { defaultLightTheme = JSON.stringify(JSON5.parse(instance.defaultLightTheme)); diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index 2778967aa0..3efc9cb27a 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -491,7 +491,7 @@ export class NoteEntityService implements OnModuleInit { @bindThis public async packAttachedFiles(fileIds: MiNote['fileIds'], packedFiles: Map | null>): Promise[]> { - const missingIds = []; + const missingIds: string[] = []; for (const id of fileIds) { if (!packedFiles.has(id)) missingIds.push(id); } diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index 264d66aec1..34fdffb430 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -232,7 +232,7 @@ export class NotificationEntityService implements OnModuleInit { validNotifications = validNotifications.filter(x => !('noteId' in x) || packedNotes.has(x.noteId)); - const userIds = []; + const userIds: string[] = []; for (const notification of validNotifications) { if ('notifierId' in notification) userIds.push(notification.notifierId); if (notification.type === 'reaction:grouped') userIds.push(...notification.reactions.map(x => x.userId)); diff --git a/packages/backend/src/misc/bigint.ts b/packages/backend/src/misc/bigint.ts index efa1527ec9..58603400b2 100644 --- a/packages/backend/src/misc/bigint.ts +++ b/packages/backend/src/misc/bigint.ts @@ -4,7 +4,7 @@ */ function parseBigIntChunked(str: string, base: number, chunkSize: number, powerOfChunkSize: bigint): bigint { - const chunks = []; + const chunks: string[] = []; while (str.length > 0) { chunks.unshift(str.slice(-chunkSize)); str = str.slice(0, -chunkSize); diff --git a/packages/backend/src/misc/generate-invite-code.ts b/packages/backend/src/misc/generate-invite-code.ts index 8a23175a65..377215fd30 100644 --- a/packages/backend/src/misc/generate-invite-code.ts +++ b/packages/backend/src/misc/generate-invite-code.ts @@ -12,7 +12,7 @@ export function generateInviteCode(now: number): string { chars: CHARS, }); - const uniqueId = []; + const uniqueId: string[] = []; let n = Math.floor(now / 1000 / 60); while (true) { uniqueId.push(CHARS[n % CHARS.length]); diff --git a/packages/backend/src/misc/prelude/array.ts b/packages/backend/src/misc/prelude/array.ts index f741a0c913..95ec9c65ed 100644 --- a/packages/backend/src/misc/prelude/array.ts +++ b/packages/backend/src/misc/prelude/array.ts @@ -80,7 +80,7 @@ export function lessThan(xs: number[], ys: number[]): boolean { * Returns the longest prefix of elements that satisfy the predicate */ export function takeWhile(f: Predicate, xs: T[]): T[] { - const ys = []; + const ys: T[] = []; for (const x of xs) { if (f(x)) { ys.push(x); diff --git a/packages/backend/src/misc/verify-field-link.ts b/packages/backend/src/misc/verify-field-link.ts index 31a356be37..bc79ad6cb6 100644 --- a/packages/backend/src/misc/verify-field-link.ts +++ b/packages/backend/src/misc/verify-field-link.ts @@ -9,7 +9,7 @@ import type { HttpRequestService } from '@/core/HttpRequestService.js'; type Field = { name: string, value: string }; export async function verifyFieldLinks(fields: Field[], profileUrls: string[], httpRequestService: HttpRequestService): Promise { - const verified_links = []; + const verified_links: string[] = []; for (const field_url of fields) { try { // getHtml validates the input URL, so we can safely pass in untrusted values diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index 0cfd408219..12c1bd1fdc 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -149,7 +149,7 @@ class TypeORMLogger implements Logger { @bindThis private transformParameters(parameters?: unknown[]): Data | undefined { if (this.props.enableQueryParamLogging && parameters && parameters.length > 0) { - return parameters.reduce((params: Record, p, i) => { + return parameters.reduce>((params: Record, p, i) => { params[`$${i + 1}`] = stringifyParameter(p); return params; }, {} as Record); diff --git a/packages/backend/src/queue/processors/ImportNotesProcessorService.ts b/packages/backend/src/queue/processors/ImportNotesProcessorService.ts index d326854b37..6f5e929673 100644 --- a/packages/backend/src/queue/processors/ImportNotesProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportNotesProcessorService.ts @@ -397,7 +397,7 @@ export class ImportNotesProcessorService { const visibility = followers ? toot.cc.includes('https://www.w3.org/ns/activitystreams#Public') ? 'home' : 'followers' : 'public'; const date = new Date(toot.object.published); - let text = undefined; + let text: string | undefined = undefined; const files: MiDriveFile[] = []; let reply: MiNote | null = null; @@ -464,7 +464,7 @@ export class ImportNotesProcessorService { } const date = new Date(post.object.published); - let text = undefined; + let text: string | undefined = undefined; const files: MiDriveFile[] = []; let reply: MiNote | null = null; @@ -547,7 +547,7 @@ export class ImportNotesProcessorService { const files: MiDriveFile[] = []; function decodeIGString(str: string) { - const arr = []; + const arr: number[] = []; for (let i = 0; i < str.length; i++) { arr.push(str.charCodeAt(i)); } @@ -700,7 +700,7 @@ export class ImportNotesProcessorService { const files: MiDriveFile[] = []; function decodeFBString(str: string) { - const arr = []; + const arr: number[] = []; for (let i = 0; i < str.length; i++) { arr.push(str.charCodeAt(i)); } @@ -708,7 +708,7 @@ export class ImportNotesProcessorService { } if (post.attachments && this.isIterable(post.attachments)) { - const media = []; + const media: any[] = []; for await (const data of post.attachments[0].data) { if (data.media) { media.push(data.media); diff --git a/packages/backend/src/server/api/endpoints/admin/captcha/current.ts b/packages/backend/src/server/api/endpoints/admin/captcha/current.ts index 41192c1926..7cc1bc675a 100644 --- a/packages/backend/src/server/api/endpoints/admin/captcha/current.ts +++ b/packages/backend/src/server/api/endpoints/admin/captcha/current.ts @@ -63,7 +63,11 @@ export const meta = { }, } as const; -export const paramDef = {} as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/admin/cw-instance.ts b/packages/backend/src/server/api/endpoints/admin/cw-instance.ts index 5e5d83283e..c7df9ee588 100644 --- a/packages/backend/src/server/api/endpoints/admin/cw-instance.ts +++ b/packages/backend/src/server/api/endpoints/admin/cw-instance.ts @@ -14,8 +14,6 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'write:admin:cw-instance', - - res: {}, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/cw-note.ts b/packages/backend/src/server/api/endpoints/admin/cw-note.ts index ba2240b8b2..92071abaf1 100644 --- a/packages/backend/src/server/api/endpoints/admin/cw-note.ts +++ b/packages/backend/src/server/api/endpoints/admin/cw-note.ts @@ -19,8 +19,6 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'write:admin:cw-note', - - res: {}, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/cw-user.ts b/packages/backend/src/server/api/endpoints/admin/cw-user.ts index a7cd2af235..ecb4512fc9 100644 --- a/packages/backend/src/server/api/endpoints/admin/cw-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/cw-user.ts @@ -17,8 +17,6 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'write:admin:cw-user', - - res: {}, } as const; export const paramDef = { @@ -63,6 +61,8 @@ export default class extends Endpoint { // eslint- userUsername: user.username, userHost: user.host, }); + + return {}; }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts index a7136d8c8c..361a7d7f95 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts @@ -167,6 +167,7 @@ export const paramDef = { fileId: { type: 'string', format: 'misskey:id' }, url: { type: 'string' }, }, + // TODO it chokes on this anyOf: [ { required: ['fileId'] }, { required: ['url'] }, diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index 492122422c..c924684e75 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -102,8 +102,6 @@ export default class extends Endpoint { // eslint- case 'NO_SUCH_EMOJI': throw new ApiError(meta.errors.noSuchEmoji); case 'SAME_NAME_EMOJI_EXISTS': throw new ApiError(meta.errors.sameNameEmojiExists); } - // 網羅性チェック - const mustBeNever: never = error; }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/gen-vapid-keys.ts b/packages/backend/src/server/api/endpoints/admin/gen-vapid-keys.ts index 85e3cd0477..9e4b87f674 100644 --- a/packages/backend/src/server/api/endpoints/admin/gen-vapid-keys.ts +++ b/packages/backend/src/server/api/endpoints/admin/gen-vapid-keys.ts @@ -17,7 +17,11 @@ export const meta = { kind: 'write:admin:meta', } as const; -export const paramDef = {} as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export diff --git a/packages/backend/src/server/api/endpoints/admin/invite/create.ts b/packages/backend/src/server/api/endpoints/admin/invite/create.ts index c6bb4086ed..ff9742706f 100644 --- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { RegistrationTicketsRepository } from '@/models/_.js'; +import type { RegistrationTicketsRepository, MiRegistrationTicket } from '@/models/_.js'; import { InviteCodeEntityService } from '@/core/entities/InviteCodeEntityService.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; @@ -65,7 +65,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.invalidDateTime); } - const ticketsPromises = []; + const ticketsPromises: Promise[] = []; for (let i = 0; i < ps.count; i++) { ticketsPromises.push(this.registrationTicketsRepository.insertOne({ diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts index e3a6d2d670..8437f9f060 100644 --- a/packages/backend/src/server/api/endpoints/channels/create.ts +++ b/packages/backend/src/server/api/endpoints/channels/create.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { ChannelsRepository, DriveFilesRepository } from '@/models/_.js'; +import type { ChannelsRepository, DriveFilesRepository, MiDriveFile } from '@/models/_.js'; import type { MiChannel } from '@/models/Channel.js'; import { IdService } from '@/core/IdService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; @@ -68,7 +68,7 @@ export default class extends Endpoint { // eslint- private channelEntityService: ChannelEntityService, ) { super(meta, paramDef, async (ps, me) => { - let banner = null; + let banner: MiDriveFile | null = null; if (ps.bannerId != null) { banner = await this.driveFilesRepository.findOneBy({ id: ps.bannerId, diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts index 7cca688fda..01166f7897 100644 --- a/packages/backend/src/server/api/endpoints/channels/update.ts +++ b/packages/backend/src/server/api/endpoints/channels/update.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFilesRepository, ChannelsRepository } from '@/models/_.js'; +import type { DriveFilesRepository, ChannelsRepository, MiDriveFile } from '@/models/_.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; import { DI } from '@/di-symbols.js'; import { RoleService } from '@/core/RoleService.js'; @@ -99,8 +99,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.accessDenied); } - // eslint:disable-next-line:no-unnecessary-initializer - let banner = undefined; + let banner: MiDriveFile | null = null; if (ps.bannerId != null) { banner = await this.driveFilesRepository.findOneBy({ id: ps.bannerId, diff --git a/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts b/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts index 0afd3b1ccb..624a1985bd 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/create-to-room.ts @@ -10,7 +10,7 @@ import { GetterService } from '@/server/api/GetterService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { ChatService } from '@/core/ChatService.js'; -import type { DriveFilesRepository, MiUser } from '@/models/_.js'; +import type { DriveFilesRepository, MiUser, MiDriveFile } from '@/models/_.js'; import type { Config } from '@/config.js'; export const meta = { @@ -96,7 +96,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.noSuchRoom); } - let file = null; + let file: MiDriveFile | null = null; if (ps.fileId != null) { file = await this.driveFilesRepository.findOneBy({ id: ps.fileId, diff --git a/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts b/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts index 83a83e0d1f..0dbcbbfe77 100644 --- a/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts +++ b/packages/backend/src/server/api/endpoints/chat/messages/create-to-user.ts @@ -10,7 +10,7 @@ import { GetterService } from '@/server/api/GetterService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { ChatService } from '@/core/ChatService.js'; -import type { DriveFilesRepository, MiUser } from '@/models/_.js'; +import type { DriveFilesRepository, MiUser, MiDriveFile } from '@/models/_.js'; import type { Config } from '@/config.js'; export const meta = { @@ -103,7 +103,7 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.maxLength); } - let file = null; + let file: MiDriveFile | null = null; if (ps.fileId != null) { file = await this.driveFilesRepository.findOneBy({ id: ps.fileId, diff --git a/packages/backend/src/server/api/endpoints/drive/folders/create.ts b/packages/backend/src/server/api/endpoints/drive/folders/create.ts index 08d9d9cdc3..bbe26d7554 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts @@ -6,7 +6,7 @@ import { Inject, Injectable } from '@nestjs/common'; import ms from 'ms'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DriveFoldersRepository } from '@/models/_.js'; +import type { DriveFoldersRepository, MiDriveFolder } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { DriveFolderEntityService } from '@/core/entities/DriveFolderEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; @@ -61,7 +61,7 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { // If the parent folder is specified - let parent = null; + let parent: MiDriveFolder | null = null; if (ps.parentId) { // Fetch parent folder parent = await this.driveFoldersRepository.findOneBy({ diff --git a/packages/backend/src/server/api/endpoints/i/registry/get.ts b/packages/backend/src/server/api/endpoints/i/registry/get.ts index d284334834..69215e12ce 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get.ts @@ -20,8 +20,6 @@ export const meta = { }, }, - res: {}, - // 10 calls per 5 seconds limit: { duration: 1000 * 5, diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index 2be2a22cfe..5931003747 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -5,7 +5,7 @@ import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; -import type { DriveFilesRepository, PagesRepository } from '@/models/_.js'; +import type { DriveFilesRepository, PagesRepository, MiDriveFile } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { MiPage, pageNameSchema } from '@/models/Page.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; @@ -83,7 +83,7 @@ export default class extends Endpoint { // eslint- private readonly timeService: TimeService, ) { super(meta, paramDef, async (ps, me) => { - let eyeCatchingImage = null; + let eyeCatchingImage: MiDriveFile | null = null; if (ps.eyeCatchingImageId != null) { eyeCatchingImage = await this.driveFilesRepository.findOneBy({ id: ps.eyeCatchingImageId, diff --git a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts index 072dacf708..1d2a1db625 100644 --- a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts +++ b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts @@ -3,6 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { createReadStream } from 'node:fs'; +import { Readable } from 'node:stream'; import { Injectable } from '@nestjs/common'; import { bindThis } from '@/decorators.js'; import { getErrorData, getErrorException, getErrorStatus, MastodonLogger } from '@/server/api/mastodon/MastodonLogger.js'; @@ -118,7 +120,10 @@ export class MastodonApiServerService { } const client = this.clientService.getClient(_request); - const data = await client.uploadMedia(multipartData); + const data = await client.uploadMedia({ + ...multipartData, + stream: Readable.toWeb(createReadStream(multipartData.filepath)), + }); const response = convertAttachment(data.data as Entity.Attachment); return reply.send(response); @@ -131,7 +136,10 @@ export class MastodonApiServerService { } const client = this.clientService.getClient(_request); - const data = await client.uploadMedia(multipartData, _request.body); + const data = await client.uploadMedia({ + ...multipartData, + stream: Readable.toWeb(createReadStream(multipartData.filepath)), + }, _request.body); const response = convertAttachment(data.data as Entity.Attachment); return reply.send(response); diff --git a/packages/backend/src/server/api/mastodon/MastodonConverters.ts b/packages/backend/src/server/api/mastodon/MastodonConverters.ts index 84cf07c2ed..6b0283bf55 100644 --- a/packages/backend/src/server/api/mastodon/MastodonConverters.ts +++ b/packages/backend/src/server/api/mastodon/MastodonConverters.ts @@ -6,8 +6,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { Entity, MastodonEntity, MisskeyEntity } from 'megalodon'; import * as mfm from 'mfm-js'; -import { MastodonNotificationType } from 'megalodon/lib/src/mastodon/notification.js'; -import { NotificationType } from 'megalodon/lib/src/notification.js'; +import { MastodonNotificationType } from 'megalodon/built/lib/mastodon/notification.js'; +import { NotificationType } from 'megalodon/built/lib/notification.js'; import { DI } from '@/di-symbols.js'; import { MfmService } from '@/core/MfmService.js'; import type { Config } from '@/config.js'; diff --git a/packages/backend/src/server/web/bios.js b/packages/backend/src/server/web/bios.js index 5dbb26f9e3..e0f0907b67 100644 --- a/packages/backend/src/server/web/bios.js +++ b/packages/backend/src/server/web/bios.js @@ -8,8 +8,8 @@ window.onload = async () => { const content = document.getElementById('content'); - document.getElementById('ls').addEventListener('click', () => { - content.innerHTML = ''; + document.getElementById('ls')?.addEventListener('click', () => { + if (content) content.innerHTML = ''; const lsEditor = document.createElement('div'); lsEditor.id = 'lsEditor'; @@ -31,7 +31,7 @@ window.onload = async () => { lsEditor.appendChild(adder); for (let i = 0; i < localStorage.length; i++) { - const k = localStorage.key(i); + const k = /** @type {string} */ (localStorage.key(i)); const record = document.createElement('div'); record.classList.add('record'); const header = document.createElement('header'); @@ -57,6 +57,6 @@ window.onload = async () => { lsEditor.appendChild(record); } - content.appendChild(lsEditor); + content?.appendChild(lsEditor); }); }; diff --git a/packages/backend/src/server/web/boot.embed.js b/packages/backend/src/server/web/boot.embed.js index 97eb6ef458..5aa326dc71 100644 --- a/packages/backend/src/server/web/boot.embed.js +++ b/packages/backend/src/server/web/boot.embed.js @@ -43,6 +43,7 @@ //#region Detect language & fetch translations if (!localStorage.getItem('locale')) { const supportedLangs = LANGS; + /** @type {string | null | undefined} */ let lang = localStorage.getItem('lang'); if (lang == null || !supportedLangs.includes(lang)) { if (supportedLangs.includes(navigator.language)) { @@ -92,12 +93,20 @@ } //#endregion + /** + * @param {string} styleText + * @returns {Promise} + */ async function addStyle(styleText) { let css = document.createElement('style'); css.appendChild(document.createTextNode(styleText)); document.head.appendChild(css); } + /** + * @param {string} code + * @returns {Promise} + */ async function renderError(code) { // Cannot set property 'innerHTML' of null を回避 if (document.readyState === 'loading') { diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index c10f6a54ae..81ceec1f12 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -34,6 +34,7 @@ //#region Detect language & fetch translations if (!localStorage.getItem('locale')) { const supportedLangs = LANGS; + /** @type {string | null | undefined} */ let lang = localStorage.getItem('lang'); if (lang == null || !supportedLangs.includes(lang)) { if (supportedLangs.includes(navigator.language)) { @@ -154,12 +155,21 @@ document.head.appendChild(style); } + /** + * @param {string} styleText + * @returns {Promise} + */ async function addStyle(styleText) { let css = document.createElement('style'); css.appendChild(document.createTextNode(styleText)); document.head.appendChild(css); } + /** + * @param {string} code + * @param {any} [details] + * @returns {Promise} + */ async function renderError(code, details) { // Cannot set property 'innerHTML' of null を回避 if (document.readyState === 'loading') { @@ -233,7 +243,7 @@ ERROR CODE: ${code} ${details.toString()} ${JSON.stringify(details)}`; - errorsElement.appendChild(detailsElement); + errorsElement?.appendChild(detailsElement); addStyle(` * { font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif; diff --git a/packages/backend/src/server/web/cli.js b/packages/backend/src/server/web/cli.js index 03e0701b32..5322ac7ab5 100644 --- a/packages/backend/src/server/web/cli.js +++ b/packages/backend/src/server/web/cli.js @@ -6,9 +6,15 @@ 'use strict'; window.onload = async () => { - const account = JSON.parse(localStorage.getItem('account')); - const i = account.token; + const accountRaw = localStorage.getItem('account'); + const account = accountRaw ? JSON.parse(accountRaw) : null; + const i = account?.token; + /** + * @param {string} endpoint + * @param {Record} data + * @returns {Promise} + */ const api = (endpoint, data = {}) => { const promise = new Promise((resolve, reject) => { // Append a credential @@ -17,19 +23,19 @@ window.onload = async () => { // Send request fetch(endpoint.indexOf('://') > -1 ? endpoint : `/api/${endpoint}`, { headers: { - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', }, method: 'POST', body: JSON.stringify(data), credentials: 'omit', - cache: 'no-cache' + cache: 'no-cache', }).then(async (res) => { const body = res.status === 204 ? null : await res.json(); if (res.status === 200) { resolve(body); } else if (res.status === 204) { - resolve(); + resolve({}); } else { reject(body.error); } @@ -39,7 +45,7 @@ window.onload = async () => { return promise; }; - document.getElementById('submit').addEventListener('click', () => { + document.getElementById('submit')?.addEventListener('click', () => { api('notes/create', { text: (/** @type {HTMLInputElement} */(document.getElementById('text'))).value }).then(() => { @@ -49,6 +55,7 @@ window.onload = async () => { api('notes/timeline').then(notes => { const tl = document.getElementById('tl'); + if (!tl) return; for (const note of notes) { const el = document.createElement('div'); const name = document.createElement('header'); diff --git a/packages/backend/test-federation/tsconfig.json b/packages/backend/test-federation/tsconfig.json index c6b1ba2ae8..b20788831c 100644 --- a/packages/backend/test-federation/tsconfig.json +++ b/packages/backend/test-federation/tsconfig.json @@ -1,15 +1,19 @@ { - "extends": "../../shared/tsconfig.node.json", + "extends": "../../shared/tsconfig.node.jsonc", "compilerOptions": { + // Checking "types": ["jest", "node"], "verbatimModuleSyntax": false, - "outDir": "./built", + "noImplicitOverride": false, + "noImplicitAny": false, + "strictFunctionTypes": false, + "strictPropertyInitialization": false, "paths": { "@/*": ["../src/*"] }, - "typeRoots": [ - "../node_modules/@types" - ] + + // Output + "outDir": "./built" }, "include": [ "daemon.ts", diff --git a/packages/backend/test-server/tsconfig.json b/packages/backend/test-server/tsconfig.json index 5472c60509..50a1108937 100644 --- a/packages/backend/test-server/tsconfig.json +++ b/packages/backend/test-server/tsconfig.json @@ -5,12 +5,7 @@ "paths": { "@/*": ["../src/*"] }, - "outDir": "../built-test", - "typeRoots": [ - "../src/@types", - "../node_modules/@types", - "../node_modules" - ] + "outDir": "../built-test" }, "include": [ "./**/*.ts", diff --git a/packages/backend/test/e2e/oauth.ts b/packages/backend/test/e2e/oauth.ts index 97830bc987..810b5ca434 100644 --- a/packages/backend/test/e2e/oauth.ts +++ b/packages/backend/test/e2e/oauth.ts @@ -153,13 +153,14 @@ async function assertDirectError(response: Response, status: number, error: stri } describe('OAuth', () => { - test('fake pass', () => { - assert.ok(true, 'fake pass'); - }); + test('fake pass', () => { + assert.ok(true, 'fake pass'); + }); }); // these tests won't pass until we integrate Misskey's OAuth code with ours -if (false) describe('OAuth', () => { +/* +describe('OAuth', () => { let fastify: FastifyInstance; let alice: misskey.entities.SignupResponse; @@ -1025,3 +1026,4 @@ if (false) describe('OAuth', () => { }); }); }); + */ diff --git a/packages/backend/test/tsconfig.json b/packages/backend/test/tsconfig.json index 74376f3a78..1591bd6dcb 100644 --- a/packages/backend/test/tsconfig.json +++ b/packages/backend/test/tsconfig.json @@ -1,18 +1,19 @@ { - "extends": "../../shared/tsconfig.node.json", + "extends": "../../shared/tsconfig.node.jsonc", "compilerOptions": { + // Checking "types": ["jest", "node"], - "outDir": "./built", - "sourceMap": true, "verbatimModuleSyntax": false, - "removeComments": false, + "noImplicitOverride": false, + "noImplicitAny": false, + "strictFunctionTypes": false, + "strictPropertyInitialization": false, "paths": { "@/*": ["../src/*"] }, - "typeRoots": [ - "../node_modules/@types", - "../src/@types" - ] + + // Output + "outDir": "./built" }, "include": [ "./**/*.ts", diff --git a/packages/backend/tsconfig.backend.json b/packages/backend/tsconfig.backend.json index 53a0136cfd..bab1ba2ad9 100644 --- a/packages/backend/tsconfig.backend.json +++ b/packages/backend/tsconfig.backend.json @@ -1,19 +1,24 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "extends": "../shared/tsconfig.node.json", + "extends": "../shared/tsconfig.node.jsonc", "compilerOptions": { - "removeComments": false, - "verbatimModuleSyntax": false, + // Input "rootDir": "./src", - "outDir": "./built", + + // Checking + "verbatimModuleSyntax": false, + "noImplicitOverride": false, + "noImplicitAny": false, + "strictFunctionTypes": false, + "strictPropertyInitialization": false, + "paths": { "@/*": ["./src/*"] }, - "typeRoots": [ - "./src/@types", - "./node_modules/@types", - "./node_modules" - ], + + // Output + "removeComments": false, + "outDir": "./built" }, "include": [ "./src/**/*.ts" diff --git a/packages/backend/jsconfig.frontend.json b/packages/backend/tsconfig.frontend.json similarity index 53% rename from packages/backend/jsconfig.frontend.json rename to packages/backend/tsconfig.frontend.json index 3354f1e464..cb7a8e1a1d 100644 --- a/packages/backend/jsconfig.frontend.json +++ b/packages/backend/tsconfig.frontend.json @@ -1,5 +1,8 @@ { - "extends": "../shared/jsconfig.web.json", + "extends": "../shared/tsconfig.web.jsonc", + "compilerOptions": { + "noEmit": true, + }, "include": [ "./assets/**/*.js", "./assets/**/*.mjs", @@ -11,14 +14,14 @@ "./src/server/web/**/*.d.ts" ], "exclude": [ - "**/node_modules/**/*", - "**/built/**/*", - "./jspm_packages", - "./tmp", - "./temp", - "./test", - "./test-federation", - "./test-server", - "**/coverage/**/*" + "node_modules", + "built", + "built-test", + "js-built", + "temp", + "coverage", + "test", + "test-federation", + "test-server" ] } diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json index 8bb0f921ee..eece3feb07 100644 --- a/packages/backend/tsconfig.json +++ b/packages/backend/tsconfig.json @@ -5,6 +5,6 @@ "references": [ { "path": "./tsconfig.scripts.json" }, { "path": "./tsconfig.backend.json" }, - { "path": "./jsconfig.frontend.json" } + { "path": "./tsconfig.frontend.json" } ] } diff --git a/packages/backend/tsconfig.scripts.json b/packages/backend/tsconfig.scripts.json index 2f056cb0a4..97dcf29e00 100644 --- a/packages/backend/tsconfig.scripts.json +++ b/packages/backend/tsconfig.scripts.json @@ -1,17 +1,18 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "extends": "../shared/tsconfig.node.json", - "compilerOptions": { - "noImplicitAny": false, - "allowImportingTsExtensions": true, - "noEmit": true - }, + "extends": "../shared/tsconfig.scripts.jsonc", "include": [ "jest.*", "eslint.*", "scripts/**/*" ], "exclude": [ + "node_modules", + "built", + "built-test", + "js-built", + "temp", + "coverage", "ormconfig.js", "scripts/check_connect.js", "scripts/generate_api_json.js"