modernize backend to target the same ES and TS standards as the rest of the app
This commit is contained in:
parent
22f49db21f
commit
9beeca5942
29 changed files with 460 additions and 232 deletions
|
|
@ -17,7 +17,7 @@
|
|||
"paths": {
|
||||
"@/*": ["*"]
|
||||
},
|
||||
"target": "es2022"
|
||||
"target": "ESNext"
|
||||
},
|
||||
"minify": false,
|
||||
"sourceMaps": "inline"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
/** @type {NodeListOf<HTMLIFrameElement>} */
|
||||
const els = document.querySelectorAll('iframe[data-misskey-embed-id]');
|
||||
|
||||
window.addEventListener('message', function (event) {
|
||||
window.addEventListener('message', (event) => {
|
||||
els.forEach((el) => {
|
||||
if (event.source !== el.contentWindow) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@ export default [
|
|||
...sharedConfig,
|
||||
{
|
||||
ignores: [
|
||||
"assets/",
|
||||
"**/built/",
|
||||
"migration/",
|
||||
"**/node_modules/",
|
||||
"test/",
|
||||
"test-federation/",
|
||||
"test-server/",
|
||||
"**/temp/",
|
||||
"**/@types/",
|
||||
"**/coverage/",
|
||||
"*.*",
|
||||
"**/*.test.ts",
|
||||
'**/built/',
|
||||
'migration/',
|
||||
'**/node_modules/',
|
||||
'test/',
|
||||
'test-federation/',
|
||||
'test-server/',
|
||||
'**/temp/',
|
||||
'**/@types/',
|
||||
'**/coverage/',
|
||||
'ormconfig.js',
|
||||
'scripts/check_connect.js',
|
||||
'scripts/generate_api_json.js',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -29,10 +29,14 @@ export default [
|
|||
},
|
||||
{
|
||||
files: ['src/**/*.ts', 'src/**/*.tsx'],
|
||||
ignores: [
|
||||
'*.*',
|
||||
'src/server/web/**/*.d.ts',
|
||||
],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
parser: tsParser,
|
||||
project: ['./tsconfig.json'],
|
||||
project: ['./tsconfig.backend.json'],
|
||||
sourceType: 'module',
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
|
|
@ -94,42 +98,50 @@ export default [
|
|||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
"selector": "NewExpression[callee.name='Date'][arguments.length=0]",
|
||||
"message": "new Date() is restricted. Use TimeService.date instead."
|
||||
'selector': 'NewExpression[callee.name=\'Date\'][arguments.length=0]',
|
||||
'message': 'new Date() is restricted. Use TimeService.date instead.',
|
||||
},
|
||||
{
|
||||
"selector": "NewExpression[callee.name='MemoryKVCache']",
|
||||
"message": "Cache constructor will produce an unmanaged instance. Use CacheManagementService.createMemoryKVCache() instead."
|
||||
'selector': 'NewExpression[callee.name=\'MemoryKVCache\']',
|
||||
'message': 'Cache constructor will produce an unmanaged instance. Use CacheManagementService.createMemoryKVCache() instead.',
|
||||
},
|
||||
{
|
||||
"selector": "NewExpression[callee.name='MemorySingleCache']",
|
||||
"message": "Cache constructor will produce an unmanaged instance. Use CacheManagementService.createMemorySingleCache() instead."
|
||||
'selector': 'NewExpression[callee.name=\'MemorySingleCache\']',
|
||||
'message': 'Cache constructor will produce an unmanaged instance. Use CacheManagementService.createMemorySingleCache() instead.',
|
||||
},
|
||||
{
|
||||
"selector": "NewExpression[callee.name='RedisKVCache']",
|
||||
"message": "Cache constructor will produce an unmanaged instance. Use CacheManagementService.createRedisKVCache() instead."
|
||||
'selector': 'NewExpression[callee.name=\'RedisKVCache\']',
|
||||
'message': 'Cache constructor will produce an unmanaged instance. Use CacheManagementService.createRedisKVCache() instead.',
|
||||
},
|
||||
{
|
||||
"selector": "NewExpression[callee.name='RedisSingleCache']",
|
||||
"message": "Cache constructor will produce an unmanaged instance. Use CacheManagementService.createRedisSingleCache() instead."
|
||||
'selector': 'NewExpression[callee.name=\'RedisSingleCache\']',
|
||||
'message': 'Cache constructor will produce an unmanaged instance. Use CacheManagementService.createRedisSingleCache() instead.',
|
||||
},
|
||||
{
|
||||
"selector": "NewExpression[callee.name='QuantumKVCache']",
|
||||
"message": "Cache constructor will produce an unmanaged instance. Use CacheManagementService.createQuantumKVCache() instead."
|
||||
'selector': 'NewExpression[callee.name=\'QuantumKVCache\']',
|
||||
'message': 'Cache constructor will produce an unmanaged instance. Use CacheManagementService.createQuantumKVCache() instead.',
|
||||
},
|
||||
{
|
||||
"selector": "CallExpression[callee.property.name='delete'][arguments.length=1] > ObjectExpression[properties.length=0]",
|
||||
"message": "repository.delete({}) will produce a runtime error. Use repository.deleteAll() instead."
|
||||
'selector': 'CallExpression[callee.property.name=\'delete\'][arguments.length=1] > ObjectExpression[properties.length=0]',
|
||||
'message': 'repository.delete({}) will produce a runtime error. Use repository.deleteAll() instead.',
|
||||
},
|
||||
{
|
||||
"selector": "CallExpression[callee.property.name='update'][arguments.length>=1] > ObjectExpression[properties.length=0]",
|
||||
"message": "repository.update({}, {...}) will produce a runtime error. Use repository.updateAll({...}) instead."
|
||||
'selector': 'CallExpression[callee.property.name=\'update\'][arguments.length>=1] > ObjectExpression[properties.length=0]',
|
||||
'message': 'repository.update({}, {...}) will produce a runtime error. Use repository.updateAll({...}) instead.',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['src/server/web/**/*.js', 'src/server/web/**/*.ts'],
|
||||
files: [
|
||||
'./assets/**/*.js',
|
||||
'./assets/**/*.mjs',
|
||||
'./assets/**/*.cjs',
|
||||
'./src/server/web/**/*.js',
|
||||
'./src/server/web/**/*.mjs',
|
||||
'./src/server/web/**/*.cjs',
|
||||
'./src/server/web/**/*.d.ts',
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
|
|
@ -137,6 +149,12 @@ export default [
|
|||
CLIENT_ENTRY: true,
|
||||
LANGS_VERSION: true,
|
||||
},
|
||||
parserOptions: {
|
||||
parser: tsParser,
|
||||
project: ['./jsconfig.frontend.json'],
|
||||
sourceType: 'module',
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-restricted-globals': 'off',
|
||||
|
|
@ -144,4 +162,25 @@ export default [
|
|||
'no-restricted-syntax': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: [
|
||||
'eslint.*',
|
||||
'jest.*',
|
||||
'scripts/dev.mjs',
|
||||
'scripts/watch.mjs',
|
||||
],
|
||||
ignores: [
|
||||
'ormconfig.js',
|
||||
'scripts/check_connect.js',
|
||||
'scripts/generate_api_json.js',
|
||||
],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
parser: tsParser,
|
||||
project: ['./tsconfig.scripts.json'],
|
||||
sourceType: 'module',
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* For a detailed explanation regarding each configuration property and type check, visit:
|
||||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
|
||||
const base = require('./jest.config.cjs')
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
globalSetup: "<rootDir>/built-test/entry.js",
|
||||
setupFilesAfterEnv: ["<rootDir>/test/jest.setup.ts"],
|
||||
testMatch: [
|
||||
"<rootDir>/test/e2e/**/*.ts",
|
||||
],
|
||||
};
|
||||
173
packages/backend/jest.config.e2e.ts
Normal file
173
packages/backend/jest.config.e2e.ts
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* For a detailed explanation regarding each configuration property and type check, visit:
|
||||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
|
||||
import base from './jest.config.ts';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
globalSetup: "<rootDir>/built-test/entry.js",
|
||||
setupFilesAfterEnv: ["<rootDir>/test/jest.setup.ts"],
|
||||
|
||||
// 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', '!src/**/*.test.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",
|
||||
|
||||
// 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: [
|
||||
"<rootDir>/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: [
|
||||
"<rootDir>/test/e2e/**/*.ts",
|
||||
],
|
||||
};
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
|
||||
const base = require('./jest.config.cjs');
|
||||
import base from './jest.config.ts';
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
// All imported modules in your tests should be mocked automatically
|
||||
// automock: false,
|
||||
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
|
||||
const base = require('./jest.config.cjs')
|
||||
import base from './jest.config.ts';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
...base,
|
||||
testMatch: [
|
||||
"<rootDir>/test/unit/**/*.ts",
|
||||
|
|
@ -24,7 +24,11 @@ child.on('error', (err) => {
|
|||
});
|
||||
child.on('exit', (code, signal) => {
|
||||
if (code === null) {
|
||||
process.exit(128 + signal);
|
||||
if (signal != null) {
|
||||
process.exit(128 + signal);
|
||||
} else {
|
||||
process.exit(128);
|
||||
}
|
||||
} else {
|
||||
process.exit(code);
|
||||
}
|
||||
|
|
|
|||
24
packages/backend/jsconfig.frontend.json
Normal file
24
packages/backend/jsconfig.frontend.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"extends": "../shared/jsconfig.web.json",
|
||||
"include": [
|
||||
"./assets/**/*.js",
|
||||
"./assets/**/*.mjs",
|
||||
"./assets/**/*.cjs",
|
||||
"./assets/**/*.d.ts",
|
||||
"./src/server/web/**/*.js",
|
||||
"./src/server/web/**/*.mjs",
|
||||
"./src/server/web/**/*.cjs",
|
||||
"./src/server/web/**/*.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**/*",
|
||||
"**/built/**/*",
|
||||
"./jspm_packages",
|
||||
"./tmp",
|
||||
"./temp",
|
||||
"./test",
|
||||
"./test-federation",
|
||||
"./test-server",
|
||||
"**/coverage/**/*"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"skipLibCheck": true,
|
||||
"allowJs": true,
|
||||
"checkJs": true
|
||||
},
|
||||
"include": [
|
||||
"./**/*.js"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"./built",
|
||||
"./jspm_packages",
|
||||
"./tmp",
|
||||
"./temp",
|
||||
"./test",
|
||||
"./test-federation",
|
||||
"./test-server"
|
||||
]
|
||||
}
|
||||
|
|
@ -18,11 +18,18 @@
|
|||
"build": "swc src -d built -D --strip-leading-paths",
|
||||
"build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc --strip-leading-paths",
|
||||
"watch:swc": "swc src -d built -D -w --strip-leading-paths",
|
||||
"build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
||||
"build:tsc": "tsc -p tsconfig.backend.json && tsc-alias -p tsconfig.backend.json",
|
||||
"watch": "node ./scripts/watch.mjs",
|
||||
"restart": "pnpm build && pnpm start",
|
||||
"dev": "node ./scripts/dev.mjs",
|
||||
"typecheck": "pnpm --filter megalodon build && tsc --noEmit && tsc -p test --noEmit && tsc -p test-federation --noEmit",
|
||||
"typecheck-all": "pnpm --filter megalodon build && pnpm run --no-bail typecheck:scripts && pnpm run --no-bail typecheck:backend && pnpm run --no-bail typecheck:frontend && pnpm run --no-bail typecheck:backend:web && pnpm run --no-bail typecheck:test && pnpm run --no-bail typecheck:test-federation && pnpm run --no-bail typecheck:test-server",
|
||||
"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: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",
|
||||
"eslint-all": "pnpm run --no-bail eslint:backend && pnpm run --no-bail eslint:test && pnpm run --no-bail eslint:test-federation && pnpm run --no-bail eslint:test-server",
|
||||
"eslint": "pnpm run eslint:backend && pnpm run eslint:test && pnpm run eslint:test-federation && pnpm run eslint:test-server",
|
||||
"eslint:backend": "eslint --quiet --cache -c eslint.config.js .",
|
||||
|
|
@ -30,11 +37,11 @@
|
|||
"eslint:test-federation": "eslint --quiet --cache -c test-federation/eslint.config.js ./test-federation",
|
||||
"eslint:test-server": "eslint --quiet --cache -c test-server/eslint.config.js ./test-server",
|
||||
"lint": "pnpm typecheck && pnpm eslint",
|
||||
"jest": "cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.unit.cjs",
|
||||
"jest:e2e": "cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.e2e.cjs",
|
||||
"jest:fed": "node ./jest.js --forceExit --config jest.config.fed.cjs",
|
||||
"jest-and-coverage": "cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.unit.cjs",
|
||||
"jest-and-coverage:e2e": "cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.e2e.cjs",
|
||||
"jest": "cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.unit.ts",
|
||||
"jest:e2e": "cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.e2e.ts",
|
||||
"jest:fed": "node ./jest.js --forceExit --config jest.config.fed.ts",
|
||||
"jest-and-coverage": "cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.unit.ts",
|
||||
"jest-and-coverage:e2e": "cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.e2e.ts",
|
||||
"jest-clear": "cross-env NODE_ENV=test node ./jest.js --clearCache",
|
||||
"test": "pnpm jest",
|
||||
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
|
||||
|
|
@ -176,7 +183,6 @@
|
|||
"tsc-alias": "1.8.16",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"typeorm": "0.3.27",
|
||||
"typescript": "5.9.2",
|
||||
"ulid": "3.0.1",
|
||||
"uuid": "13.0.0",
|
||||
"vary": "1.1.2",
|
||||
|
|
@ -240,6 +246,9 @@
|
|||
"nodemon": "3.1.10",
|
||||
"pid-port": "2.0.0",
|
||||
"simple-oauth2": "5.1.0",
|
||||
"ts-jest": "29.4.4",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.2",
|
||||
"supertest": "7.1.4"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { execa, execaNode } from 'execa';
|
||||
|
||||
/** @type {import('execa').ExecaChildProcess | undefined} */
|
||||
/** @type {import('execa').ResultPromise | undefined} */
|
||||
let backendProcess;
|
||||
|
||||
async function execBuildAssets() {
|
||||
|
|
@ -32,8 +32,8 @@ async function killProc() {
|
|||
if (backendProcess) {
|
||||
backendProcess.catch(() => {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す
|
||||
backendProcess.kill();
|
||||
await new Promise(resolve => backendProcess.on('exit', resolve));
|
||||
backendProcess = undefined;
|
||||
await new Promise(resolve => backendProcess?.on('exit', resolve))
|
||||
.finally(() => backendProcess = undefined);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ async function killProc() {
|
|||
stdio: [process.stdin, process.stdout, process.stderr, 'ipc'],
|
||||
serialization: "json",
|
||||
})
|
||||
.on('message', async (message) => {
|
||||
.on('message', /** @param {{type: string}} message */ async (message) => {
|
||||
if (message.type === 'exit') {
|
||||
// かならずbuild->build-assetsの順番で呼び出したいので、
|
||||
// 少々トリッキーだがnodemonからのexitイベントを利用してbuild-assets->startを行う。
|
||||
|
|
|
|||
|
|
@ -8,20 +8,20 @@ import { execa } from 'execa';
|
|||
(async () => {
|
||||
// なぜかchokidarが動かない影響で、watchされない
|
||||
/*
|
||||
execa('tsc-alias', ['-w', '-p', 'tsconfig.json'], {
|
||||
execa('tsc-alias', ['-w', '-p', 'tsconfig.backend.json'], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
*/
|
||||
|
||||
setInterval(() => {
|
||||
execa('tsc-alias', ['-p', 'tsconfig.json'], {
|
||||
execa('tsc-alias', ['-p', 'tsconfig.backend.json'], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
}, 3000);
|
||||
|
||||
execa('tsc', ['-w', '-p', 'tsconfig.json'], {
|
||||
execa('tsc', ['-w', '-p', 'tsconfig.backend.json'], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,11 +6,49 @@
|
|||
import { appendContentWarning } from './append-content-warning.js';
|
||||
import type { Packed } from './json-schema.js';
|
||||
|
||||
// export type PackedNoteForSummary = Omit<Partial<Packed<'Note'>>, 'user'> & {
|
||||
// user: Omit<Partial<Packed<'Note'>['user']>, 'instance'> & {
|
||||
// instance?: Partial<Packed<'Note'>['user']['instance']> | null;
|
||||
// };
|
||||
// };
|
||||
|
||||
// Workaround for weird typescript but
|
||||
// type Pivot<N, U, I> = {
|
||||
// [KNote in keyof N]?: KNote extends 'user'
|
||||
// ? {
|
||||
// [KUser in keyof U]?: KUser extends 'instance'
|
||||
// ? {
|
||||
// [KInst in keyof I]?: I[KInst] | undefined;
|
||||
// }
|
||||
// : U[KUser]
|
||||
// }
|
||||
// : N[KNote]
|
||||
// };
|
||||
// type Pivot<N extends { user: U }, U extends { instance?: I | null }, I extends object> = Split<N, 'user'> & {
|
||||
// user: Split<U, 'instance'> & {
|
||||
// instance: I | undefined;
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// type Split<T, O extends keyof T, R extends keyof T = Exclude<keyof T, O>> = {
|
||||
// [K in (keyof T) & R]: T[K];
|
||||
// } & {
|
||||
// [K in (keyof T) & O]?: T[K] | undefined;
|
||||
// };
|
||||
//
|
||||
// export type PackedNoteForSummary = Pivot<Packed<'Note'>, Packed<'Note'>['user'], NonNullable<Packed<'Note'>['user']['instance']>>;
|
||||
export type PackedNoteForSummary = DeepPartial<Packed<'Note'>>;
|
||||
|
||||
// Do we really not have a type for this yet??
|
||||
type DeepPartial<T extends object> = {
|
||||
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* 投稿を表す文字列を取得します。
|
||||
* @param {*} note (packされた)投稿
|
||||
*/
|
||||
export const getNoteSummary = (note: Packed<'Note'>): string => {
|
||||
export const getNoteSummary = (note: PackedNoteForSummary): string => {
|
||||
if (note.deletedAt) {
|
||||
return '(❌⛔)';
|
||||
}
|
||||
|
|
@ -26,13 +64,13 @@ export const getNoteSummary = (note: Packed<'Note'>): string => {
|
|||
if (note.mandatoryCW) {
|
||||
cw = appendContentWarning(cw, `Note is flagged: "${note.mandatoryCW}"`);
|
||||
}
|
||||
if (note.user.mandatoryCW) {
|
||||
if (note.user?.mandatoryCW) {
|
||||
const username = note.user.host
|
||||
? `@${note.user.username}@${note.user.host}`
|
||||
: `@${note.user.username}`;
|
||||
cw = appendContentWarning(cw, `${username} is flagged: "${note.user.mandatoryCW}"`);
|
||||
}
|
||||
if (note.user.instance?.mandatoryCW) {
|
||||
if (note.user?.instance?.mandatoryCW) {
|
||||
cw = appendContentWarning(cw, `${note.user.host} is flagged: "${note.user.instance.mandatoryCW}"`);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ export class MastodonConverters {
|
|||
this.getUser(p)
|
||||
.then(u => this.encode(u, mentionedRemoteUsers))
|
||||
.catch(() => null)))
|
||||
.then((p: Entity.Mention[]) => p.filter(m => m));
|
||||
.then((p: (Entity.Mention | null)[]) => p.filter(m => m != null));
|
||||
|
||||
const tags = note.tags.map(tag => {
|
||||
return {
|
||||
|
|
@ -345,7 +345,7 @@ export class MastodonConverters {
|
|||
sensitive: status.sensitive || !!cw,
|
||||
spoiler_text: cw,
|
||||
visibility: status.visibility,
|
||||
media_attachments: status.media_attachments.map((a: Entity.Account) => convertAttachment(a)),
|
||||
media_attachments: status.media_attachments.map((a: Entity.Attachment) => convertAttachment(a)),
|
||||
mentions: mentions,
|
||||
tags: tags,
|
||||
card: null, //FIXME
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ export class ApiInstanceMastodon {
|
|||
const response: MastodonEntity.Instance = {
|
||||
uri: this.config.host,
|
||||
title: this.meta.name || 'Sharkey',
|
||||
shortDescription: this.meta.description || 'This is a vanilla Sharkey Instance. It doesn\'t seem to have a description.',
|
||||
description: this.meta.about || 'This is a vanilla Sharkey Instance.',
|
||||
description: this.meta.description || this.meta.about || 'This is a vanilla Sharkey Instance.',
|
||||
email: instance.email || '',
|
||||
version: `3.0.0 (compatible; Sharkey ${this.config.version}; like Akkoma)`,
|
||||
urls: instance.urls,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { parseTimelineArgs, TimelineArgs, toBoolean, toInt } from '@/server/api/
|
|||
import { MastodonClientService } from '@/server/api/mastodon/MastodonClientService.js';
|
||||
import { MastodonDataService } from '@/server/api/mastodon/MastodonDataService.js';
|
||||
import { getNoteSummary } from '@/misc/get-note-summary.js';
|
||||
import type { Packed } from '@/misc/json-schema.js';
|
||||
import { isPureRenote } from '@/misc/is-renote.js';
|
||||
import { convertAttachment, convertPoll, MastodonConverters } from '../MastodonConverters.js';
|
||||
import type { Entity } from 'megalodon';
|
||||
|
|
@ -46,7 +45,34 @@ export class ApiStatusMastodon {
|
|||
|
||||
// Fixup - Discord ignores CWs and renders the entire post.
|
||||
if (response.sensitive && _request.headers['user-agent']?.match(/\bDiscordbot\//)) {
|
||||
response.content = getNoteSummary(data.data satisfies Packed<'Note'>);
|
||||
// TODO move this mastoConverters?
|
||||
response.content = getNoteSummary({
|
||||
...data.data,
|
||||
user: {
|
||||
...data.data.account,
|
||||
emojis: {},
|
||||
noindex: data.data.account.noindex ?? false,
|
||||
},
|
||||
visibility: data.data.visibility === 'direct'
|
||||
? 'specified'
|
||||
: data.data.visibility === 'private'
|
||||
? 'followers'
|
||||
: data.data.visibility === 'unlisted'
|
||||
? 'home'
|
||||
: data.data.visibility,
|
||||
mentions: data.data.mentions.map(m => m.id),
|
||||
tags: data.data.tags.map(t => t.name),
|
||||
poll: data.data.poll && {
|
||||
...data.data.poll,
|
||||
choices: data.data.poll.options.map(o => ({
|
||||
...o,
|
||||
text: o.title,
|
||||
votes: o.votes_count ?? 0,
|
||||
isVoted: o.votes_count != null,
|
||||
})),
|
||||
},
|
||||
emojis: {},
|
||||
});
|
||||
response.media_attachments = [];
|
||||
response.in_reply_to_id = null;
|
||||
response.in_reply_to_account_id = null;
|
||||
|
|
@ -182,7 +208,7 @@ export class ApiStatusMastodon {
|
|||
if (body.in_reply_to_id && removed === '/unreact') {
|
||||
const id = body.in_reply_to_id;
|
||||
const post = await client.getStatus(id);
|
||||
const react = post.data.emoji_reactions.filter((e: Entity.Emoji) => e.me)[0].name;
|
||||
const react = post.data.emoji_reactions.filter((e: Entity.Reaction) => e.me)[0].name;
|
||||
const data = await client.deleteEmojiReaction(id, react);
|
||||
return reply.send(data.data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
let forceError = localStorage.getItem('forceError');
|
||||
if (forceError != null) {
|
||||
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.');
|
||||
renderError('FORCED_ERROR');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ window.onload = async () => {
|
|||
|
||||
document.getElementById('submit').addEventListener('click', () => {
|
||||
api('notes/create', {
|
||||
text: document.getElementById('text').value
|
||||
text: (/** @type {HTMLInputElement} */(document.getElementById('text'))).value
|
||||
}).then(() => {
|
||||
location.reload();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
el.textContent = reload;
|
||||
}
|
||||
|
||||
/** @type {NodeListOf<HTMLElement>} */
|
||||
const i18nEls = document.querySelectorAll('[data-i18n]');
|
||||
for (const el of i18nEls) {
|
||||
const key = el.dataset.i18n;
|
||||
|
|
|
|||
3
packages/backend/src/server/web/global.d.ts
vendored
Normal file
3
packages/backend/src/server/web/global.d.ts
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
declare const CLIENT_ENTRY: string;
|
||||
declare const LANGS_VERSION: string;
|
||||
declare const LANGS: string[];
|
||||
|
|
@ -1,24 +1,16 @@
|
|||
{
|
||||
"extends": "../../shared/tsconfig.node.json",
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"types": ["jest", "node"],
|
||||
"verbatimModuleSyntax": false,
|
||||
"outDir": "./built",
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["../src/*"]
|
||||
},
|
||||
"typeRoots": [
|
||||
"../node_modules/@types",
|
||||
],
|
||||
"lib": [
|
||||
"esnext"
|
||||
],
|
||||
"types": ["jest", "node"]
|
||||
"../node_modules/@types"
|
||||
]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"daemon.ts",
|
||||
"./test/**/*.ts"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
"paths": {
|
||||
"@/*": ["*"]
|
||||
},
|
||||
"target": "es2022"
|
||||
"target": "ESNext"
|
||||
},
|
||||
"minify": false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,53 +1,28 @@
|
|||
{
|
||||
"extends": "../tsconfig.backend.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"noEmitOnError": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedParameters": false,
|
||||
"noUnusedLocals": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"declaration": false,
|
||||
"sourceMap": true,
|
||||
"target": "ES2022",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"removeComments": false,
|
||||
"noLib": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"skipLibCheck": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"rootDir": "../src",
|
||||
"baseUrl": "./",
|
||||
"rootDir": "../",
|
||||
"paths": {
|
||||
"@/*": ["../src/*"]
|
||||
},
|
||||
"outDir": "../built-test",
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"typeRoots": [
|
||||
"../src/@types",
|
||||
"../node_modules/@types",
|
||||
"../node_modules"
|
||||
],
|
||||
"lib": [
|
||||
"esnext"
|
||||
]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"../src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules",
|
||||
"**/built/",
|
||||
"**/*.test.ts",
|
||||
"./test/**/*",
|
||||
"./test-federation/**/*",
|
||||
"./test-server/**/*",
|
||||
"../src/**/*.test.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +1,19 @@
|
|||
{
|
||||
"extends": "../../shared/tsconfig.node.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"noEmitOnError": false,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedParameters": false,
|
||||
"noUnusedLocals": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"declaration": false,
|
||||
"types": ["jest", "node"],
|
||||
"outDir": "./built",
|
||||
"sourceMap": true,
|
||||
"target": "ES2022",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"verbatimModuleSyntax": false,
|
||||
"removeComments": false,
|
||||
"noLib": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"skipLibCheck": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["../src/*"]
|
||||
},
|
||||
"typeRoots": [
|
||||
"../node_modules/@types",
|
||||
"../src/@types"
|
||||
],
|
||||
"lib": [
|
||||
"esnext"
|
||||
],
|
||||
"types": ["jest", "node"]
|
||||
]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"../src/**/*.test.ts",
|
||||
|
|
|
|||
33
packages/backend/tsconfig.backend.json
Normal file
33
packages/backend/tsconfig.backend.json
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "../shared/tsconfig.node.json",
|
||||
"compilerOptions": {
|
||||
"removeComments": false,
|
||||
"verbatimModuleSyntax": false,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./built",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"typeRoots": [
|
||||
"./src/@types",
|
||||
"./node_modules/@types",
|
||||
"./node_modules"
|
||||
],
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/built/",
|
||||
"**/*.test.ts",
|
||||
"./src/server/web/**/*.js",
|
||||
"./src/server/web/**/*.mjs",
|
||||
"./src/server/web/**/*.cjs",
|
||||
"./src/server/web/**/*.d.ts",
|
||||
"test/**/*",
|
||||
"test-federation/**/*",
|
||||
"test-server/**/*"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,53 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"noEmitOnError": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedParameters": false,
|
||||
"noUnusedLocals": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"declaration": false,
|
||||
"sourceMap": false,
|
||||
"target": "ES2022",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"removeComments": false,
|
||||
"noLib": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"skipLibCheck": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"rootDir": "./src",
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"outDir": "./built",
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"typeRoots": [
|
||||
"./src/@types",
|
||||
"./node_modules/@types",
|
||||
"./node_modules"
|
||||
],
|
||||
"lib": [
|
||||
"esnext"
|
||||
]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"include": [
|
||||
"./src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"./src/**/*.test.ts"
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"files": [],
|
||||
// WebStorm only reads one tsconfig per directory, so this tricks it into loading both.
|
||||
"references": [
|
||||
{ "path": "./tsconfig.scripts.json" },
|
||||
{ "path": "./tsconfig.backend.json" },
|
||||
{ "path": "./jsconfig.frontend.json" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
18
packages/backend/tsconfig.scripts.json
Normal file
18
packages/backend/tsconfig.scripts.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "../shared/tsconfig.node.json",
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": false,
|
||||
"allowImportingTsExtensions": true,
|
||||
},
|
||||
"include": [
|
||||
"jest.*",
|
||||
"eslint.*",
|
||||
"scripts/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"ormconfig.js",
|
||||
"scripts/check_connect.js",
|
||||
"scripts/generate_api_json.js"
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue