enhance(backend): テストの高速化 (#12939)

* enhance(backend): テストの高速化

* add ls

* 自動的にマージされるようなので不要

* 起動方法を揃える

* fix test
This commit is contained in:
おさむのひと 2024-01-08 17:43:52 +09:00 committed by GitHub
parent 618e2ba1d2
commit 35ec41fc1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 563 additions and 283 deletions

View file

@ -8,7 +8,7 @@ on:
pull_request: pull_request:
jobs: jobs:
jest: unit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
@ -51,9 +51,59 @@ jobs:
- name: Build - name: Build
run: pnpm build run: pnpm build
- name: Test - name: Test
run: pnpm jest-and-coverage run: pnpm --filter backend test-and-coverage
- name: Upload Coverage - name: Upload to Codecov
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v3
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json files: ./packages/backend/coverage/coverage-final.json
e2e:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.10.0]
services:
postgres:
image: postgres:15
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 8
run_install: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.1
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: pnpm build
- name: Test
run: pnpm --filter backend test-and-coverage:e2e
- name: Upload to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json

1
.gitignore vendored
View file

@ -41,6 +41,7 @@ docker-compose.yml
# misskey # misskey
/build /build
built built
built-test
/data /data
/.cache-loader /.cache-loader
/db /db

View file

@ -160,7 +160,6 @@ module.exports = {
testMatch: [ testMatch: [
"<rootDir>/test/unit/**/*.ts", "<rootDir>/test/unit/**/*.ts",
"<rootDir>/src/**/*.test.ts", "<rootDir>/src/**/*.test.ts",
"<rootDir>/test/e2e/**/*.ts",
], ],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped

View file

@ -0,0 +1,15 @@
/*
* 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",
],
};

View file

@ -0,0 +1,14 @@
/*
* 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,
testMatch: [
"<rootDir>/test/unit/**/*.ts",
"<rootDir>/src/**/*.test.ts",
],
};

View file

@ -13,6 +13,7 @@
"revert": "pnpm typeorm migration:revert -d ormconfig.js", "revert": "pnpm typeorm migration:revert -d ormconfig.js",
"check:connect": "node ./check_connect.js", "check:connect": "node ./check_connect.js",
"build": "swc src -d built -D", "build": "swc src -d built -D",
"build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc",
"watch:swc": "swc src -d built -D -w", "watch:swc": "swc src -d built -D -w",
"build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json", "build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
"watch": "node watch.mjs", "watch": "node watch.mjs",
@ -21,11 +22,15 @@
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"eslint": "eslint --quiet \"src/**/*.ts\"", "eslint": "eslint --quiet \"src/**/*.ts\"",
"lint": "pnpm typecheck && pnpm eslint", "lint": "pnpm typecheck && pnpm eslint",
"jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit", "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.unit.cjs",
"jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit", "jest:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.e2e.cjs",
"jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.unit.cjs",
"jest-and-coverage:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.e2e.cjs",
"jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache", "jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache",
"test": "pnpm jest", "test": "pnpm jest",
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
"test-and-coverage": "pnpm jest-and-coverage", "test-and-coverage": "pnpm jest-and-coverage",
"test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e",
"generate-api-json": "node ./generate_api_json.js" "generate-api-json": "node ./generate_api_json.js"
}, },
"optionalDependencies": { "optionalDependencies": {
@ -178,6 +183,7 @@
"devDependencies": { "devDependencies": {
"@jest/globals": "29.7.0", "@jest/globals": "29.7.0",
"@misskey-dev/eslint-plugin": "^1.0.0", "@misskey-dev/eslint-plugin": "^1.0.0",
"@nestjs/platform-express": "^10.3.0",
"@simplewebauthn/typescript-types": "8.3.4", "@simplewebauthn/typescript-types": "8.3.4",
"@swc/jest": "0.2.29", "@swc/jest": "0.2.29",
"@types/accepts": "1.3.7", "@types/accepts": "1.3.7",
@ -226,9 +232,11 @@
"eslint": "8.56.0", "eslint": "8.56.0",
"eslint-plugin-import": "2.29.1", "eslint-plugin-import": "2.29.1",
"execa": "8.0.1", "execa": "8.0.1",
"fkill": "^9.0.0",
"jest": "29.7.0", "jest": "29.7.0",
"jest-mock": "29.7.0", "jest-mock": "29.7.0",
"nodemon": "3.0.2", "nodemon": "3.0.2",
"pid-port": "^1.0.0",
"simple-oauth2": "5.0.0" "simple-oauth2": "5.0.0"
} }
} }

View file

@ -0,0 +1,32 @@
module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
extends: [
'../../shared/.eslintrc.js',
],
rules: {
'import/order': ['warn', {
'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
'pathGroups': [
{
'pattern': '@/**',
'group': 'external',
'position': 'after'
}
],
}],
'no-restricted-globals': [
'error',
{
'name': '__dirname',
'message': 'Not in ESModule. Use `import.meta.url` instead.'
},
{
'name': '__filename',
'message': 'Not in ESModule. Use `import.meta.url` instead.'
}
]
},
};

View file

@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript",
"dynamicImport": true,
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"experimental": {
"keepImportAssertions": true
},
"baseUrl": "../built",
"paths": {
"@/*": ["*"]
},
"target": "es2022"
},
"minify": false
}

View file

@ -0,0 +1,80 @@
import { portToPid } from 'pid-port';
import fkill from 'fkill';
import Fastify from 'fastify';
import { NestFactory } from '@nestjs/core';
import { MainModule } from '@/MainModule.js';
import { ServerService } from '@/server/ServerService.js';
import { loadConfig } from '@/config.js';
import { NestLogger } from '@/NestLogger.js';
const config = loadConfig();
const originEnv = JSON.stringify(process.env);
process.env.NODE_ENV = 'test';
/**
*
*/
async function launch() {
await killTestServer();
console.log('starting application...');
const app = await NestFactory.createApplicationContext(MainModule, {
logger: new NestLogger(),
});
const serverService = app.get(ServerService);
await serverService.launch();
await startControllerEndpoints();
// ジョブキューは必要な時にテストコード側で起動する
// ジョブキューが動くとテスト結果の確認に支障が出ることがあるので意図的に動かさないでいる
console.log('application initialized.');
}
/**
* killする
*/
async function killTestServer() {
//
try {
const pid = await portToPid(config.port);
if (pid) {
await fkill(pid, { force: true });
}
} catch {
// NOP;
}
}
/**
*
* @param port
*/
async function startControllerEndpoints(port = config.port + 1000) {
const fastify = Fastify();
fastify.post<{ Body: { key?: string, value?: string } }>('/env', async (req, res) => {
console.log(req.body);
const key = req.body['key'];
if (!key) {
res.code(400).send({ success: false });
return;
}
process.env[key] = req.body['value'];
res.code(200).send({ success: true });
});
fastify.post<{ Body: { key?: string, value?: string } }>('/env-reset', async (req, res) => {
process.env = JSON.parse(originEnv);
res.code(200).send({ success: true });
});
await fastify.listen({ port: port, host: 'localhost' });
}
export default launch;

View file

@ -0,0 +1,52 @@
{
"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,
"rootDir": "../src",
"baseUrl": "./",
"paths": {
"@/*": ["../src/*"]
},
"outDir": "../built-test",
"types": [
"node"
],
"typeRoots": [
"../src/@types",
"../node_modules/@types",
"../node_modules"
],
"lib": [
"esnext"
]
},
"compileOnSave": false,
"include": [
"./**/*.ts",
"../src/**/*.ts"
],
"exclude": [
"../src/**/*.test.ts"
]
}

View file

