diff --git a/packages/misskey-js/api-extractor.json b/packages/misskey-js/api-extractor.json index 35c2b09a9c..9659d250df 100644 --- a/packages/misskey-js/api-extractor.json +++ b/packages/misskey-js/api-extractor.json @@ -79,7 +79,7 @@ * SUPPORTED TOKENS: , , * DEFAULT VALUE: "/tsconfig.json" */ - // "tsconfigFilePath": "/tsconfig.json", + "tsconfigFilePath": "/tsconfig.lib.json", /** * Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk. * The object must conform to the TypeScript tsconfig schema: diff --git a/packages/misskey-js/eslint.config.js b/packages/misskey-js/eslint.config.js index f355ed4afe..8c3d08fc5b 100644 --- a/packages/misskey-js/eslint.config.js +++ b/packages/misskey-js/eslint.config.js @@ -1,4 +1,5 @@ import tsParser from '@typescript-eslint/parser'; +import globals from 'globals'; import sharedConfig from '../shared/eslint.config.js'; // eslint-disable-next-line import/no-default-export @@ -6,35 +7,60 @@ export default [ ...sharedConfig, { ignores: [ - '**/node_modules', - 'built', - 'coverage', - 'jest.config.ts', - 'test', - 'test-d', 'generator', '**/lib/', '**/temp/', '**/built/', '**/coverage/', '**/node_modules/', - 'scripts', - '*.*', ], }, { - files: ['src/**/*.ts', 'test/**/*.ts'], + files: ['src/**/*.ts'], languageOptions: { parserOptions: { parser: tsParser, - project: ['./tsconfig.json'], + project: ['./tsconfig.lib.json'], sourceType: 'module', tsconfigRootDir: import.meta.dirname, }, }, }, { - files: ['scripts/**/*.mjs'], + files: ['test/**/*.ts'], + languageOptions: { + parserOptions: { + parser: tsParser, + projectService: ['./tsconfig.test.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, + { + files: ['test-d/**/*.ts'], + languageOptions: { + parserOptions: { + parser: tsParser, + projectService: ['./tsconfig.test-d.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, + { + files: ['*.ts', '*.js', 'scripts/**/*'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.scripts.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + globals: { + ...globals.node, + }, + }, }, { files: ['src/autogen/**/*.ts', 'src/autogen/**/*.tsx'], diff --git a/packages/misskey-js/generator/eslint.config.js b/packages/misskey-js/generator/eslint.config.js index 2bfcc7f26e..bb6fd7a6b3 100644 --- a/packages/misskey-js/generator/eslint.config.js +++ b/packages/misskey-js/generator/eslint.config.js @@ -4,11 +4,11 @@ import sharedConfig from '../../shared/eslint.config.js'; export default [ ...sharedConfig, { - files: ['**/*.ts', '**/*.tsx'], + files: ['src/**/*.ts', 'src/**/*.tsx'], languageOptions: { parserOptions: { parser: tsParser, - project: ['./tsconfig.json'], + project: ['./tsconfig.generator.json'], sourceType: 'module', tsconfigRootDir: import.meta.dirname, }, @@ -16,14 +16,32 @@ export default [ }, { files: ['built/autogen/**.ts'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.autogen.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, rules: { '@stylistic/indent': 'off', }, }, + { + files: ['*.js'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./jsconfig.scripts.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, { ignores: [ '**/node_modules', - '*.*', ], }, ]; diff --git a/packages/misskey-js/generator/jsconfig.scripts.json b/packages/misskey-js/generator/jsconfig.scripts.json new file mode 100644 index 0000000000..5bf3d9a2d2 --- /dev/null +++ b/packages/misskey-js/generator/jsconfig.scripts.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../../shared/jsconfig.node.json", + "compilerOptions": { + "typeRoots": [ + "./node_modules/@types" + ] + }, + "include": [ + "*.js" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/packages/misskey-js/generator/package.json b/packages/misskey-js/generator/package.json index 8ab5b1baa5..d5fef55e44 100644 --- a/packages/misskey-js/generator/package.json +++ b/packages/misskey-js/generator/package.json @@ -4,7 +4,14 @@ "description": "Misskey TypeGenerator", "type": "module", "scripts": { - "generate": "tsx src/generator.ts && eslint ./built/**/*.ts --fix --cache" + "generate": "tsx src/generator.ts && eslint ./built/**/*.ts --fix --cache", + "eslint": "eslint --quiet --cache -c eslint.config.js .", + "typecheck-all": "pnpm run --no-bail typecheck:generator && pnpm run --no-bail typecheck:autogen && pnpm run --no-bail typecheck:scripts", + "typecheck": "pnpm run typecheck:generator && pnpm run typecheck:autogen && pnpm run typecheck:scripts", + "typecheck:generator": "tsc -p tsconfig.generator.json --noEmit", + "typecheck:autogen": "tsc -p tsconfig.autogen.json --noEmit", + "typecheck:scripts": "tsc -p jsconfig.scripts.json --noEmit", + "lint": "pnpm typecheck && pnpm eslint" }, "devDependencies": { "@readme/openapi-parser": "5.0.1", diff --git a/packages/misskey-js/generator/src/generator.ts b/packages/misskey-js/generator/src/generator.ts index d4aacd884f..0bd62c19ba 100644 --- a/packages/misskey-js/generator/src/generator.ts +++ b/packages/misskey-js/generator/src/generator.ts @@ -1,11 +1,11 @@ import assert from 'assert'; import { mkdir, readFile, writeFile } from 'fs/promises'; -import { OpenAPIV3_1 } from 'openapi-types'; import { toPascal } from 'ts-case-convert'; import * as OpenAPIParser from '@readme/openapi-parser'; -import openapiTS, { astToString, OpenAPI3, OperationObject, PathItemObject } from 'openapi-typescript'; +import openapiTS, { astToString, type OpenAPI3, type OperationObject, type PathItemObject } from 'openapi-typescript'; import ts from 'typescript'; import { createConfig } from '@redocly/openapi-core'; +import type { OpenAPIV3_1 } from 'openapi-types'; async function generateBaseTypes( openApiDocs: OpenAPIV3_1.Document, @@ -64,6 +64,7 @@ async function generateBaseTypes( if ('format' in schemaObject && schemaObject.format === 'binary') { return schemaObject.nullable ? ts.factory.createUnionTypeNode([BLOB, NULL]) : BLOB; } + return undefined; }, }); @@ -115,7 +116,7 @@ async function generateSchemaEntities( const schemaNames = Object.keys(schemas); const typeAliasLines: string[] = []; - typeAliasLines.push(`import { components } from '${toImportPath(typeFileName)}';`); + typeAliasLines.push(`import type { components } from '${toImportPath(typeFileName)}';`); typeAliasLines.push( ...schemaNames.map(it => `export type ${it} = components['schemas']['${it}'];`), ); @@ -190,7 +191,7 @@ async function generateEndpoints( entitiesOutputLine.push('/* eslint @typescript-eslint/naming-convention: 0 */'); - entitiesOutputLine.push(`import { operations } from '${toImportPath(typeFileName)}';`); + entitiesOutputLine.push(`import type { operations } from '${toImportPath(typeFileName)}';`); entitiesOutputLine.push(''); entitiesOutputLine.push(new EmptyTypeAlias(OperationsAliasType.REQUEST).toLine()); diff --git a/packages/misskey-js/generator/tsconfig.autogen.json b/packages/misskey-js/generator/tsconfig.autogen.json new file mode 100644 index 0000000000..b143f440f1 --- /dev/null +++ b/packages/misskey-js/generator/tsconfig.autogen.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../../shared/tsconfig.web.json", + "compilerOptions": { + "noImplicitAny": false, + "isolatedModules": false, + "rootDirs": [ + "built", + "../built" + ] + }, + "include": [ + "built/autogen/**/*.ts" + ], + "exclude": [ + "node_modules", + "./built/**/*.js" + ] +} diff --git a/packages/misskey-js/generator/tsconfig.generator.json b/packages/misskey-js/generator/tsconfig.generator.json new file mode 100644 index 0000000000..f7c54755fe --- /dev/null +++ b/packages/misskey-js/generator/tsconfig.generator.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../../shared/tsconfig.node.json", + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules", + "./built/**/*.js" + ] +} diff --git a/packages/misskey-js/generator/tsconfig.json b/packages/misskey-js/generator/tsconfig.json index a55249e878..73a6ed5189 100644 --- a/packages/misskey-js/generator/tsconfig.json +++ b/packages/misskey-js/generator/tsconfig.json @@ -1,25 +1,10 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "nodenext", - "strict": true, - "strictFunctionTypes": true, - "strictNullChecks": true, - "skipLibCheck": true, - "esModuleInterop": true, - "incremental": true, - "lib": [ - "esnext", - ] - }, - "include": [ - "src/**/*.ts", - "built/autogen/**/*.ts" - ], - "exclude": [ - "node_modules", - "./built/**/*.js" + "files": [], + // WebStorm only reads one tsconfig per directory, so this tricks it into loading both. + "references": [ + { "path": "./tsconfig.generator.json" }, + { "path": "./tsconfig.autogen.json" }, + { "path": "./jsconfig.scripts.json" } ] } diff --git a/packages/misskey-js/jest.config.ts b/packages/misskey-js/jest.config.ts new file mode 100644 index 0000000000..cca319c457 --- /dev/null +++ b/packages/misskey-js/jest.config.ts @@ -0,0 +1,238 @@ +/* +* For a detailed explanation regarding each configuration property and type check, visit: +* https://jestjs.io/docs/en/configuration.html +*/ + +// https://kulshekhar.github.io/ts-jest/docs/getting-started/presets#createdefaultesmpresetoptions +import { createDefaultEsmPreset, type JestConfigWithTsJest } from 'ts-jest'; + +const presetConfig = createDefaultEsmPreset({ + tsconfig: '/tsconfig.lib.json' +}); + +export default { + ...presetConfig, + + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "C:\\Users\\ai\\AppData\\Local\\Temp\\jest", + + // Automatically clear mock calls and instances between every test + // clearMocks: false, + + // Indicates whether the coverage information should be collected while executing the test + // collectCoverage: false, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + collectCoverageFrom: ['src/**/*.ts'], + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: { + // }, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "json", + // "jsx", + // "ts", + // "tsx", + // "node" + // ], + moduleFileExtensions: [ + "ts", + "js" + ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + moduleNameMapper: { + // Do not resolve .wasm.js to .wasm by the rule below + '^(.+)\\.wasm\\.js$': '$1.wasm.js', + // SWC converts @/foo/bar.js to `../../src/foo/bar.js`, and then this rule + // converts it again to `../../src/foo/bar` which then can be resolved to + // `.ts` files. + // See https://github.com/swc-project/jest/issues/64#issuecomment-1029753225 + // TODO: Use `--allowImportingTsExtensions` on TypeScript 5.0 so that we can + // directly import `.ts` files without this hack. + '^((?:\\.{1,2}|[A-Z:])*/.*)\\.js$': '$1', + }, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + //preset: "ts-jest/presets/js-with-ts-esm", + // "preset": "ts-jest/presets/default", + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state between every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: './jest-resolver.cjs', + + // Automatically restore mock state between every test + restoreMocks: true, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + roots: [ + "/test" + ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: "node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + testMatch: [ + "/test/**/*.ts" + ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "\\\\node_modules\\\\" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jasmine2", + + // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href + // testURL: "http://localhost", + + // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" + // timers: "real", + + // A map from regular expressions to paths to transformers + // transform: { + // "^.+\\.(ts|tsx)$": [ + // "ts-jest", + // { + // "tsconfig": "tsconfig.json" + // } + // ] + // }, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "\\\\node_modules\\\\", + // "\\.pnp\\.[^\\\\]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, + + // extensionsToTreatAsEsm: ['.ts'], + + // testTimeout: 60000, + + // // Let Jest kill the test worker whenever it grows too much + // // (It seems there's a known memory leak issue in Node.js' vm.Script used by Jest) + // // https://github.com/facebook/jest/issues/11956 + // maxWorkers: 1, // Make it use worker (that can be killed and restarted) + // logHeapUsage: true, // To debug when out-of-memory happens on CI + // workerIdleMemoryLimit: '1GiB', // Limit the worker to 1GB (GitHub Workflows dies at 2GB) + // + // maxConcurrency: 32, +} satisfies JestConfigWithTsJest; diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index c08b261e20..8c78d409bd 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -8,15 +8,20 @@ "types": "./built/index.d.ts", "scripts": { "clean": "node scripts/clean.mjs", - "build": "tsc -b && node scripts/post-build.mjs", + "build": "tsc -p tsconfig.lib.json && node scripts/post-build.mjs", "rebuild": "pnpm clean && pnpm build", "tsd": "tsd --types \"./temp/built/src/index.d.ts\" --files \"./temp/built/test-d/**/*.ts\"", "api": "pnpm api-extractor run --local --verbose", "api-prod": "pnpm api-extractor run --verbose", - "eslint": "eslint --quiet \"{src,test,test-d,scripts}/**/*.{js,jsx,ts,tsx,vue}\" --cache", - "typecheck": "tsc -b --noEmit", + "eslint": "eslint --quiet --cache -c eslint.config.js .", + "typecheck-all": "pnpm run --no-bail typecheck:lib && pnpm run --no-bail typecheck:test && pnpm run --no-bail typecheck:test-d && pnpm run --no-bail typecheck:scripts", + "typecheck": "pnpm run typecheck:lib && pnpm run typecheck:test && pnpm run typecheck:test-d && pnpm run typecheck:scripts", + "typecheck:lib": "tsc -p tsconfig.lib.json --noEmit", + "typecheck:test": "tsc -p tsconfig.test.json --noEmit", + "typecheck:test-d": "tsc -p tsconfig.test-d.json --noEmit", + "typecheck:scripts": "tsc -p tsconfig.scripts.json --noEmit", "lint": "pnpm typecheck && pnpm eslint", - "jest": "jest --coverage --detectOpenHandles", + "jest": "node --no-experimental-require-module --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --detectOpenHandles", "test": "pnpm jest && pnpm tsd", "update-autogen-code": "pnpm --filter misskey-js-type-generator generate && ncp generator/built/autogen src/autogen" }, @@ -27,6 +32,7 @@ }, "devDependencies": { "@microsoft/api-extractor": "7.52.13", + "@misskey-dev/eslint-plugin": "2.1.0", "@simplewebauthn/types": "12.0.0", "@types/jest": "30.0.0", "@types/node": "22.18.1", @@ -35,6 +41,8 @@ "jest": "30.1.3", "jest-fetch-mock": "3.0.3", "jest-websocket-mock": "2.5.0", + "ts-jest": "29.4.4", + "ts-node": "10.9.2", "mock-socket": "9.3.1", "ncp": "2.0.0", "tsd": "0.33.0", diff --git a/packages/misskey-js/scripts/clean.mjs b/packages/misskey-js/scripts/clean.mjs index 1d7cd62767..c9f0b7d3b7 100644 --- a/packages/misskey-js/scripts/clean.mjs +++ b/packages/misskey-js/scripts/clean.mjs @@ -4,7 +4,7 @@ */ import { rm } from 'fs/promises'; -import {buildDir, outDir} from './_common.mjs'; +import { buildDir, outDir } from './_common.mjs'; console.log(`Cleaning working directory ${buildDir}...`); await rm(buildDir, { recursive: true, force: true }); diff --git a/packages/misskey-js/scripts/post-build.mjs b/packages/misskey-js/scripts/post-build.mjs index 69bb1c099f..142e95ab4e 100644 --- a/packages/misskey-js/scripts/post-build.mjs +++ b/packages/misskey-js/scripts/post-build.mjs @@ -3,8 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import {libBuild, outDir, testDBuild, testDSource} from './_common.mjs'; -import {rm, cp} from 'fs/promises'; +import { libBuild, outDir, testDBuild, testDSource } from './_common.mjs'; +import { rm, cp } from 'fs/promises'; // Always clean the output, because artifacts are cached in the build directory instead. console.log(`Cleaning output directory ${outDir}...`); diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts index fa803194bf..e20a2e355d 100644 --- a/packages/misskey-js/src/api.types.ts +++ b/packages/misskey-js/src/api.types.ts @@ -1,7 +1,7 @@ -import { Endpoints as Gen } from './autogen/endpoint.js'; -import { UserDetailed } from './autogen/models.js'; -import { AdminRolesCreateRequest, AdminRolesCreateResponse, UsersShowRequest } from './autogen/entities.js'; -import { +import type { Endpoints as Gen } from './autogen/endpoint.js'; +import type { UserDetailed } from './autogen/models.js'; +import type { AdminRolesCreateRequest, AdminRolesCreateResponse, UsersShowRequest } from './autogen/entities.js'; +import type { PartialRolePolicyOverride, SigninFlowRequest, SigninFlowResponse, diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index de868fbb29..b060f5817b 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -1,5 +1,5 @@ /* eslint @typescript-eslint/naming-convention: 0 */ -import { operations } from './types.js'; +import type { operations } from './types.js'; export type EmptyRequest = Record | undefined; export type EmptyResponse = Record | undefined; diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts index 354daf800b..3bb36c923e 100644 --- a/packages/misskey-js/src/autogen/models.ts +++ b/packages/misskey-js/src/autogen/models.ts @@ -1,4 +1,4 @@ -import { components } from './types.js'; +import type { components } from './types.js'; export type Error = components['schemas']['Error']; export type UserLite = components['schemas']['UserLite']; export type UserDetailedNotMeOnly = components['schemas']['UserDetailedNotMeOnly']; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index be3f83fda5..6b369fc52d 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -1,5 +1,5 @@ -import { ModerationLogPayloads } from './consts.js'; -import { +import type { ModerationLogPayloads } from './consts.js'; +import type { Announcement, EmojiDetailed, MeDetailed, diff --git a/packages/misskey-js/src/streaming.ts b/packages/misskey-js/src/streaming.ts index 371f3f1d13..bc3650ab5d 100644 --- a/packages/misskey-js/src/streaming.ts +++ b/packages/misskey-js/src/streaming.ts @@ -1,10 +1,11 @@ import { EventEmitter } from 'eventemitter3'; -import _ReconnectingWebSocket, { Options } from 'reconnecting-websocket'; +import ReconnectingWebSocket from 'reconnecting-websocket'; +import type { Options } from 'reconnecting-websocket'; import type { BroadcastEvents, Channels } from './streaming.types.js'; -// コンストラクタとクラスそのものの定義が上手く解決出来ないため再定義 -const ReconnectingWebSocketConstructor = _ReconnectingWebSocket as unknown as typeof _ReconnectingWebSocket.default; -type ReconnectingWebSocket = _ReconnectingWebSocket.default; +// // コンストラクタとクラスそのものの定義が上手く解決出来ないため再定義 +// const ReconnectingWebSocketConstructor = _ReconnectingWebSocket.default; +// type ReconnectingWebSocket = _ReconnectingWebSocket.default; export function urlQuery(obj: Record): string { const params = Object.entries(obj) @@ -83,7 +84,7 @@ export default class Stream extends EventEmitter implements IStrea const wsOrigin = origin.replace('http://', 'ws://').replace('https://', 'wss://'); - this.stream = new ReconnectingWebSocketConstructor(`${wsOrigin}/streaming?${query}`, '', { + this.stream = new ReconnectingWebSocket(`${wsOrigin}/streaming?${query}`, '', { minReconnectionDelay: 1, // https://github.com/pladaria/reconnecting-websocket/issues/91 WebSocket: options.WebSocket, }); diff --git a/packages/misskey-js/src/streaming.types.ts b/packages/misskey-js/src/streaming.types.ts index d13a54b1c2..dbae1f87e1 100644 --- a/packages/misskey-js/src/streaming.types.ts +++ b/packages/misskey-js/src/streaming.types.ts @@ -1,4 +1,4 @@ -import { +import type { Antenna, ChatMessage, ChatMessageLite, @@ -12,7 +12,7 @@ import { UserDetailedNotMe, UserLite, } from './autogen/models.js'; -import { +import type { AnnouncementCreated, EmojiAdded, EmojiDeleted, EmojiUpdated, @@ -23,7 +23,7 @@ import { ServerStatsLog, ReversiGameDetailed, } from './entities.js'; -import { +import type { ReversiUpdateKey, } from './consts.js'; diff --git a/packages/misskey-js/test-d/streaming.ts b/packages/misskey-js/test-d/streaming.ts index b46b06e4df..7dff1fbcec 100644 --- a/packages/misskey-js/test-d/streaming.ts +++ b/packages/misskey-js/test-d/streaming.ts @@ -1,9 +1,10 @@ import { expectType } from 'tsd'; import * as Misskey from '../src/index.js'; +import Stream from '../src/streaming.js'; describe('Streaming', () => { test('emit type', async () => { - const stream = new Misskey.Stream('https://misskey.test', { token: 'TOKEN' }); + const stream = new Stream('https://misskey.test', { token: 'TOKEN' }); const mainChannel = stream.useChannel('main'); mainChannel.on('notification', notification => { expectType(notification); diff --git a/packages/misskey-js/test/api.ts b/packages/misskey-js/test/api.ts index 1a7574de25..856d167113 100644 --- a/packages/misskey-js/test/api.ts +++ b/packages/misskey-js/test/api.ts @@ -1,7 +1,7 @@ -import { enableFetchMocks } from 'jest-fetch-mock'; +import fetchMock from 'jest-fetch-mock'; import { APIClient, isAPIError } from '../src/api.js'; -enableFetchMocks(); +fetchMock.enableMocks(); function getFetchCall(call: any[]) { const { body, method } = call[1]; @@ -26,7 +26,7 @@ describe('API', () => { fetchMock.resetMocks(); fetchMock.mockResponse(async (req) => { const body = await req.json(); - if (req.method == 'POST' && req.url == 'https://misskey.test/api/i') { + if (req.method === 'POST' && req.url === 'https://misskey.test/api/i') { if (body.i === 'TOKEN') { return JSON.stringify({ id: 'foo' }); } else { @@ -45,14 +45,14 @@ describe('API', () => { const res = await cli.request('i'); expect(res).toEqual({ - id: 'foo' + id: 'foo', }); expect(getFetchCall(fetchMock.mock.calls[0])).toEqual({ url: 'https://misskey.test/api/i', method: 'POST', contentType: 'application/json', - body: { i: 'TOKEN' } + body: { i: 'TOKEN' }, }); }); @@ -60,7 +60,7 @@ describe('API', () => { fetchMock.resetMocks(); fetchMock.mockResponse(async (req) => { const body = await req.json(); - if (req.method == 'POST' && req.url == 'https://misskey.test/api/notes/show') { + if (req.method === 'POST' && req.url === 'https://misskey.test/api/notes/show') { if (body.i === 'TOKEN' && body.noteId === 'aaaaa') { return JSON.stringify({ id: 'foo' }); } else { @@ -79,21 +79,21 @@ describe('API', () => { const res = await cli.request('notes/show', { noteId: 'aaaaa' }); expect(res).toEqual({ - id: 'foo' + id: 'foo', }); expect(getFetchCall(fetchMock.mock.calls[0])).toEqual({ url: 'https://misskey.test/api/notes/show', method: 'POST', contentType: 'application/json', - body: { i: 'TOKEN', noteId: 'aaaaa' } + body: { i: 'TOKEN', noteId: 'aaaaa' }, }); }); test('multipart/form-data', async () => { fetchMock.resetMocks(); fetchMock.mockResponse(async (req) => { - if (req.method == 'POST' && req.url == 'https://misskey.test/api/drive/files/create') { + if (req.method === 'POST' && req.url === 'https://misskey.test/api/drive/files/create') { if (req.headers.get('Content-Type')?.includes('multipart/form-data')) { return JSON.stringify({ id: 'foo' }); } else { @@ -117,7 +117,7 @@ describe('API', () => { }); expect(res).toEqual({ - id: 'foo' + id: 'foo', }); expect(getFetchCall(fetchMock.mock.calls[0])).toEqual({ @@ -127,14 +127,14 @@ describe('API', () => { body: { i: 'TOKEN', file: testFile, - } + }, }); }); test('204 No Content で null が返る', async () => { fetchMock.resetMocks(); fetchMock.mockResponse(async (req) => { - if (req.method == 'POST' && req.url == 'https://misskey.test/api/reset-password') { + if (req.method === 'POST' && req.url === 'https://misskey.test/api/reset-password') { return { status: 204 }; } else { return { status: 404 }; @@ -154,7 +154,7 @@ describe('API', () => { url: 'https://misskey.test/api/reset-password', method: 'POST', contentType: 'application/json', - body: { i: 'TOKEN', token: 'aaa', password: 'aaa' } + body: { i: 'TOKEN', token: 'aaa', password: 'aaa' }, }); }); @@ -162,7 +162,7 @@ describe('API', () => { fetchMock.resetMocks(); fetchMock.mockResponse(async (req) => { const body = await req.json(); - if (req.method == 'POST' && req.url == 'https://misskey.test/api/i') { + if (req.method === 'POST' && req.url === 'https://misskey.test/api/i') { if (typeof body.i === 'string') { return JSON.stringify({ id: 'foo' }); } else { @@ -173,8 +173,8 @@ describe('API', () => { message: 'Credential required.', code: 'CREDENTIAL_REQUIRED', id: '1384574d-a912-4b81-8601-c7b1c4085df1', - } - }) + }, + }), }; } } else { @@ -206,7 +206,7 @@ describe('API', () => { id: '5d37dbcb-891e-41ca-a3d6-e690c97775ac', kind: 'server', }, - }) + }), }; }); @@ -244,7 +244,7 @@ describe('API', () => { fetchMock.mockResponse(async (req) => { return { status: 500, - body: 'I AM NOT JSON' + body: 'I AM NOT JSON', }; }); @@ -266,7 +266,7 @@ describe('API', () => { return { // 本来返すべき値は`Role`型だが、テストなのでお茶を濁す status: 200, - body: '{}' + body: '{}', }; }); @@ -296,5 +296,5 @@ describe('API', () => { }, target: 'manual', }); - }) + }); }); diff --git a/packages/misskey-js/test/nyaize.test.ts b/packages/misskey-js/test/nyaize.test.ts index bda9bbbef8..df8f2fc801 100644 --- a/packages/misskey-js/test/nyaize.test.ts +++ b/packages/misskey-js/test/nyaize.test.ts @@ -7,30 +7,30 @@ import { nyaize } from '../src/nyaize.js'; function runTests(cases: [string, string][]) { for (const c of cases) { - const [input,expected] = c; + const [input, expected] = c; const got = nyaize(input); expect(got).toEqual(expected); } } describe('nyaize', () => { - test('ja-JP', () => { - runTests([ - ['きれいな','きれいにゃ'], - ['ナナナ', 'ニャニャニャ'], - ['ナナ','ニャニャ'], - ]); - }); - test('en-US', () => { - runTests([ - ['bar','bar'], - ['banana','banyanya'], - ['booting','booting'], - ['morning','mornyan'], - ['mmmorning','mmmornyan'], - ['someone','someone'], - ['everyone','everynyan'], - ['foreveryone','foreverynyan'], - ]); - }); + test('ja-JP', () => { + runTests([ + ['きれいな', 'きれいにゃ'], + ['ナナナ', 'ニャニャニャ'], + ['ナナ', 'ニャニャ'], + ]); + }); + test('en-US', () => { + runTests([ + ['bar', 'bar'], + ['banana', 'banyanya'], + ['booting', 'booting'], + ['morning', 'mornyan'], + ['mmmorning', 'mmmornyan'], + ['someone', 'someone'], + ['everyone', 'everynyan'], + ['foreveryone', 'foreverynyan'], + ]); + }); }); diff --git a/packages/misskey-js/tsconfig.json b/packages/misskey-js/tsconfig.json index 6fb6804fae..207df95f9b 100644 --- a/packages/misskey-js/tsconfig.json +++ b/packages/misskey-js/tsconfig.json @@ -1,43 +1,11 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "target": "ES2022", - "module": "nodenext", - "moduleResolution": "nodenext", - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "inlineSources": true, - "allowJs": true, - "checkJs": true, - "outDir": "./temp/built/", - "strict": true, - "strictFunctionTypes": true, - "strictNullChecks": true, - "experimentalDecorators": true, - "noImplicitReturns": true, - "esModuleInterop": true, - "exactOptionalPropertyTypes": true, - "rootDir": ".", - "incremental": true, - "composite": true, - "typeRoots": [ - "./node_modules/@types" - ], - "lib": [ - "esnext", - "dom", - "dom.iterable" // https://dev.to/deciduously/formdata-in-typescript-24cl - ] - }, - "compileOnSave": false, - "include": [ - "src/**/*", - "test/**/*", - "test-d/**/*", - "scripts/**/*", - ], - "exclude": [ - "node_modules" + "files": [], + // WebStorm only reads one tsconfig per directory, so this tricks it into loading both. + "references": [ + { "path": "./tsconfig.lib.json" }, + { "path": "./tsconfig.test.json" }, + { "path": "./tsconfig.test-d.json" }, + { "path": "./tsconfig.scripts.json" } ] } diff --git a/packages/misskey-js/tsconfig.lib.json b/packages/misskey-js/tsconfig.lib.json new file mode 100644 index 0000000000..95279184fa --- /dev/null +++ b/packages/misskey-js/tsconfig.lib.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../shared/tsconfig.web.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "inlineSources": true, + "outDir": "./temp/built/", + "rootDir": ".", + "exactOptionalPropertyTypes": true, + "composite": true, + "typeRoots": [ + "./node_modules/@types" + ] + }, + "include": [ + "src/**/*", + "test/**/*", + "test-d/**/*" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/packages/misskey-js/tsconfig.scripts.json b/packages/misskey-js/tsconfig.scripts.json new file mode 100644 index 0000000000..c1969bd759 --- /dev/null +++ b/packages/misskey-js/tsconfig.scripts.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "../shared/tsconfig.node.json", + "compilerOptions": { + "noImplicitAny": false + }, + "include": [ + "*.ts", + "*.js", + "scripts/**/*" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/packages/misskey-js/tsconfig.test-d.json b/packages/misskey-js/tsconfig.test-d.json new file mode 100644 index 0000000000..d3c9c91e74 --- /dev/null +++ b/packages/misskey-js/tsconfig.test-d.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig.lib.json", + "compilerOptions": { + "composite": false, + "declaration": false, + "declarationMap": false, + "sourceMap": false, + "inlineSources": false, + "outDir": "./temp/built/test-d/", + "rootDir": "." + }, + "references": [ + { "path": "./tsconfig.lib.json" } + ], + "include": [ + "test-d/**/*" + ] +} diff --git a/packages/misskey-js/tsconfig.test.json b/packages/misskey-js/tsconfig.test.json new file mode 100644 index 0000000000..dbe065f0d8 --- /dev/null +++ b/packages/misskey-js/tsconfig.test.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig.lib.json", + "compilerOptions": { + "composite": false, + "declaration": false, + "declarationMap": false, + "sourceMap": false, + "inlineSources": false, + "module": "nodenext", + "moduleResolution": "nodenext", + "outDir": "./temp/built/test/", + "rootDir": "./test/" + }, + "references": [ + { "path": "./tsconfig.lib.json" } + ], + "include": [ + "test/**/*" + ] +}