@ -10,7 +10,7 @@ import * as crypto from 'node:crypto';
import cbor from 'cbor'; import cbor from 'cbor';
import * as OTPAuth from 'otpauth'; import * as OTPAuth from 'otpauth';
import { loadConfig } from '@/config.js'; import { loadConfig } from '@/config.js';
import { api, signup, startServer } from '../utils.js'; import { api, signup } from '../utils.js';
import type { import type {
AuthenticationResponseJSON, AuthenticationResponseJSON,
AuthenticatorAssertionResponseJSON, AuthenticatorAssertionResponseJSON,
@ -19,11 +19,9 @@ import type {
PublicKeyCredentialRequestOptionsJSON, PublicKeyCredentialRequestOptionsJSON,
RegistrationResponseJSON, RegistrationResponseJSON,
} from '@simplewebauthn/typescript-types'; } from '@simplewebauthn/typescript-types';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('2要素認証', () => { describe('2要素認証', () => {
let app: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
const config = loadConfig(); const config = loadConfig();
@ -185,14 +183,9 @@ describe('2要素認証', () => {
}; };
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username, password }); alice = await signup({ username, password });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('が設定でき、OTPでログインできる。', async () => { test('が設定でき、OTPでログインできる。', async () => {
const registerResponse = await api('/i/2fa/register', { const registerResponse = await api('/i/2fa/register', {
password, password,

View file

@ -6,24 +6,20 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { inspect } from 'node:util';
import { DEFAULT_POLICIES } from '@/core/RoleService.js'; import { DEFAULT_POLICIES } from '@/core/RoleService.js';
import type { Packed } from '@/misc/json-schema.js'; import type { Packed } from '@/misc/json-schema.js';
import { import {
signup,
post,
userList,
page,
role,
startServer,
api, api,
successfulApiCall,
failedApiCall, failedApiCall,
uploadFile, post,
role,
signup,
successfulApiCall,
testPaginationConsistency, testPaginationConsistency,
uploadFile,
userList,
} from '../utils.js'; } from '../utils.js';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
import type { INestApplicationContext } from '@nestjs/common';
const compareBy = <T extends { id: string }>(selector: (s: T) => string = (s: T): string => s.id) => (a: T, b: T): number => { const compareBy = <T extends { id: string }>(selector: (s: T) => string = (s: T): string => s.id) => (a: T, b: T): number => {
return selector(a).localeCompare(selector(b)); return selector(a).localeCompare(selector(b));
@ -54,8 +50,6 @@ describe('アンテナ', () => {
withReplies: false, withReplies: false,
}; };
let app: INestApplicationContext;
let root: User; let root: User;
let alice: User; let alice: User;
let bob: User; let bob: User;
@ -79,10 +73,6 @@ describe('アンテナ', () => {
let userMutingAlice: User; let userMutingAlice: User;
let userMutedByAlice: User; let userMutedByAlice: User;
beforeAll(async () => {
app = await startServer();
}, 1000 * 60 * 2);
beforeAll(async () => { beforeAll(async () => {
root = await signup({ username: 'root' }); root = await signup({ username: 'root' });
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
@ -136,10 +126,6 @@ describe('アンテナ', () => {
await api('mute/create', { userId: userMutedByAlice.id }, alice); await api('mute/create', { userId: userMutedByAlice.id }, alice);
}, 1000 * 60 * 10); }, 1000 * 60 * 10);
afterAll(async () => {
await app.close();
});
beforeEach(async () => { beforeEach(async () => {
// テスト間で影響し合わないように毎回全部消す。 // テスト間で影響し合わないように毎回全部消す。
for (const user of [alice, bob]) { for (const user of [alice, bob]) {

View file

@ -6,21 +6,10 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, post, startServer } from '../utils.js'; import { api, post, signup } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('API visibility', () => { describe('API visibility', () => {
let app: INestApplicationContext;
beforeAll(async () => {
app = await startServer();
}, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
describe('Note visibility', () => { describe('Note visibility', () => {
//#region vars //#region vars
/** ヒロイン */ /** ヒロイン */

View file

@ -7,27 +7,30 @@ process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { IncomingMessage } from 'http'; import { IncomingMessage } from 'http';
import { signup, api, startServer, successfulApiCall, failedApiCall, uploadFile, waitFire, connectStream, relativeFetch, createAppToken } from '../utils.js'; import {
import type { INestApplicationContext } from '@nestjs/common'; api,
connectStream,
createAppToken,
failedApiCall,
relativeFetch,
signup,
successfulApiCall,
uploadFile,
waitFire,
} from '../utils.js';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('API', () => { describe('API', () => {
let app: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
let carol: misskey.entities.SignupResponse; let carol: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
carol = await signup({ username: 'carol' }); carol = await signup({ username: 'carol' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
describe('General validation', () => { describe('General validation', () => {
test('wrong type', async () => { test('wrong type', async () => {
const res = await api('/test', { const res = await api('/test', {

View file

@ -6,29 +6,21 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, post, startServer } from '../utils.js'; import { api, post, signup } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Block', () => { describe('Block', () => {
let app: INestApplicationContext;
// alice blocks bob // alice blocks bob
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
let carol: misskey.entities.SignupResponse; let carol: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
carol = await signup({ username: 'carol' }); carol = await signup({ username: 'carol' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('Block作成', async () => { test('Block作成', async () => {
const res = await api('/blocking/create', { const res = await api('/blocking/create', {
userId: bob.id, userId: bob.id,

View file

@ -18,25 +18,13 @@ import { paramDef as UnfavoriteParamDef } from '@/server/api/endpoints/clips/unf
import { paramDef as AddNoteParamDef } from '@/server/api/endpoints/clips/add-note.js'; import { paramDef as AddNoteParamDef } from '@/server/api/endpoints/clips/add-note.js';
import { paramDef as RemoveNoteParamDef } from '@/server/api/endpoints/clips/remove-note.js'; import { paramDef as RemoveNoteParamDef } from '@/server/api/endpoints/clips/remove-note.js';
import { paramDef as NotesParamDef } from '@/server/api/endpoints/clips/notes.js'; import { paramDef as NotesParamDef } from '@/server/api/endpoints/clips/notes.js';
import { import { api, ApiRequest, failedApiCall, hiddenNote, post, signup, successfulApiCall } from '../utils.js';
signup,
post,
startServer,
api,
successfulApiCall,
failedApiCall,
ApiRequest,
hiddenNote,
} from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
describe('クリップ', () => { describe('クリップ', () => {
type User = Packed<'User'>; type User = Packed<'User'>;
type Note = Packed<'Note'>; type Note = Packed<'Note'>;
type Clip = Packed<'Clip'>; type Clip = Packed<'Clip'>;
let app: INestApplicationContext;
let alice: User; let alice: User;
let bob: User; let bob: User;
let aliceNote: Note; let aliceNote: Note;
@ -145,7 +133,6 @@ describe('クリップ', () => {
}; };
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
@ -160,10 +147,6 @@ describe('クリップ', () => {
bobSpecifiedNote = await post(bob, { text: 'specified only', visibility: 'specified' }) as any; bobSpecifiedNote = await post(bob, { text: 'specified only', visibility: 'specified' }) as any;
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
afterEach(async () => { afterEach(async () => {
// テスト間で影響し合わないように毎回全部消す。 // テスト間で影響し合わないように毎回全部消す。
for (const user of [alice, bob]) { for (const user of [alice, bob]) {

View file

@ -10,30 +10,22 @@ import * as assert from 'assert';
// https://github.com/node-fetch/node-fetch/pull/1664 // https://github.com/node-fetch/node-fetch/pull/1664
import { Blob } from 'node-fetch'; import { Blob } from 'node-fetch';
import { MiUser } from '@/models/_.js'; import { MiUser } from '@/models/_.js';
import { startServer, signup, post, api, uploadFile, simpleGet, initTestDb } from '../utils.js'; import { api, initTestDb, post, signup, simpleGet, uploadFile } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Endpoints', () => { describe('Endpoints', () => {
let app: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
let carol: misskey.entities.SignupResponse; let carol: misskey.entities.SignupResponse;
let dave: misskey.entities.SignupResponse; let dave: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
carol = await signup({ username: 'carol' }); carol = await signup({ username: 'carol' });
dave = await signup({ username: 'dave' }); dave = await signup({ username: 'dave' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
describe('signup', () => { describe('signup', () => {
test('不正なユーザー名でアカウントが作成できない', async () => { test('不正なユーザー名でアカウントが作成できない', async () => {
const res = await api('signup', { const res = await api('signup', {

View file

@ -6,12 +6,12 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, startServer, startJobQueue, port, post } from '../utils.js'; import { api, port, post, signup, startJobQueue } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common'; import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('export-clips', () => { describe('export-clips', () => {
let app: INestApplicationContext; let queue: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
@ -33,14 +33,13 @@ describe('export-clips', () => {
} }
beforeAll(async () => { beforeAll(async () => {
app = await startServer(); queue = await startJobQueue();
await startJobQueue();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => { afterAll(async () => {
await app.close(); await queue.close();
}); });
beforeEach(async () => { beforeEach(async () => {

View file

@ -6,9 +6,8 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { startServer, channel, clip, cookie, galleryPost, signup, page, play, post, simpleGet, uploadFile } from '../utils.js'; import { channel, clip, cookie, galleryPost, page, play, post, signup, simpleGet, uploadFile } from '../utils.js';
import type { SimpleGetResponse } from '../utils.js'; import type { SimpleGetResponse } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
// Request Accept // Request Accept
@ -23,8 +22,6 @@ const HTML = 'text/html; charset=utf-8';
const JSON_UTF8 = 'application/json; charset=utf-8'; const JSON_UTF8 = 'application/json; charset=utf-8';
describe('Webリソース', () => { describe('Webリソース', () => {
let app: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let aliceUploadedFile: any; let aliceUploadedFile: any;
let alicesPost: any; let alicesPost: any;
@ -79,7 +76,6 @@ describe('Webリソース', () => {
}; };
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
aliceUploadedFile = await uploadFile(alice); aliceUploadedFile = await uploadFile(alice);
alicesPost = await post(alice, { alicesPost = await post(alice, {
@ -96,10 +92,6 @@ describe('Webリソース', () => {
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
describe.each([ describe.each([
{ path: '/', type: HTML }, { path: '/', type: HTML },
{ path: '/docs/ja-JP/about', type: HTML }, // "指定されたURLに該当するページはありませんでした。" { path: '/docs/ja-JP/about', type: HTML }, // "指定されたURLに該当するページはありませんでした。"

View file

@ -6,26 +6,18 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, startServer, simpleGet } from '../utils.js'; import { api, signup, simpleGet } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('FF visibility', () => { describe('FF visibility', () => {
let app: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('followingVisibility, followersVisibility がともに public なユーザーのフォロー/フォロワーを誰でも見れる', async () => { test('followingVisibility, followersVisibility がともに public なユーザーのフォロー/フォロワーを誰でも見れる', async () => {
await api('/i/update', { await api('/i/update', {
followingVisibility: 'public', followingVisibility: 'public',

View file

@ -3,19 +3,19 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { INestApplicationContext } from '@nestjs/common';
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { loadConfig } from '@/config.js'; import { loadConfig } from '@/config.js';
import { MiUser, UsersRepository } from '@/models/_.js'; import { MiUser, UsersRepository } from '@/models/_.js';
import { jobQueue } from '@/boot/common.js';
import { secureRndstr } from '@/misc/secure-rndstr.js'; import { secureRndstr } from '@/misc/secure-rndstr.js';
import { uploadFile, signup, startServer, initTestDb, api, sleep, successfulApiCall } from '../utils.js'; import { jobQueue } from '@/boot/common.js';
import type { INestApplicationContext } from '@nestjs/common'; import { api, initTestDb, signup, sleep, successfulApiCall, uploadFile } from '../utils.js';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Account Move', () => { describe('Account Move', () => {
let app: INestApplicationContext;
let jq: INestApplicationContext; let jq: INestApplicationContext;
let url: URL; let url: URL;
@ -30,8 +30,8 @@ describe('Account Move', () => {
let Users: UsersRepository; let Users: UsersRepository;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
jq = await jobQueue(); jq = await jobQueue();
const config = loadConfig(); const config = loadConfig();
url = new URL(config.url); url = new URL(config.url);
const connection = await initTestDb(false); const connection = await initTestDb(false);
@ -46,7 +46,7 @@ describe('Account Move', () => {
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => { afterAll(async () => {
await Promise.all([app.close(), jq.close()]); await jq.close();
}); });
describe('Create Alias', () => { describe('Create Alias', () => {

View file

@ -6,29 +6,21 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, post, react, startServer, waitFire } from '../utils.js'; import { api, post, react, signup, waitFire } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Mute', () => { describe('Mute', () => {
let app: INestApplicationContext;
// alice mutes carol // alice mutes carol
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
let carol: misskey.entities.SignupResponse; let carol: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
carol = await signup({ username: 'carol' }); carol = await signup({ username: 'carol' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('ミュート作成', async () => { test('ミュート作成', async () => {
const res = await api('/mute/create', { const res = await api('/mute/create', {
userId: carol.id, userId: carol.id,

View file

@ -6,20 +6,9 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { relativeFetch, startServer } from '../utils.js'; import { relativeFetch } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
describe('nodeinfo', () => { describe('nodeinfo', () => {
let app: INestApplicationContext;
beforeAll(async () => {
app = await startServer();
}, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('nodeinfo 2.1', async () => { test('nodeinfo 2.1', async () => {
const res = await relativeFetch('nodeinfo/2.1'); const res = await relativeFetch('nodeinfo/2.1');
assert.ok(res.ok); assert.ok(res.ok);

View file

@ -8,29 +8,22 @@ process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { MiNote } from '@/models/Note.js'; import { MiNote } from '@/models/Note.js';
import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js';
import { signup, post, uploadUrl, startServer, initTestDb, api, uploadFile } from '../utils.js'; import { api, initTestDb, post, signup, uploadFile, uploadUrl } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Note', () => { describe('Note', () => {
let app: INestApplicationContext;
let Notes: any; let Notes: any;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
const connection = await initTestDb(true); const connection = await initTestDb(true);
Notes = connection.getRepository(MiNote); Notes = connection.getRepository(MiNote);
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('投稿できる', async () => { test('投稿できる', async () => {
const post = { const post = {
text: 'test', text: 'test',

View file

@ -11,13 +11,18 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { AuthorizationCode, ResourceOwnerPassword, type AuthorizationTokenConfig, ClientCredentials, ModuleOptions } from 'simple-oauth2'; import {
AuthorizationCode,
type AuthorizationTokenConfig,
ClientCredentials,
ModuleOptions,
ResourceOwnerPassword,
} from 'simple-oauth2';
import pkceChallenge from 'pkce-challenge'; import pkceChallenge from 'pkce-challenge';
import { JSDOM } from 'jsdom'; import { JSDOM } from 'jsdom';
import Fastify, { type FastifyReply, type FastifyInstance } from 'fastify'; import Fastify, { type FastifyInstance, type FastifyReply } from 'fastify';
import { api, port, signup, startServer } from '../utils.js'; import { api, port, sendEnvUpdateRequest, signup } from '../utils.js';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
import type { INestApplicationContext } from '@nestjs/common';
const host = `http://127.0.0.1:${port}`; const host = `http://127.0.0.1:${port}`;
@ -147,7 +152,6 @@ async function assertDirectError(response: Response, status: number, error: stri
} }
describe('OAuth', () => { describe('OAuth', () => {
let app: INestApplicationContext;
let fastify: FastifyInstance; let fastify: FastifyInstance;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
@ -156,7 +160,6 @@ describe('OAuth', () => {
let sender: (reply: FastifyReply) => void; let sender: (reply: FastifyReply) => void;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
@ -168,7 +171,7 @@ describe('OAuth', () => {
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
beforeEach(async () => { beforeEach(async () => {
process.env.MISSKEY_TEST_CHECK_IP_RANGE = ''; await sendEnvUpdateRequest({ key: 'MISSKEY_TEST_CHECK_IP_RANGE', value: '' });
sender = (reply): void => { sender = (reply): void => {
reply.send(` reply.send(`
<!DOCTYPE html> <!DOCTYPE html>
@ -180,7 +183,6 @@ describe('OAuth', () => {
afterAll(async () => { afterAll(async () => {
await fastify.close(); await fastify.close();
await app.close();
}); });
test('Full flow', async () => { test('Full flow', async () => {
@ -881,7 +883,7 @@ describe('OAuth', () => {
}); });
test('Disallow loopback', async () => { test('Disallow loopback', async () => {
process.env.MISSKEY_TEST_CHECK_IP_RANGE = '1'; await sendEnvUpdateRequest({ key: 'MISSKEY_TEST_CHECK_IP_RANGE', value: '1' });
const client = new AuthorizationCode(clientConfig); const client = new AuthorizationCode(clientConfig);
const response = await fetch(client.authorizeURL({ const response = await fetch(client.authorizeURL({

View file

@ -6,29 +6,21 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, post, react, startServer, waitFire, sleep } from '../utils.js'; import { api, post, signup, sleep, waitFire } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Renote Mute', () => { describe('Renote Mute', () => {
let app: INestApplicationContext;
// alice mutes carol // alice mutes carol
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
let carol: misskey.entities.SignupResponse; let carol: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
carol = await signup({ username: 'carol' }); carol = await signup({ username: 'carol' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('ミュート作成', async () => { test('ミュート作成', async () => {
const res = await api('/renote-mute/create', { const res = await api('/renote-mute/create', {
userId: carol.id, userId: carol.id,

View file

@ -8,12 +8,10 @@ process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { WebSocket } from 'ws'; import { WebSocket } from 'ws';
import { MiFollowing } from '@/models/Following.js'; import { MiFollowing } from '@/models/Following.js';
import { signup, api, post, startServer, initTestDb, waitFire, createAppToken, port } from '../utils.js'; import { api, createAppToken, initTestDb, port, post, signup, waitFire } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Streaming', () => { describe('Streaming', () => {
let app: INestApplicationContext;
let Followings: any; let Followings: any;
const follow = async (follower: any, followee: any) => { const follow = async (follower: any, followee: any) => {
@ -48,7 +46,6 @@ describe('Streaming', () => {
let list: any; let list: any;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
const connection = await initTestDb(true); const connection = await initTestDb(true);
Followings = connection.getRepository(MiFollowing); Followings = connection.getRepository(MiFollowing);
@ -95,10 +92,6 @@ describe('Streaming', () => {
}, chitose); }, chitose);
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
describe('Events', () => { describe('Events', () => {
test('mention event', async () => { test('mention event', async () => {
const fired = await waitFire( const fired = await waitFire(

View file

@ -6,28 +6,20 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, post, connectStream, startServer } from '../utils.js'; import { api, connectStream, post, signup } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('Note thread mute', () => { describe('Note thread mute', () => {
let app: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let bob: misskey.entities.SignupResponse; let bob: misskey.entities.SignupResponse;
let carol: misskey.entities.SignupResponse; let carol: misskey.entities.SignupResponse;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
bob = await signup({ username: 'bob' }); bob = await signup({ username: 'bob' });
carol = await signup({ username: 'carol' }); carol = await signup({ username: 'carol' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('notes/mentions にミュートしているスレッドの投稿が含まれない', async () => { test('notes/mentions にミュートしているスレッドの投稿が含まれない', async () => {
const bobNote = await post(bob, { text: '@alice @carol root note' }); const bobNote = await post(bob, { text: '@alice @carol root note' });
const aliceReply = await post(alice, { replyId: bobNote.id, text: '@bob @carol child note' }); const aliceReply = await post(alice, { replyId: bobNote.id, text: '@bob @carol child note' });

View file

@ -6,12 +6,8 @@
// How to run: // How to run:
// pnpm jest -- e2e/timelines.ts // pnpm jest -- e2e/timelines.ts
process.env.NODE_ENV = 'test';
process.env.FORCE_FOLLOW_REMOTE_USER_FOR_TESTING = 'true';
import * as assert from 'assert'; import * as assert from 'assert';
import { api, post, randomString, signup, sleep, startServer, uploadUrl } from '../utils.js'; import { api, post, randomString, sendEnvUpdateRequest, signup, sleep, uploadUrl } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
function genHost() { function genHost() {
return randomString() + '.example.com'; return randomString() + '.example.com';
@ -21,16 +17,6 @@ function waitForPushToTl() {
return sleep(500); return sleep(500);
} }
let app: INestApplicationContext;
beforeAll(async () => {
app = await startServer();
}, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
describe('Timelines', () => { describe('Timelines', () => {
describe('Home TL', () => { describe('Home TL', () => {
test.concurrent('自分の visibility: followers なノートが含まれる', async () => { test.concurrent('自分の visibility: followers なノートが含まれる', async () => {
@ -334,8 +320,9 @@ describe('Timelines', () => {
test.concurrent('フォローしているリモートユーザーのノートが含まれる', async () => { test.concurrent('フォローしているリモートユーザーのノートが含まれる', async () => {
const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]);
await sendEnvUpdateRequest({ key: 'FORCE_FOLLOW_REMOTE_USER_FOR_TESTING', value: 'true' });
await api('/following/create', { userId: bob.id }, alice); await api('/following/create', { userId: bob.id }, alice);
await sleep(1000);
const bobNote = await post(bob, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi' });
await waitForPushToTl(); await waitForPushToTl();
@ -348,8 +335,9 @@ describe('Timelines', () => {
test.concurrent('フォローしているリモートユーザーの visibility: home なノートが含まれる', async () => { test.concurrent('フォローしているリモートユーザーの visibility: home なノートが含まれる', async () => {
const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]);
await sendEnvUpdateRequest({ key: 'FORCE_FOLLOW_REMOTE_USER_FOR_TESTING', value: 'true' });
await api('/following/create', { userId: bob.id }, alice); await api('/following/create', { userId: bob.id }, alice);
await sleep(1000);
const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
await waitForPushToTl(); await waitForPushToTl();
@ -762,8 +750,9 @@ describe('Timelines', () => {
test.concurrent('フォローしているリモートユーザーのノートが含まれる', async () => { test.concurrent('フォローしているリモートユーザーのノートが含まれる', async () => {
const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]);
await sendEnvUpdateRequest({ key: 'FORCE_FOLLOW_REMOTE_USER_FOR_TESTING', value: 'true' });
await api('/following/create', { userId: bob.id }, alice); await api('/following/create', { userId: bob.id }, alice);
await sleep(1000);
const bobNote = await post(bob, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi' });
await waitForPushToTl(); await waitForPushToTl();
@ -776,8 +765,9 @@ describe('Timelines', () => {
test.concurrent('フォローしているリモートユーザーの visibility: home なノートが含まれる', async () => { test.concurrent('フォローしているリモートユーザーの visibility: home なノートが含まれる', async () => {
const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]); const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]);
await sendEnvUpdateRequest({ key: 'FORCE_FOLLOW_REMOTE_USER_FOR_TESTING', value: 'true' });
await api('/following/create', { userId: bob.id }, alice); await api('/following/create', { userId: bob.id }, alice);
await sleep(1000);
const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); const bobNote = await post(bob, { text: 'hi', visibility: 'home' });
await waitForPushToTl(); await waitForPushToTl();

View file

@ -6,20 +6,16 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { signup, api, post, uploadUrl, startServer } from '../utils.js'; import { api, post, signup, uploadUrl } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('users/notes', () => { describe('users/notes', () => {
let app: INestApplicationContext;
let alice: misskey.entities.SignupResponse; let alice: misskey.entities.SignupResponse;
let jpgNote: any; let jpgNote: any;
let pngNote: any; let pngNote: any;
let jpgPngNote: any; let jpgPngNote: any;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'); const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg');
const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.png'); const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.png');
@ -34,10 +30,6 @@ describe('users/notes', () => {
}); });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async() => {
await app.close();
});
test('withFiles', async () => { test('withFiles', async () => {
const res = await api('/users/notes', { const res = await api('/users/notes', {
userId: alice.id, userId: alice.id,

View file

@ -8,20 +8,8 @@ process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { inspect } from 'node:util'; import { inspect } from 'node:util';
import { DEFAULT_POLICIES } from '@/core/RoleService.js'; import { DEFAULT_POLICIES } from '@/core/RoleService.js';
import type { Packed } from '@/misc/json-schema.js'; import { api, page, post, role, signup, successfulApiCall, uploadFile } from '../utils.js';
import {
signup,
post,
page,
role,
startServer,
api,
successfulApiCall,
failedApiCall,
uploadFile,
} from '../utils.js';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
import type { INestApplicationContext } from '@nestjs/common';
describe('ユーザー', () => { describe('ユーザー', () => {
// エンティティとしてのユーザーを主眼においたテストを記述する // エンティティとしてのユーザーを主眼においたテストを記述する
@ -185,8 +173,6 @@ describe('ユーザー', () => {
}); });
}; };
let app: INestApplicationContext;
let root: User; let root: User;
let alice: User; let alice: User;
let aliceNote: misskey.entities.Note; let aliceNote: misskey.entities.Note;
@ -230,10 +216,6 @@ describe('ユーザー', () => {
let userFollowRequesting: User; let userFollowRequesting: User;
let userFollowRequested: User; let userFollowRequested: User;
beforeAll(async () => {
app = await startServer();
}, 1000 * 60 * 2);
beforeAll(async () => { beforeAll(async () => {
root = await signup({ username: 'root' }); root = await signup({ username: 'root' });
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
@ -321,10 +303,6 @@ describe('ユーザー', () => {
await api('following/create', { userId: userFollowRequested.id }, userFollowRequesting); await api('following/create', { userId: userFollowRequested.id }, userFollowRequesting);
}, 1000 * 60 * 10); }, 1000 * 60 * 10);
afterAll(async () => {
await app.close();
});
beforeEach(async () => { beforeEach(async () => {
alice = { alice = {
...alice, ...alice,

View file

@ -6,24 +6,16 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import * as assert from 'assert'; import * as assert from 'assert';
import { host, origin, relativeFetch, signup, startServer } from '../utils.js'; import { host, origin, relativeFetch, signup } from '../utils.js';
import type { INestApplicationContext } from '@nestjs/common';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
describe('.well-known', () => { describe('.well-known', () => {
let app: INestApplicationContext;
let alice: misskey.entities.User; let alice: misskey.entities.User;
beforeAll(async () => { beforeAll(async () => {
app = await startServer();
alice = await signup({ username: 'alice' }); alice = await signup({ username: 'alice' });
}, 1000 * 60 * 2); }, 1000 * 60 * 2);
afterAll(async () => {
await app.close();
});
test('nodeinfo', async () => { test('nodeinfo', async () => {
const res = await relativeFetch('.well-known/nodeinfo'); const res = await relativeFetch('.well-known/nodeinfo');
assert.ok(res.ok); assert.ok(res.ok);

View file

@ -0,0 +1,8 @@
import { initTestDb, sendEnvResetRequest } from './utils.js';
beforeAll(async () => {
await Promise.all([
initTestDb(false),
sendEnvResetRequest(),
]);
});

View file

@ -15,7 +15,13 @@ import type { LoggerService } from '@/core/LoggerService.js';
import type { MetaService } from '@/core/MetaService.js'; import type { MetaService } from '@/core/MetaService.js';
import type { UtilityService } from '@/core/UtilityService.js'; import type { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import type { NoteReactionsRepository, NotesRepository, PollsRepository, UsersRepository, FollowRequestsRepository } from '@/models/_.js'; import type {
FollowRequestsRepository,
NoteReactionsRepository,
NotesRepository,
PollsRepository,
UsersRepository,
} from '@/models/_.js';
type MockResponse = { type MockResponse = {
type: string; type: string;

View file

@ -10,7 +10,13 @@ import { ModuleMocker } from 'jest-mock';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
import { GlobalModule } from '@/GlobalModule.js'; import { GlobalModule } from '@/GlobalModule.js';
import { AnnouncementService } from '@/core/AnnouncementService.js'; import { AnnouncementService } from '@/core/AnnouncementService.js';
import type { MiAnnouncement, AnnouncementsRepository, AnnouncementReadsRepository, UsersRepository, MiUser } from '@/models/_.js'; import type {
AnnouncementReadsRepository,
AnnouncementsRepository,
MiAnnouncement,
MiUser,
UsersRepository,
} from '@/models/_.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { genAidx } from '@/misc/id/aidx.js'; import { genAidx } from '@/misc/id/aidx.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';

View file

@ -6,7 +6,13 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
import { DeleteObjectCommandOutput, DeleteObjectCommand, NoSuchKey, InvalidObjectState, S3Client } from '@aws-sdk/client-s3'; import {
DeleteObjectCommand,
DeleteObjectCommandOutput,
InvalidObjectState,
NoSuchKey,
S3Client,
} from '@aws-sdk/client-s3';
import { mockClient } from 'aws-sdk-client-mock'; import { mockClient } from 'aws-sdk-client-mock';
import { GlobalModule } from '@/GlobalModule.js'; import { GlobalModule } from '@/GlobalModule.js';
import { DriveService } from '@/core/DriveService.js'; import { DriveService } from '@/core/DriveService.js';

View file

@ -55,7 +55,8 @@ describe('FetchInstanceMetadataService', () => {
return { fetch: jest.fn() }; return { fetch: jest.fn() };
} else if (token === DI.redis) { } else if (token === DI.redis) {
return mockRedis; return mockRedis;
}}) }
})
.compile(); .compile();
app.enableShutdownHooks(); app.enableShutdownHooks();

View file

@ -10,7 +10,7 @@ import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path'; import { dirname } from 'node:path';
import { ModuleMocker } from 'jest-mock'; import { ModuleMocker } from 'jest-mock';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
import { describe, beforeAll, afterAll, test } from '@jest/globals'; import { afterAll, beforeAll, describe, test } from '@jest/globals';
import { GlobalModule } from '@/GlobalModule.js'; import { GlobalModule } from '@/GlobalModule.js';
import { FileInfoService } from '@/core/FileInfoService.js'; import { FileInfoService } from '@/core/FileInfoService.js';
//import { DI } from '@/di-symbols.js'; //import { DI } from '@/di-symbols.js';

View file

@ -6,15 +6,13 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import { jest } from '@jest/globals'; import { jest } from '@jest/globals';
import { ModuleMocker } from 'jest-mock';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
import { GlobalModule } from '@/GlobalModule.js'; import { GlobalModule } from '@/GlobalModule.js';
import type { MetasRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { CoreModule } from '@/core/CoreModule.js'; import { CoreModule } from '@/core/CoreModule.js';
import type { DataSource } from 'typeorm';
import type { TestingModule } from '@nestjs/testing'; import type { TestingModule } from '@nestjs/testing';
import type { DataSource } from 'typeorm';
describe('MetaService', () => { describe('MetaService', () => {
let app: TestingModule; let app: TestingModule;

View file

@ -11,7 +11,7 @@ import { Test } from '@nestjs/testing';
import * as lolex from '@sinonjs/fake-timers'; import * as lolex from '@sinonjs/fake-timers';
import { GlobalModule } from '@/GlobalModule.js'; import { GlobalModule } from '@/GlobalModule.js';
import { RoleService } from '@/core/RoleService.js'; import { RoleService } from '@/core/RoleService.js';
import type { MiRole, RolesRepository, RoleAssignmentsRepository, UsersRepository, MiUser } from '@/models/_.js'; import type { MiRole, MiUser, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { genAidx } from '@/misc/id/aidx.js'; import { genAidx } from '@/misc/id/aidx.js';

View file

@ -6,7 +6,13 @@
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
import { UploadPartCommand, CompleteMultipartUploadCommand, CreateMultipartUploadCommand, S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; import {
CompleteMultipartUploadCommand,
CreateMultipartUploadCommand,
PutObjectCommand,
S3Client,
UploadPartCommand,
} from '@aws-sdk/client-s3';
import { mockClient } from 'aws-sdk-client-mock'; import { mockClient } from 'aws-sdk-client-mock';
import { GlobalModule } from '@/GlobalModule.js'; import { GlobalModule } from '@/GlobalModule.js';
import { CoreModule } from '@/core/CoreModule.js'; import { CoreModule } from '@/core/CoreModule.js';

View file

@ -4,13 +4,13 @@
*/ */
import { ulid } from 'ulid'; import { ulid } from 'ulid';
import { describe, test, expect } from '@jest/globals'; import { describe, expect, test } from '@jest/globals';
import { aidRegExp, genAid, parseAid } from '@/misc/id/aid.js'; import { aidRegExp, genAid, parseAid } from '@/misc/id/aid.js';
import { aidxRegExp, genAidx, parseAidx } from '@/misc/id/aidx.js'; import { aidxRegExp, genAidx, parseAidx } from '@/misc/id/aidx.js';
import { genMeid, meidRegExp, parseMeid } from '@/misc/id/meid.js'; import { genMeid, meidRegExp, parseMeid } from '@/misc/id/meid.js';
import { genMeidg, meidgRegExp, parseMeidg } from '@/misc/id/meidg.js'; import { genMeidg, meidgRegExp, parseMeidg } from '@/misc/id/meidg.js';
import { genObjectId, objectIdRegExp, parseObjectId } from '@/misc/id/object-id.js'; import { genObjectId, objectIdRegExp, parseObjectId } from '@/misc/id/object-id.js';
import { ulidRegExp, parseUlid } from '@/misc/id/ulid.js'; import { parseUlid, ulidRegExp } from '@/misc/id/ulid.js';
describe('misc:id', () => { describe('misc:id', () => {
test('aid', () => { test('aid', () => {

View file

@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { describe, test, expect } from '@jest/globals'; import { describe, expect, test } from '@jest/globals';
import { contentDisposition } from '@/misc/content-disposition.js'; import { contentDisposition } from '@/misc/content-disposition.js';
describe('misc:content-disposition', () => { describe('misc:content-disposition', () => {

View file

@ -5,7 +5,7 @@
import * as assert from 'node:assert'; import * as assert from 'node:assert';
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import { isAbsolute, basename } from 'node:path'; import { basename, isAbsolute } from 'node:path';
import { randomUUID } from 'node:crypto'; import { randomUUID } from 'node:crypto';
import { inspect } from 'node:util'; import { inspect } from 'node:util';
import WebSocket, { ClientOptions } from 'ws'; import WebSocket, { ClientOptions } from 'ws';
@ -68,7 +68,11 @@ export const failedApiCall = async <T, >(request: ApiRequest, assertion: {
return res.body; return res.body;
}; };
const request = async (path: string, params: any, me?: UserToken): Promise<{ status: number, headers: Headers, body: any }> => { const request = async (path: string, params: any, me?: UserToken): Promise<{
status: number,
headers: Headers,
body: any
}> => {
const bodyAuth: Record<string, string> = {}; const bodyAuth: Record<string, string> = {};
const headers: Record<string, string> = { const headers: Record<string, string> = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -275,7 +279,11 @@ interface UploadOptions {
* Upload file * Upload file
* @param user User * @param user User
*/ */
export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadOptions = {}): Promise<{ status: number, headers: Headers, body: misskey.Endpoints['drive/files/create']['res'] | null }> => { export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadOptions = {}): Promise<{
status: number,
headers: Headers,
body: misskey.Endpoints['drive/files/create']['res'] | null
}> => {
const absPath = path == null const absPath = path == null
? new URL('resources/Lenna.jpg', import.meta.url) ? new URL('resources/Lenna.jpg', import.meta.url)
: isAbsolute(path.toString()) : isAbsolute(path.toString())
@ -426,8 +434,8 @@ export const simpleGet = async (path: string, accept = '*/*', cookie: any = unde
]; ];
const body = const body =
jsonTypes.includes(res.headers.get('content-type') ?? '') ? await res.json() : jsonTypes.includes(res.headers.get('content-type') ?? '') ? await res.json() :
htmlTypes.includes(res.headers.get('content-type') ?? '') ? new JSDOM(await res.text()) : htmlTypes.includes(res.headers.get('content-type') ?? '') ? new JSDOM(await res.text()) :
null; null;
return { return {
@ -557,3 +565,34 @@ export function sleep(msec: number) {
}, msec); }, msec);
}); });
} }
export async function sendEnvUpdateRequest(params: { key: string, value?: string }) {
const res = await fetch(
`http://localhost:${port + 1000}/env`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
},
);
if (res.status !== 200) {
throw new Error('server env update failed.');
}
}
export async function sendEnvResetRequest() {
const res = await fetch(
`http://localhost:${port + 1000}/env-reset`,
{
method: 'POST',
body: JSON.stringify({}),
},
);
if (res.status !== 200) {
throw new Error('server env update failed.');
}
}

View file

@ -112,10 +112,10 @@ importers:
version: 10.2.10(reflect-metadata@0.1.14)(rxjs@7.8.1) version: 10.2.10(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/core': '@nestjs/core':
specifier: 10.2.10 specifier: 10.2.10
version: 10.2.10(@nestjs/common@10.2.10)(reflect-metadata@0.1.14)(rxjs@7.8.1) version: 10.2.10(@nestjs/common@10.2.10)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/testing': '@nestjs/testing':
specifier: 10.2.10 specifier: 10.2.10
version: 10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10) version: 10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(@nestjs/platform-express@10.3.0)
'@peertube/http-signature': '@peertube/http-signature':
specifier: 1.7.0 specifier: 1.7.0
version: 1.7.0 version: 1.7.0
@ -496,6 +496,9 @@ importers:
'@misskey-dev/eslint-plugin': '@misskey-dev/eslint-plugin':
specifier: ^1.0.0 specifier: ^1.0.0
version: 1.0.0(@typescript-eslint/eslint-plugin@6.14.0)(@typescript-eslint/parser@6.14.0)(eslint-plugin-import@2.29.1)(eslint@8.56.0) version: 1.0.0(@typescript-eslint/eslint-plugin@6.14.0)(@typescript-eslint/parser@6.14.0)(eslint-plugin-import@2.29.1)(eslint@8.56.0)
'@nestjs/platform-express':
specifier: ^10.3.0
version: 10.3.0(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)
'@simplewebauthn/typescript-types': '@simplewebauthn/typescript-types':
specifier: 8.3.4 specifier: 8.3.4
version: 8.3.4 version: 8.3.4
@ -640,6 +643,9 @@ importers:
execa: execa:
specifier: 8.0.1 specifier: 8.0.1
version: 8.0.1 version: 8.0.1
fkill:
specifier: ^9.0.0
version: 9.0.0
jest: jest:
specifier: 29.7.0 specifier: 29.7.0
version: 29.7.0(@types/node@20.10.5) version: 29.7.0(@types/node@20.10.5)
@ -649,6 +655,9 @@ importers:
nodemon: nodemon:
specifier: 3.0.2 specifier: 3.0.2
version: 3.0.2 version: 3.0.2
pid-port:
specifier: ^1.0.0
version: 1.0.0
simple-oauth2: simple-oauth2:
specifier: 5.0.0 specifier: 5.0.0
version: 5.0.0 version: 5.0.0
@ -4878,7 +4887,6 @@ packages:
/@lukeed/csprng@1.0.1: /@lukeed/csprng@1.0.1:
resolution: {integrity: sha512-uSvJdwQU5nK+Vdf6zxcWAY2A8r7uqe+gePwLWzJ+fsQehq18pc0I2hJKwypZ2aLM90+Er9u1xn4iLJPZ+xlL4g==} resolution: {integrity: sha512-uSvJdwQU5nK+Vdf6zxcWAY2A8r7uqe+gePwLWzJ+fsQehq18pc0I2hJKwypZ2aLM90+Er9u1xn4iLJPZ+xlL4g==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: false
/@lukeed/ms@2.0.1: /@lukeed/ms@2.0.1:
resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==} resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==}
@ -5132,9 +5140,8 @@ packages:
rxjs: 7.8.1 rxjs: 7.8.1
tslib: 2.6.2 tslib: 2.6.2
uid: 2.0.2 uid: 2.0.2
dev: false
/@nestjs/core@10.2.10(@nestjs/common@10.2.10)(reflect-metadata@0.1.14)(rxjs@7.8.1): /@nestjs/core@10.2.10(@nestjs/common@10.2.10)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.14)(rxjs@7.8.1):
resolution: {integrity: sha512-+ckOI6BPi2ZMHikT9MCG4ctHDc4OnjhoIytrn7f2AYMMXI4bnutJhqyQKc30VDka5x3Wq6QAD57pgSP7y+JjJg==} resolution: {integrity: sha512-+ckOI6BPi2ZMHikT9MCG4ctHDc4OnjhoIytrn7f2AYMMXI4bnutJhqyQKc30VDka5x3Wq6QAD57pgSP7y+JjJg==}
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:
@ -5153,6 +5160,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@nestjs/common': 10.2.10(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nestjs/common': 10.2.10(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/platform-express': 10.3.0(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)
'@nuxtjs/opencollective': 0.3.2 '@nuxtjs/opencollective': 0.3.2
fast-safe-stringify: 2.1.1 fast-safe-stringify: 2.1.1
iterare: 1.2.1 iterare: 1.2.1
@ -5163,9 +5171,24 @@ packages:
uid: 2.0.2 uid: 2.0.2
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
dev: false
/@nestjs/testing@10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10): /@nestjs/platform-express@10.3.0(@nestjs/common@10.2.10)(@nestjs/core@10.2.10):
resolution: {integrity: sha512-E4hUW48bYv8OHbP9XQg6deefmXb0pDSSuE38SdhA0mJ37zGY7C5EqqBUdlQk4ttfD+OdnbIgJ1zOokT6dd2d7A==}
peerDependencies:
'@nestjs/common': ^10.0.0
'@nestjs/core': ^10.0.0
dependencies:
'@nestjs/common': 10.2.10(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/core': 10.2.10(@nestjs/common@10.2.10)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.14)(rxjs@7.8.1)
body-parser: 1.20.2
cors: 2.8.5
express: 4.18.2
multer: 1.4.4-lts.1
tslib: 2.6.2
transitivePeerDependencies:
- supports-color
/@nestjs/testing@10.2.10(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)(@nestjs/platform-express@10.3.0):
resolution: {integrity: sha512-IVLUnPz/+fkBtPATYfqTIP+phN9yjkXejmj+JyhmcfPJZpxBmD1i9VSMqa4u54l37j0xkGPscQ0IXpbhqMYUKw==} resolution: {integrity: sha512-IVLUnPz/+fkBtPATYfqTIP+phN9yjkXejmj+JyhmcfPJZpxBmD1i9VSMqa4u54l37j0xkGPscQ0IXpbhqMYUKw==}
peerDependencies: peerDependencies:
'@nestjs/common': ^10.0.0 '@nestjs/common': ^10.0.0
@ -5179,7 +5202,8 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@nestjs/common': 10.2.10(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nestjs/common': 10.2.10(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/core': 10.2.10(@nestjs/common@10.2.10)(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nestjs/core': 10.2.10(@nestjs/common@10.2.10)(@nestjs/platform-express@10.3.0)(reflect-metadata@0.1.14)(rxjs@7.8.1)
'@nestjs/platform-express': 10.3.0(@nestjs/common@10.2.10)(@nestjs/core@10.2.10)
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
@ -5249,7 +5273,6 @@ packages:
node-fetch: 2.7.0 node-fetch: 2.7.0
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
dev: false
/@one-ini/wasm@0.1.1: /@one-ini/wasm@0.1.1:
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
@ -9164,6 +9187,14 @@ packages:
clean-stack: 2.2.0 clean-stack: 2.2.0
indent-string: 4.0.0 indent-string: 4.0.0
/aggregate-error@5.0.0:
resolution: {integrity: sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==}
engines: {node: '>=18'}
dependencies:
clean-stack: 5.2.0
indent-string: 5.0.0
dev: true
/ajv-draft-04@1.0.0(ajv@8.12.0): /ajv-draft-04@1.0.0(ajv@8.12.0):
resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
peerDependencies: peerDependencies:
@ -9268,6 +9299,9 @@ packages:
engines: {node: '>= 6.0.0'} engines: {node: '>= 6.0.0'}
dev: false dev: false
/append-field@1.0.0:
resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==}
/aproba@2.0.0: /aproba@2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
requiresBuild: true requiresBuild: true
@ -9806,7 +9840,6 @@ packages:
unpipe: 1.0.0 unpipe: 1.0.0
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: false
/boolbase@1.0.0: /boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
@ -9952,7 +9985,6 @@ packages:
engines: {node: '>=10.16.0'} engines: {node: '>=10.16.0'}
dependencies: dependencies:
streamsearch: 1.1.0 streamsearch: 1.1.0
dev: false
/bytes@3.0.0: /bytes@3.0.0:
resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==}
@ -10290,6 +10322,13 @@ packages:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'} engines: {node: '>=6'}
/clean-stack@5.2.0:
resolution: {integrity: sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==}
engines: {node: '>=14.16'}
dependencies:
escape-string-regexp: 5.0.0
dev: true
/cli-cursor@3.1.0: /cli-cursor@3.1.0:
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -10534,7 +10573,6 @@ packages:
inherits: 2.0.4 inherits: 2.0.4
readable-stream: 2.3.7 readable-stream: 2.3.7
typedarray: 0.0.6 typedarray: 0.0.6
dev: true
/config-chain@1.1.13: /config-chain@1.1.13:
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
@ -10545,7 +10583,6 @@ packages:
/consola@2.15.3: /consola@2.15.3:
resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==}
dev: false
/console-control-strings@1.1.0: /console-control-strings@1.1.0:
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
@ -10611,6 +10648,13 @@ packages:
/core-util-is@1.0.3: /core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
/cors@2.8.5:
resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
engines: {node: '>= 0.10'}
dependencies:
object-assign: 4.1.1
vary: 1.1.2
/crc-32@1.2.2: /crc-32@1.2.2:
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
engines: {node: '>=0.8'} engines: {node: '>=0.8'}
@ -11636,7 +11680,6 @@ packages:
/escape-string-regexp@5.0.0: /escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'} engines: {node: '>=12'}
dev: false
/escodegen@2.1.0: /escodegen@2.1.0:
resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
@ -12058,6 +12101,21 @@ packages:
signal-exit: 3.0.7 signal-exit: 3.0.7
strip-final-newline: 2.0.0 strip-final-newline: 2.0.0
/execa@6.1.0:
resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
cross-spawn: 7.0.3
get-stream: 6.0.1
human-signals: 3.0.1
is-stream: 3.0.0
merge-stream: 2.0.0
npm-run-path: 5.1.0
onetime: 6.0.0
signal-exit: 3.0.7
strip-final-newline: 3.0.0
dev: true
/execa@8.0.1: /execa@8.0.1:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'} engines: {node: '>=16.17'}
@ -12252,7 +12310,6 @@ packages:
/fast-safe-stringify@2.1.1: /fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
dev: false
/fast-uri@2.2.0: /fast-uri@2.2.0:
resolution: {integrity: sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg==} resolution: {integrity: sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg==}
@ -12470,6 +12527,18 @@ packages:
semver-regex: 4.0.5 semver-regex: 4.0.5
dev: false dev: false
/fkill@9.0.0:
resolution: {integrity: sha512-MdYSsbdCaIRjzo5edthZtWmEZVMfr1qrtYZUHIdO3swCE+CoZA8S5l0s4jDsYlTa9ZiXv0pTgpzE7s4N8NeUOA==}
engines: {node: '>=18'}
dependencies:
aggregate-error: 5.0.0
execa: 8.0.1
pid-port: 1.0.0
process-exists: 5.0.0
ps-list: 8.1.1
taskkill: 5.0.0
dev: true
/flat-cache@3.0.4: /flat-cache@3.0.4:
resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
engines: {node: ^10.12.0 || >=12.0.0} engines: {node: ^10.12.0 || >=12.0.0}
@ -13298,6 +13367,11 @@ packages:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'} engines: {node: '>=10.17.0'}
/human-signals@3.0.1:
resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==}
engines: {node: '>=12.20.0'}
dev: true
/human-signals@5.0.0: /human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'} engines: {node: '>=16.17.0'}
@ -13362,6 +13436,11 @@ packages:
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
engines: {node: '>=8'} engines: {node: '>=8'}
/indent-string@5.0.0:
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
engines: {node: '>=12'}
dev: true
/inflight@1.0.6: /inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies: dependencies:
@ -13893,7 +13972,6 @@ packages:
/iterare@1.2.1: /iterare@1.2.1:
resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==} resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
engines: {node: '>=6'} engines: {node: '>=6'}
dev: false
/jackspeak@2.3.6: /jackspeak@2.3.6:
resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
@ -15437,6 +15515,18 @@ packages:
resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
dev: true dev: true
/multer@1.4.4-lts.1:
resolution: {integrity: sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==}
engines: {node: '>= 6.0.0'}
dependencies:
append-field: 1.0.0
busboy: 1.6.0
concat-stream: 1.6.2
mkdirp: 0.5.6
object-assign: 4.1.1
type-is: 1.6.18
xtend: 4.0.2
/multi-integer-range@3.0.0: /multi-integer-range@3.0.0:
resolution: {integrity: sha512-uQzynjVJ8F7x5wjaK0g4Ybhy2TvO/pk96+YHyS5g1W4GuUEV6HMebZ8HcRwWgKIRCUT2MLbM5uCKwYcAqkS+8Q==} resolution: {integrity: sha512-uQzynjVJ8F7x5wjaK0g4Ybhy2TvO/pk96+YHyS5g1W4GuUEV6HMebZ8HcRwWgKIRCUT2MLbM5uCKwYcAqkS+8Q==}
dev: false dev: false
@ -16230,7 +16320,6 @@ packages:
/path-to-regexp@3.2.0: /path-to-regexp@3.2.0:
resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==} resolution: {integrity: sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==}
dev: false
/path-to-regexp@6.2.1: /path-to-regexp@6.2.1:
resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
@ -16366,6 +16455,13 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
/pid-port@1.0.0:
resolution: {integrity: sha512-LSNBeKChRPA4Xlrs6+zV588G1hSrFvANtPV5rt/5MPfSPK3V9XPWxx1d29svsrOjngT9ifLisXWCLS7DvO9ZhQ==}
engines: {node: '>=18'}
dependencies:
execa: 8.0.1
dev: true
/pify@2.3.0: /pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -16922,6 +17018,13 @@ packages:
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
dev: false dev: false
/process-exists@5.0.0:
resolution: {integrity: sha512-6QPRh5fyHD8MaXr4GYML8K/YY0Sq5dKHGIOrAKS3cYpHQdmygFCcijIu1dVoNKAZ0TWAMoeh8KDK9dF8auBkJA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
ps-list: 8.1.1
dev: true
/process-nextick-args@2.0.1: /process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
@ -16993,6 +17096,11 @@ packages:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
dev: true dev: true
/ps-list@8.1.1:
resolution: {integrity: sha512-OPS9kEJYVmiO48u/B9qneqhkMvgCxT+Tm28VCEJpheTpl8cJ0ffZRRNgS5mrQRTrX5yRTpaJ+hRDeefXYmmorQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: true
/ps-tree@1.2.0: /ps-tree@1.2.0:
resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==}
engines: {node: '>= 0.10'} engines: {node: '>= 0.10'}
@ -17258,7 +17366,6 @@ packages:
http-errors: 2.0.0 http-errors: 2.0.0
iconv-lite: 0.4.24 iconv-lite: 0.4.24
unpipe: 1.0.0 unpipe: 1.0.0
dev: false
/rc@1.2.8: /rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
@ -17563,7 +17670,6 @@ packages:
/reflect-metadata@0.1.14: /reflect-metadata@0.1.14:
resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==} resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==}
dev: false
/regenerate-unicode-properties@10.1.0: /regenerate-unicode-properties@10.1.0:
resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==}
@ -18546,7 +18652,6 @@ packages:
/streamsearch@1.1.0: /streamsearch@1.1.0:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
dev: false
/streamx@2.15.0: /streamx@2.15.0:
resolution: {integrity: sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg==} resolution: {integrity: sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg==}
@ -18855,6 +18960,13 @@ packages:
mkdirp: 1.0.4 mkdirp: 1.0.4
yallist: 4.0.0 yallist: 4.0.0
/taskkill@5.0.0:
resolution: {integrity: sha512-+HRtZ40Vc+6YfCDWCeAsixwxJgMbPY4HHuTgzPYH3JXvqHWUlsCfy+ylXlAKhFNcuLp4xVeWeFBUhDk+7KYUvQ==}
engines: {node: '>=14.16'}
dependencies:
execa: 6.1.0
dev: true
/telejson@7.2.0: /telejson@7.2.0:
resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==}
dependencies: dependencies:
@ -19288,7 +19400,6 @@ packages:
/typedarray@0.0.6: /typedarray@0.0.6:
resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
dev: true
/typeorm@0.3.17(ioredis@5.3.2)(pg@8.11.3): /typeorm@0.3.17(ioredis@5.3.2)(pg@8.11.3):
resolution: {integrity: sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==} resolution: {integrity: sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==}
@ -19401,7 +19512,6 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
'@lukeed/csprng': 1.0.1 '@lukeed/csprng': 1.0.1
dev: false
/ulid@2.3.0: /ulid@2.3.0:
resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==}