diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..7d8a497 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +dist/ +build/ +coverage/ +node_modules/ diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 73133d4..ca1ee35 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,3 +1,4 @@ +<<<<<<< HEAD 'use strict'; module.exports = { @@ -26,26 +27,70 @@ module.exports = { 'error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, ], - - // Allow explicit `any` with a warning instead of hard error (relax for now) - '@typescript-eslint/no-explicit-any': 'warn', - - // Enforce consistent type imports - '@typescript-eslint/consistent-type-imports': [ + 'airbnb-typescript/base', + ], + rules: { + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + '@typescript-eslint/quotes': ['error', 'double'], + 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], + 'import/extensions': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/naming-convention': [ + 'error', + { + selector: 'variableLike', + format: ['camelCase', 'PascalCase', 'UPPER_CASE'], + leadingUnderscore: 'allow', + }, + ], + 'node/no-missing-import': 'off', + 'indent': 'off', + '@typescript-eslint/indent': 'off', + }, + overrides: [ + { + files: ['**/*.test.ts'], + rules: { + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + }, + }, + ], + ignorePatterns: ['dist/', 'node_modules/', 'coverage/', 'build/'], + es2021: true, + jest: true, + }, + plugins: ['@typescript-eslint', 'import', 'node', 'promise'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'airbnb-typescript/base', + ], + rules: { + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + '@typescript-eslint/quotes': ['error', 'double'], + 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], + 'import/extensions': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/naming-convention': [ 'error', - { prefer: 'type-imports', fixStyle: 'inline-type-imports' }, + { + selector: 'variableLike', + format: ['camelCase', 'PascalCase', 'UPPER_CASE'], + leadingUnderscore: 'allow', + }, ], - - // No floating promises — important for async route handlers - '@typescript-eslint/no-floating-promises': 'error', - - // Disallow require() in ESM codebase - '@typescript-eslint/no-require-imports': 'error', + 'node/no-missing-import': 'off', + 'indent': 'off', + '@typescript-eslint/indent': 'off', }, - ignorePatterns: [ - 'dist/', - 'node_modules/', - 'coverage/', - '*.cjs', // ignore this file itself + overrides: [ + { + files: ['**/*.test.ts'], + rules: { + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + }, + }, ], + ignorePatterns: ['dist/', 'node_modules/', 'coverage/', 'build/'], +>>>>>>> 4e2f84e (chore: configure ESLint for backend TypeScript) }; diff --git a/README.md b/README.md index 84fb2d5..cf4aa05 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,16 @@ npm run test:watch - `GET /api/credit/lines/:id` — Get credit line by id (placeholder) - `POST /api/risk/evaluate` — Request risk evaluation; body: `{ "walletAddress": "..." }` +## Linting and formatting + +Consistent coding practices are enforced via ESLint configured for TypeScript. Run the linter with: + +```bash +npm run lint # analyze source files under src/ +``` + +The configuration lives in `.eslintrc.cjs` and common ignores are listed in `.eslintignore`. + ## Project layout ``` diff --git a/coverage/.tmp/coverage-0.json b/coverage/.tmp/coverage-0.json new file mode 100644 index 0000000..26f5f91 --- /dev/null +++ b/coverage/.tmp/coverage-0.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/__test__/creditService.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":29158,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":29158,"count":1},{"startOffset":566,"endOffset":29157,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":602,"endOffset":650,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":684,"endOffset":2309,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2340,"endOffset":2909,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2942,"endOffset":3555,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3590,"endOffset":7033,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":7066,"endOffset":10040,"count":0}],"isBlockCoverage":false}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-1.json b/coverage/.tmp/coverage-1.json new file mode 100644 index 0000000..79addda --- /dev/null +++ b/coverage/.tmp/coverage-1.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/__test__/horizonListener.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":42421,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":42421,"count":1}],"isBlockCoverage":true},{"functionName":"silenceConsole","ranges":[{"startOffset":397,"endOffset":615,"count":33}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":473,"endOffset":484,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":536,"endOffset":547,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":600,"endOffset":611,"count":0}],"isBlockCoverage":false},{"functionName":"restoreConsole","ranges":[{"startOffset":616,"endOffset":741,"count":33},{"startOffset":669,"endOffset":673,"count":0},{"startOffset":701,"endOffset":705,"count":0},{"startOffset":734,"endOffset":738,"count":0}],"isBlockCoverage":true},{"functionName":"withEnv","ranges":[{"startOffset":742,"endOffset":1120,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1132,"endOffset":1278,"count":33},{"startOffset":1201,"endOffset":1277,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1291,"endOffset":1461,"count":33},{"startOffset":1340,"endOffset":1369,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1492,"endOffset":3620,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1559,"endOffset":1998,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2036,"endOffset":2253,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2292,"endOffset":2452,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2512,"endOffset":2754,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2808,"endOffset":3021,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3091,"endOffset":3229,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3273,"endOffset":3420,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3467,"endOffset":3616,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3661,"endOffset":4472,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":3720,"endOffset":3848,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3904,"endOffset":4181,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":4233,"endOffset":4468,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":4495,"endOffset":6355,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":4532,"endOffset":4674,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":4727,"endOffset":5059,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":5114,"endOffset":5684,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":5745,"endOffset":6085,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":6128,"endOffset":6351,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":6377,"endOffset":8004,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":6415,"endOffset":6592,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":6654,"endOffset":7142,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":7199,"endOffset":7372,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":7406,"endOffset":7666,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":7724,"endOffset":8000,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":8052,"endOffset":10351,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":8119,"endOffset":8461,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":8523,"endOffset":8923,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":8987,"endOffset":9312,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":9393,"endOffset":9887,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":9944,"endOffset":10347,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":10377,"endOffset":12791,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":10601,"endOffset":10705,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":10753,"endOffset":10969,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":11034,"endOffset":11463,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":11521,"endOffset":11709,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":11772,"endOffset":11965,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":12033,"endOffset":12364,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":12425,"endOffset":12787,"count":0}],"isBlockCoverage":false}]},{"scriptId":"376","url":"file:///home/samaro/cred/Creditra-Backend/src/services/horizonListener.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":13746,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":13746,"count":1}],"isBlockCoverage":true},{"functionName":"resolveConfig","ranges":[{"startOffset":284,"endOffset":792,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":894,"endOffset":923,"count":0}],"isBlockCoverage":false},{"functionName":"onEvent","ranges":[{"startOffset":927,"endOffset":987,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":1083,"endOffset":1106,"count":0}],"isBlockCoverage":false},{"functionName":"clearEventHandlers","ranges":[{"startOffset":1110,"endOffset":1171,"count":33}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":1278,"endOffset":1312,"count":33}],"isBlockCoverage":true},{"functionName":"dispatchEvent","ranges":[{"startOffset":1316,"endOffset":1565,"count":0}],"isBlockCoverage":false},{"functionName":"pollOnce","ranges":[{"startOffset":1566,"endOffset":2297,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":2394,"endOffset":2418,"count":0}],"isBlockCoverage":false},{"functionName":"isRunning","ranges":[{"startOffset":2422,"endOffset":2464,"count":33}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":2562,"endOffset":2587,"count":33}],"isBlockCoverage":true},{"functionName":"getConfig","ranges":[{"startOffset":2591,"endOffset":2638,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":2736,"endOffset":2761,"count":0}],"isBlockCoverage":false},{"functionName":"start","ranges":[{"startOffset":2765,"endOffset":3413,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":3507,"endOffset":3528,"count":0}],"isBlockCoverage":false},{"functionName":"stop","ranges":[{"startOffset":3532,"endOffset":3846,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":3939,"endOffset":3959,"count":0}],"isBlockCoverage":false}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-2.json b/coverage/.tmp/coverage-2.json new file mode 100644 index 0000000..9ae9a81 --- /dev/null +++ b/coverage/.tmp/coverage-2.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/__test__/creditRoute.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":28745,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":28745,"count":1},{"startOffset":384,"endOffset":28744,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1055,"endOffset":1178,"count":0}],"isBlockCoverage":false},{"functionName":"buildApp","ranges":[{"startOffset":1239,"endOffset":1429,"count":0}],"isBlockCoverage":false},{"functionName":"allowAdmin","ranges":[{"startOffset":1529,"endOffset":1620,"count":0}],"isBlockCoverage":false},{"functionName":"denyAdmin","ranges":[{"startOffset":1621,"endOffset":1806,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1840,"endOffset":1904,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1939,"endOffset":1977,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2014,"endOffset":2764,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2805,"endOffset":3606,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3672,"endOffset":4357,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":4424,"endOffset":6302,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":6366,"endOffset":7045,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":7110,"endOffset":9579,"count":0}],"isBlockCoverage":false}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-3.json b/coverage/.tmp/coverage-3.json new file mode 100644 index 0000000..5b472b9 --- /dev/null +++ b/coverage/.tmp/coverage-3.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/__test__/riskService.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":19908,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":19908,"count":1},{"startOffset":354,"endOffset":19907,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":555,"endOffset":2194,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":2228,"endOffset":3202,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":3234,"endOffset":6310,"count":0}],"isBlockCoverage":false}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-4.json b/coverage/.tmp/coverage-4.json new file mode 100644 index 0000000..7c34283 --- /dev/null +++ b/coverage/.tmp/coverage-4.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/__test__/riskRoute.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":15957,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":15957,"count":1},{"startOffset":384,"endOffset":15956,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":795,"endOffset":856,"count":0}],"isBlockCoverage":false},{"functionName":"buildApp","ranges":[{"startOffset":926,"endOffset":1114,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1436,"endOffset":5283,"count":0}],"isBlockCoverage":false}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-5.json b/coverage/.tmp/coverage-5.json new file mode 100644 index 0000000..c1bf4be --- /dev/null +++ b/coverage/.tmp/coverage-5.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/db/migrations.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":16086,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":16086,"count":1}],"isBlockCoverage":true},{"functionName":"createMockClient","ranges":[{"startOffset":555,"endOffset":773,"count":6}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":828,"endOffset":1232,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":888,"endOffset":1029,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1091,"endOffset":1228,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1292,"endOffset":1684,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1384,"endOffset":1680,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1740,"endOffset":2674,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1830,"endOffset":2278,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":2358,"endOffset":2670,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":2730,"endOffset":3320,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":2809,"endOffset":3316,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":3205,"endOffset":3230,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":3372,"endOffset":4129,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":3453,"endOffset":4125,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":3586,"endOffset":3628,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":3892,"endOffset":3973,"count":2}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":4187,"endOffset":5368,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":4258,"endOffset":4740,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":4547,"endOffset":4589,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":4823,"endOffset":5364,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":5079,"endOffset":5121,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":5421,"endOffset":5700,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":5491,"endOffset":5696,"count":1}],"isBlockCoverage":true}]},{"scriptId":"377","url":"file:///home/samaro/cred/Creditra-Backend/src/db/migrations.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":9334,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":9334,"count":1}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":773,"endOffset":804,"count":1}],"isBlockCoverage":true},{"functionName":"ensureSchemaMigrations","ranges":[{"startOffset":808,"endOffset":904,"count":5}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":1015,"endOffset":1053,"count":1}],"isBlockCoverage":true},{"functionName":"listMigrationFiles","ranges":[{"startOffset":1057,"endOffset":1304,"count":3}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1214,"endOffset":1258,"count":6}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1264,"endOffset":1277,"count":3}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":1411,"endOffset":1445,"count":1}],"isBlockCoverage":true},{"functionName":"versionFromFilename","ranges":[{"startOffset":1449,"endOffset":1574,"count":6},{"startOffset":1524,"endOffset":1540,"count":1},{"startOffset":1540,"endOffset":1573,"count":5}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":1682,"endOffset":1717,"count":2}],"isBlockCoverage":true},{"functionName":"getAppliedVersions","ranges":[{"startOffset":1721,"endOffset":1974,"count":4}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1954,"endOffset":1970,"count":2}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":2081,"endOffset":2115,"count":2}],"isBlockCoverage":true},{"functionName":"applyMigration","ranges":[{"startOffset":2119,"endOffset":2548,"count":2}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":2651,"endOffset":2681,"count":1}],"isBlockCoverage":true},{"functionName":"runPendingMigrations","ranges":[{"startOffset":2685,"endOffset":3158,"count":2},{"startOffset":3022,"endOffset":3142,"count":1}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":3267,"endOffset":3303,"count":2}],"isBlockCoverage":true}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-6.json b/coverage/.tmp/coverage-6.json new file mode 100644 index 0000000..97352e8 --- /dev/null +++ b/coverage/.tmp/coverage-6.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/__test__/adminAuth.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":12905,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":12905,"count":1},{"startOffset":384,"endOffset":12904,"count":0}],"isBlockCoverage":true},{"functionName":"buildApp","ranges":[{"startOffset":687,"endOffset":929,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":980,"endOffset":1070,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1105,"endOffset":1244,"count":0}],"isBlockCoverage":false},{"functionName":"","ranges":[{"startOffset":1280,"endOffset":4295,"count":0}],"isBlockCoverage":false}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-7.json b/coverage/.tmp/coverage-7.json new file mode 100644 index 0000000..5d60161 --- /dev/null +++ b/coverage/.tmp/coverage-7.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/db/validate-schema.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":10521,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":10521,"count":1}],"isBlockCoverage":true},{"functionName":"createMockClient","ranges":[{"startOffset":446,"endOffset":664,"count":6}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":713,"endOffset":2573,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":787,"endOffset":1263,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1324,"endOffset":1731,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1792,"endOffset":2103,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":2184,"endOffset":2569,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":2625,"endOffset":3655,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":2709,"endOffset":3170,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":3236,"endOffset":3651,"count":1}],"isBlockCoverage":true}]},{"scriptId":"377","url":"file:///home/samaro/cred/Creditra-Backend/src/db/validate-schema.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":3804,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":3804,"count":1}],"isBlockCoverage":true},{"functionName":"missingTables","ranges":[{"startOffset":307,"endOffset":795,"count":7}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":428,"endOffset":449,"count":30}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":685,"endOffset":704,"count":15}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":768,"endOffset":791,"count":30}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":897,"endOffset":926,"count":4}],"isBlockCoverage":true},{"functionName":"validateSchema","ranges":[{"startOffset":930,"endOffset":1112,"count":3},{"startOffset":1043,"endOffset":1110,"count":2}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":1215,"endOffset":1245,"count":3}],"isBlockCoverage":true}]},{"scriptId":"378","url":"file:///home/samaro/cred/Creditra-Backend/src/db/migrations.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":9334,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":9334,"count":1}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":773,"endOffset":804,"count":5}],"isBlockCoverage":true},{"functionName":"ensureSchemaMigrations","ranges":[{"startOffset":808,"endOffset":904,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":1015,"endOffset":1053,"count":0}],"isBlockCoverage":false},{"functionName":"listMigrationFiles","ranges":[{"startOffset":1057,"endOffset":1304,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":1411,"endOffset":1445,"count":0}],"isBlockCoverage":false},{"functionName":"versionFromFilename","ranges":[{"startOffset":1449,"endOffset":1574,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":1682,"endOffset":1717,"count":0}],"isBlockCoverage":false},{"functionName":"getAppliedVersions","ranges":[{"startOffset":1721,"endOffset":1974,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":2081,"endOffset":2115,"count":0}],"isBlockCoverage":false},{"functionName":"applyMigration","ranges":[{"startOffset":2119,"endOffset":2548,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":2651,"endOffset":2681,"count":0}],"isBlockCoverage":false},{"functionName":"runPendingMigrations","ranges":[{"startOffset":2685,"endOffset":3158,"count":0}],"isBlockCoverage":false},{"functionName":"get","ranges":[{"startOffset":3267,"endOffset":3303,"count":0}],"isBlockCoverage":false}]}]} \ No newline at end of file diff --git a/coverage/.tmp/coverage-8.json b/coverage/.tmp/coverage-8.json new file mode 100644 index 0000000..7832301 --- /dev/null +++ b/coverage/.tmp/coverage-8.json @@ -0,0 +1 @@ +{"result":[{"scriptId":"375","url":"file:///home/samaro/cred/Creditra-Backend/src/db/client.test.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":2934,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":2934,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":488,"endOffset":1160,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":572,"endOffset":620,"count":2}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":657,"endOffset":726,"count":2},{"startOffset":690,"endOffset":722,"count":0}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":795,"endOffset":921,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":836,"endOffset":879,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":995,"endOffset":1156,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":1071,"endOffset":1114,"count":1}],"isBlockCoverage":true}]},{"scriptId":"377","url":"file:///home/samaro/cred/Creditra-Backend/src/db/client.ts","functions":[{"functionName":"","ranges":[{"startOffset":0,"endOffset":2289,"count":1}],"isBlockCoverage":true},{"functionName":"","ranges":[{"startOffset":13,"endOffset":2289,"count":1}],"isBlockCoverage":true},{"functionName":"getConnection","ranges":[{"startOffset":373,"endOffset":587,"count":2},{"startOffset":506,"endOffset":586,"count":0}],"isBlockCoverage":true},{"functionName":"get","ranges":[{"startOffset":689,"endOffset":718,"count":2}],"isBlockCoverage":true}]}]} \ No newline at end of file diff --git a/coverage/lcov-report/base.css b/coverage/lcov-report/base.css deleted file mode 100644 index f418035..0000000 --- a/coverage/lcov-report/base.css +++ /dev/null @@ -1,224 +0,0 @@ -body, html { - margin:0; padding: 0; - height: 100%; -} -body { - font-family: Helvetica Neue, Helvetica, Arial; - font-size: 14px; - color:#333; -} -.small { font-size: 12px; } -*, *:after, *:before { - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - box-sizing:border-box; - } -h1 { font-size: 20px; margin: 0;} -h2 { font-size: 14px; } -pre { - font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; - margin: 0; - padding: 0; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; -} -a { color:#0074D9; text-decoration:none; } -a:hover { text-decoration:underline; } -.strong { font-weight: bold; } -.space-top1 { padding: 10px 0 0 0; } -.pad2y { padding: 20px 0; } -.pad1y { padding: 10px 0; } -.pad2x { padding: 0 20px; } -.pad2 { padding: 20px; } -.pad1 { padding: 10px; } -.space-left2 { padding-left:55px; } -.space-right2 { padding-right:20px; } -.center { text-align:center; } -.clearfix { display:block; } -.clearfix:after { - content:''; - display:block; - height:0; - clear:both; - visibility:hidden; - } -.fl { float: left; } -@media only screen and (max-width:640px) { - .col3 { width:100%; max-width:100%; } - .hide-mobile { display:none!important; } -} - -.quiet { - color: #7f7f7f; - color: rgba(0,0,0,0.5); -} -.quiet a { opacity: 0.7; } - -.fraction { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 10px; - color: #555; - background: #E8E8E8; - padding: 4px 5px; - border-radius: 3px; - vertical-align: middle; -} - -div.path a:link, div.path a:visited { color: #333; } -table.coverage { - border-collapse: collapse; - margin: 10px 0 0 0; - padding: 0; -} - -table.coverage td { - margin: 0; - padding: 0; - vertical-align: top; -} -table.coverage td.line-count { - text-align: right; - padding: 0 5px 0 20px; -} -table.coverage td.line-coverage { - text-align: right; - padding-right: 10px; - min-width:20px; -} - -table.coverage td span.cline-any { - display: inline-block; - padding: 0 5px; - width: 100%; -} -.missing-if-branch { - display: inline-block; - margin-right: 5px; - border-radius: 3px; - position: relative; - padding: 0 4px; - background: #333; - color: yellow; -} - -.skip-if-branch { - display: none; - margin-right: 10px; - position: relative; - padding: 0 4px; - background: #ccc; - color: white; -} -.missing-if-branch .typ, .skip-if-branch .typ { - color: inherit !important; -} -.coverage-summary { - border-collapse: collapse; - width: 100%; -} -.coverage-summary tr { border-bottom: 1px solid #bbb; } -.keyline-all { border: 1px solid #ddd; } -.coverage-summary td, .coverage-summary th { padding: 10px; } -.coverage-summary tbody { border: 1px solid #bbb; } -.coverage-summary td { border-right: 1px solid #bbb; } -.coverage-summary td:last-child { border-right: none; } -.coverage-summary th { - text-align: left; - font-weight: normal; - white-space: nowrap; -} -.coverage-summary th.file { border-right: none !important; } -.coverage-summary th.pct { } -.coverage-summary th.pic, -.coverage-summary th.abs, -.coverage-summary td.pct, -.coverage-summary td.abs { text-align: right; } -.coverage-summary td.file { white-space: nowrap; } -.coverage-summary td.pic { min-width: 120px !important; } -.coverage-summary tfoot td { } - -.coverage-summary .sorter { - height: 10px; - width: 7px; - display: inline-block; - margin-left: 0.5em; - background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; -} -.coverage-summary .sorted .sorter { - background-position: 0 -20px; -} -.coverage-summary .sorted-desc .sorter { - background-position: 0 -10px; -} -.status-line { height: 10px; } -/* yellow */ -.cbranch-no { background: yellow !important; color: #111; } -/* dark red */ -.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } -.low .chart { border:1px solid #C21F39 } -.highlighted, -.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ - background: #C21F39 !important; -} -/* medium red */ -.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } -/* light red */ -.low, .cline-no { background:#FCE1E5 } -/* light green */ -.high, .cline-yes { background:rgb(230,245,208) } -/* medium green */ -.cstat-yes { background:rgb(161,215,106) } -/* dark green */ -.status-line.high, .high .cover-fill { background:rgb(77,146,33) } -.high .chart { border:1px solid rgb(77,146,33) } -/* dark yellow (gold) */ -.status-line.medium, .medium .cover-fill { background: #f9cd0b; } -.medium .chart { border:1px solid #f9cd0b; } -/* light yellow */ -.medium { background: #fff4c2; } - -.cstat-skip { background: #ddd; color: #111; } -.fstat-skip { background: #ddd; color: #111 !important; } -.cbranch-skip { background: #ddd !important; color: #111; } - -span.cline-neutral { background: #eaeaea; } - -.coverage-summary td.empty { - opacity: .5; - padding-top: 4px; - padding-bottom: 4px; - line-height: 1; - color: #888; -} - -.cover-fill, .cover-empty { - display:inline-block; - height: 12px; -} -.chart { - line-height: 0; -} -.cover-empty { - background: white; -} -.cover-full { - border-right: none !important; -} -pre.prettyprint { - border: none !important; - padding: 0 !important; - margin: 0 !important; -} -.com { color: #999 !important; } -.ignore-none { color: #999; font-weight: normal; } - -.wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -48px; -} -.footer, .push { - height: 48px; -} diff --git a/coverage/lcov-report/block-navigation.js b/coverage/lcov-report/block-navigation.js deleted file mode 100644 index 530d1ed..0000000 --- a/coverage/lcov-report/block-navigation.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable */ -var jumpToCode = (function init() { - // Classes of code we would like to highlight in the file view - var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; - - // Elements to highlight in the file listing view - var fileListingElements = ['td.pct.low']; - - // We don't want to select elements that are direct descendants of another match - var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` - - // Selector that finds elements on the page to which we can jump - var selector = - fileListingElements.join(', ') + - ', ' + - notSelector + - missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` - - // The NodeList of matching elements - var missingCoverageElements = document.querySelectorAll(selector); - - var currentIndex; - - function toggleClass(index) { - missingCoverageElements - .item(currentIndex) - .classList.remove('highlighted'); - missingCoverageElements.item(index).classList.add('highlighted'); - } - - function makeCurrent(index) { - toggleClass(index); - currentIndex = index; - missingCoverageElements.item(index).scrollIntoView({ - behavior: 'smooth', - block: 'center', - inline: 'center' - }); - } - - function goToPrevious() { - var nextIndex = 0; - if (typeof currentIndex !== 'number' || currentIndex === 0) { - nextIndex = missingCoverageElements.length - 1; - } else if (missingCoverageElements.length > 1) { - nextIndex = currentIndex - 1; - } - - makeCurrent(nextIndex); - } - - function goToNext() { - var nextIndex = 0; - - if ( - typeof currentIndex === 'number' && - currentIndex < missingCoverageElements.length - 1 - ) { - nextIndex = currentIndex + 1; - } - - makeCurrent(nextIndex); - } - - return function jump(event) { - if ( - document.getElementById('fileSearch') === document.activeElement && - document.activeElement != null - ) { - // if we're currently focused on the search input, we don't want to navigate - return; - } - - switch (event.which) { - case 78: // n - case 74: // j - goToNext(); - break; - case 66: // b - case 75: // k - case 80: // p - goToPrevious(); - break; - } - }; -})(); -window.addEventListener('keydown', jumpToCode); diff --git a/coverage/lcov-report/favicon.png b/coverage/lcov-report/favicon.png deleted file mode 100644 index c1525b8..0000000 Binary files a/coverage/lcov-report/favicon.png and /dev/null differ diff --git a/coverage/lcov-report/index.html b/coverage/lcov-report/index.html deleted file mode 100644 index 1915251..0000000 --- a/coverage/lcov-report/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for All files - - - - - - - - - -
-
-

All files

-
- -
- 100% - Statements - 132/132 -
- - -
- 100% - Branches - 18/18 -
- - -
- 100% - Functions - 8/8 -
- - -
- 100% - Lines - 132/132 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
migrations.ts -
-
100%98/98100%12/12100%6/6100%98/98
validate-schema.ts -
-
100%34/34100%6/6100%2/2100%34/34
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/migrations.ts.html b/coverage/lcov-report/migrations.ts.html deleted file mode 100644 index faeb659..0000000 --- a/coverage/lcov-report/migrations.ts.html +++ /dev/null @@ -1,379 +0,0 @@ - - - - - - Code coverage report for migrations.ts - - - - - - - - - -
-
-

All files migrations.ts

-
- -
- 100% - Statements - 98/98 -
- - -
- 100% - Branches - 12/12 -
- - -
- 100% - Functions - 6/6 -
- - -
- 100% - Lines - 98/98 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -991x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -1x -5x -5x -5x -1x -1x -1x -1x -3x -3x -3x -3x -3x -3x -3x -3x -1x -1x -1x -1x -1x -6x -5x -5x -1x -1x -1x -1x -4x -4x -4x -4x -4x -4x -4x -4x -1x -1x -1x -1x -2x -2x -2x -2x -2x -2x -2x -2x -2x -2x -2x -2x -2x -2x -1x -1x -1x -1x -1x -2x -2x -2x -2x -2x -2x -2x -2x -2x -2x -2x -1x -1x -1x -1x -2x -2x - 
import { readdir, readFile } from 'fs/promises';
-import { join } from 'path';
-import type { DbClient } from './client.js';
- 
-const SCHEMA_MIGRATIONS_TABLE = `
-CREATE TABLE IF NOT EXISTS schema_migrations (
-  version TEXT PRIMARY KEY,
-  applied_at TIMESTAMPTZ NOT NULL DEFAULT now()
-);
-`;
- 
-/** Expected core tables that must exist after initial schema. */
-export const EXPECTED_TABLES = [
-  'borrowers',
-  'credit_lines',
-  'risk_evaluations',
-  'transactions',
-  'events',
-] as const;
- 
-/**
- * Ensure schema_migrations table exists (for first-run or standalone migration).
- */
-export async function ensureSchemaMigrations(client: DbClient): Promise<void> {
-  await client.query(SCHEMA_MIGRATIONS_TABLE);
-}
- 
-/**
- * Return sorted list of migration filenames (e.g. 001_initial_schema.sql) in the given directory.
- */
-export async function listMigrationFiles(dir: string): Promise<string[]> {
-  const entries = await readdir(dir, { withFileTypes: true });
-  const files = entries
-    .filter((e) => e.isFile() && e.name.endsWith('.sql'))
-    .map((e) => e.name)
-    .sort();
-  return files;
-}
- 
-/**
- * Extract version string from migration filename (e.g. 001_initial_schema.sql -> 001_initial_schema).
- */
-export function versionFromFilename(filename: string): string {
-  if (!filename.endsWith('.sql')) return filename;
-  return filename.slice(0, -4);
-}
- 
-/**
- * Get applied migration versions from schema_migrations.
- */
-export async function getAppliedVersions(client: DbClient): Promise<string[]> {
-  await ensureSchemaMigrations(client);
-  const result = await client.query(
-    'SELECT version FROM schema_migrations ORDER BY version'
-  );
-  const rows = result.rows as { version: string }[];
-  return rows.map((r) => r.version);
-}
- 
-/**
- * Apply a single migration file (run its SQL and record version).
- */
-export async function applyMigration(
-  client: DbClient,
-  migrationsDir: string,
-  filename: string
-): Promise<void> {
-  const path = join(migrationsDir, filename);
-  const sql = await readFile(path, 'utf-8');
-  await client.query(sql);
-  const version = versionFromFilename(filename);
-  await client.query(
-    'INSERT INTO schema_migrations (version, applied_at) VALUES ($1, now()) ON CONFLICT (version) DO NOTHING',
-    [version]
-  );
-}
- 
-/**
- * Run all pending migrations in the given directory.
- * Uses process.cwd() if migrationsDir is not absolute to resolve relative to cwd.
- */
-export async function runPendingMigrations(
-  client: DbClient,
-  migrationsDir: string
-): Promise<string[]> {
-  const applied = await getAppliedVersions(client);
-  const files = await listMigrationFiles(migrationsDir);
-  const appliedSet = new Set(applied);
-  const run: string[] = [];
-  for (const file of files) {
-    const version = versionFromFilename(file);
-    if (appliedSet.has(version)) continue;
-    await applyMigration(client, migrationsDir, file);
-    run.push(version);
-    appliedSet.add(version);
-  }
-  return run;
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov-report/prettify.css b/coverage/lcov-report/prettify.css deleted file mode 100644 index b317a7c..0000000 --- a/coverage/lcov-report/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/coverage/lcov-report/prettify.js b/coverage/lcov-report/prettify.js deleted file mode 100644 index b322523..0000000 --- a/coverage/lcov-report/prettify.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable */ -window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/coverage/lcov-report/sort-arrow-sprite.png b/coverage/lcov-report/sort-arrow-sprite.png deleted file mode 100644 index 6ed6831..0000000 Binary files a/coverage/lcov-report/sort-arrow-sprite.png and /dev/null differ diff --git a/coverage/lcov-report/sorter.js b/coverage/lcov-report/sorter.js deleted file mode 100644 index 4ed70ae..0000000 --- a/coverage/lcov-report/sorter.js +++ /dev/null @@ -1,210 +0,0 @@ -/* eslint-disable */ -var addSorting = (function() { - 'use strict'; - var cols, - currentSort = { - index: 0, - desc: false - }; - - // returns the summary table element - function getTable() { - return document.querySelector('.coverage-summary'); - } - // returns the thead element of the summary table - function getTableHeader() { - return getTable().querySelector('thead tr'); - } - // returns the tbody element of the summary table - function getTableBody() { - return getTable().querySelector('tbody'); - } - // returns the th element for nth column - function getNthColumn(n) { - return getTableHeader().querySelectorAll('th')[n]; - } - - function onFilterInput() { - const searchValue = document.getElementById('fileSearch').value; - const rows = document.getElementsByTagName('tbody')[0].children; - - // Try to create a RegExp from the searchValue. If it fails (invalid regex), - // it will be treated as a plain text search - let searchRegex; - try { - searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive - } catch (error) { - searchRegex = null; - } - - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - let isMatch = false; - - if (searchRegex) { - // If a valid regex was created, use it for matching - isMatch = searchRegex.test(row.textContent); - } else { - // Otherwise, fall back to the original plain text search - isMatch = row.textContent - .toLowerCase() - .includes(searchValue.toLowerCase()); - } - - row.style.display = isMatch ? '' : 'none'; - } - } - - // loads the search box - function addSearchBox() { - var template = document.getElementById('filterTemplate'); - var templateClone = template.content.cloneNode(true); - templateClone.getElementById('fileSearch').oninput = onFilterInput; - template.parentElement.appendChild(templateClone); - } - - // loads all columns - function loadColumns() { - var colNodes = getTableHeader().querySelectorAll('th'), - colNode, - cols = [], - col, - i; - - for (i = 0; i < colNodes.length; i += 1) { - colNode = colNodes[i]; - col = { - key: colNode.getAttribute('data-col'), - sortable: !colNode.getAttribute('data-nosort'), - type: colNode.getAttribute('data-type') || 'string' - }; - cols.push(col); - if (col.sortable) { - col.defaultDescSort = col.type === 'number'; - colNode.innerHTML = - colNode.innerHTML + ''; - } - } - return cols; - } - // attaches a data attribute to every tr element with an object - // of data values keyed by column name - function loadRowData(tableRow) { - var tableCols = tableRow.querySelectorAll('td'), - colNode, - col, - data = {}, - i, - val; - for (i = 0; i < tableCols.length; i += 1) { - colNode = tableCols[i]; - col = cols[i]; - val = colNode.getAttribute('data-value'); - if (col.type === 'number') { - val = Number(val); - } - data[col.key] = val; - } - return data; - } - // loads all row data - function loadData() { - var rows = getTableBody().querySelectorAll('tr'), - i; - - for (i = 0; i < rows.length; i += 1) { - rows[i].data = loadRowData(rows[i]); - } - } - // sorts the table using the data for the ith column - function sortByIndex(index, desc) { - var key = cols[index].key, - sorter = function(a, b) { - a = a.data[key]; - b = b.data[key]; - return a < b ? -1 : a > b ? 1 : 0; - }, - finalSorter = sorter, - tableBody = document.querySelector('.coverage-summary tbody'), - rowNodes = tableBody.querySelectorAll('tr'), - rows = [], - i; - - if (desc) { - finalSorter = function(a, b) { - return -1 * sorter(a, b); - }; - } - - for (i = 0; i < rowNodes.length; i += 1) { - rows.push(rowNodes[i]); - tableBody.removeChild(rowNodes[i]); - } - - rows.sort(finalSorter); - - for (i = 0; i < rows.length; i += 1) { - tableBody.appendChild(rows[i]); - } - } - // removes sort indicators for current column being sorted - function removeSortIndicators() { - var col = getNthColumn(currentSort.index), - cls = col.className; - - cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); - col.className = cls; - } - // adds sort indicators for current column being sorted - function addSortIndicators() { - getNthColumn(currentSort.index).className += currentSort.desc - ? ' sorted-desc' - : ' sorted'; - } - // adds event listeners for all sorter widgets - function enableUI() { - var i, - el, - ithSorter = function ithSorter(i) { - var col = cols[i]; - - return function() { - var desc = col.defaultDescSort; - - if (currentSort.index === i) { - desc = !currentSort.desc; - } - sortByIndex(i, desc); - removeSortIndicators(); - currentSort.index = i; - currentSort.desc = desc; - addSortIndicators(); - }; - }; - for (i = 0; i < cols.length; i += 1) { - if (cols[i].sortable) { - // add the click event handler on the th so users - // dont have to click on those tiny arrows - el = getNthColumn(i).querySelector('.sorter').parentElement; - if (el.addEventListener) { - el.addEventListener('click', ithSorter(i)); - } else { - el.attachEvent('onclick', ithSorter(i)); - } - } - } - } - // adds sorting functionality to the UI - return function() { - if (!getTable()) { - return; - } - cols = loadColumns(); - loadData(); - addSearchBox(); - addSortIndicators(); - enableUI(); - }; -})(); - -window.addEventListener('load', addSorting); diff --git a/coverage/lcov-report/validate-schema.ts.html b/coverage/lcov-report/validate-schema.ts.html deleted file mode 100644 index 3ecbee7..0000000 --- a/coverage/lcov-report/validate-schema.ts.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - Code coverage report for validate-schema.ts - - - - - - - - - -
-
-

All files validate-schema.ts

-
- -
- 100% - Statements - 34/34 -
- - -
- 100% - Branches - 6/6 -
- - -
- 100% - Functions - 2/2 -
- - -
- 100% - Lines - 34/34 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -351x -1x -1x -1x -1x -1x -1x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -7x -1x -1x -1x -1x -1x -3x -3x -3x -2x -2x -3x - 
import type { DbClient } from './client.js';
-import { EXPECTED_TABLES } from './migrations.js';
- 
-/**
- * Check that the given tables exist in the current schema (public).
- * Returns list of missing table names; empty if all exist.
- */
-export async function missingTables(
-  client: DbClient,
-  tables: readonly string[] = EXPECTED_TABLES
-): Promise<string[]> {
-  const placeholders = tables.map((_, i) => `$${i + 1}`).join(', ');
-  const result = await client.query(
-    `SELECT table_name FROM information_schema.tables
-     WHERE table_schema = 'public' AND table_name IN (${placeholders})`,
-    [...tables]
-  );
-  const found = (result.rows as { table_name: string }[]).map(
-    (r) => r.table_name
-  );
-  const foundSet = new Set(found);
-  return tables.filter((t) => !foundSet.has(t));
-}
- 
-/**
- * Validate that the core schema is present (all EXPECTED_TABLES exist).
- * Throws if any are missing.
- */
-export async function validateSchema(client: DbClient): Promise<void> {
-  const missing = await missingTables(client);
-  if (missing.length > 0) {
-    throw new Error(`Missing tables: ${missing.join(', ')}`);
-  }
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/coverage/lcov.info b/coverage/lcov.info deleted file mode 100644 index c8ce268..0000000 --- a/coverage/lcov.info +++ /dev/null @@ -1,184 +0,0 @@ -TN: -SF:src/db/migrations.ts -FN:24,ensureSchemaMigrations -FN:31,listMigrationFiles -FN:43,versionFromFilename -FN:51,getAppliedVersions -FN:63,applyMigration -FN:82,runPendingMigrations -FNF:6 -FNH:6 -FNDA:5,ensureSchemaMigrations -FNDA:3,listMigrationFiles -FNDA:6,versionFromFilename -FNDA:4,getAppliedVersions -FNDA:2,applyMigration -FNDA:2,runPendingMigrations -DA:1,1 -DA:2,1 -DA:3,1 -DA:4,1 -DA:5,1 -DA:6,1 -DA:7,1 -DA:8,1 -DA:9,1 -DA:10,1 -DA:11,1 -DA:12,1 -DA:13,1 -DA:14,1 -DA:15,1 -DA:16,1 -DA:17,1 -DA:18,1 -DA:19,1 -DA:20,1 -DA:21,1 -DA:22,1 -DA:23,1 -DA:24,5 -DA:25,5 -DA:26,5 -DA:27,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:31,3 -DA:32,3 -DA:33,3 -DA:34,3 -DA:35,3 -DA:36,3 -DA:37,3 -DA:38,3 -DA:39,1 -DA:40,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:44,6 -DA:45,5 -DA:46,5 -DA:47,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:51,4 -DA:52,4 -DA:53,4 -DA:54,4 -DA:55,4 -DA:56,4 -DA:57,4 -DA:58,4 -DA:59,1 -DA:60,1 -DA:61,1 -DA:62,1 -DA:63,2 -DA:64,2 -DA:65,2 -DA:66,2 -DA:67,2 -DA:68,2 -DA:69,2 -DA:70,2 -DA:71,2 -DA:72,2 -DA:73,2 -DA:74,2 -DA:75,2 -DA:76,2 -DA:77,1 -DA:78,1 -DA:79,1 -DA:80,1 -DA:81,1 -DA:82,2 -DA:83,2 -DA:84,2 -DA:85,2 -DA:86,2 -DA:87,2 -DA:88,2 -DA:89,2 -DA:90,2 -DA:91,2 -DA:92,2 -DA:93,1 -DA:94,1 -DA:95,1 -DA:96,1 -DA:97,2 -DA:98,2 -LF:98 -LH:98 -BRDA:24,0,0,5 -BRDA:31,1,0,3 -BRDA:34,2,0,6 -BRDA:35,3,0,3 -BRDA:43,4,0,6 -BRDA:44,5,0,1 -BRDA:44,6,0,5 -BRDA:51,7,0,4 -BRDA:57,8,0,2 -BRDA:63,9,0,2 -BRDA:82,10,0,2 -BRDA:92,11,0,1 -BRF:12 -BRH:12 -end_of_record -TN: -SF:src/db/validate-schema.ts -FN:8,missingTables -FN:29,validateSchema -FNF:2 -FNH:2 -FNDA:7,missingTables -FNDA:3,validateSchema -DA:1,1 -DA:2,1 -DA:3,1 -DA:4,1 -DA:5,1 -DA:6,1 -DA:7,1 -DA:8,7 -DA:9,7 -DA:10,7 -DA:11,7 -DA:12,7 -DA:13,7 -DA:14,7 -DA:15,7 -DA:16,7 -DA:17,7 -DA:18,7 -DA:19,7 -DA:20,7 -DA:21,7 -DA:22,7 -DA:23,7 -DA:24,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,3 -DA:30,3 -DA:31,3 -DA:32,2 -DA:33,2 -DA:34,3 -LF:34 -LH:34 -BRDA:8,0,0,7 -BRDA:12,1,0,30 -BRDA:19,2,0,15 -BRDA:22,3,0,30 -BRDA:29,4,0,3 -BRDA:31,5,0,2 -BRF:6 -BRH:6 -end_of_record diff --git a/package-lock.json b/package-lock.json index 313de85..5e1396e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,14 +21,32 @@ "@types/pg": "^8.10.9", "@types/supertest": "^7.2.0", "@types/swagger-ui-express": "^4.1.8", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", "@vitest/coverage-v8": "^1.6.1", - "@vitest/coverage-v8": "^4.0.18", + "eslint": "^8.57.1", + "eslint-config-airbnb-typescript": "^18.0.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^7.2.1", "supertest": "^7.2.2", "tsx": "^4.7.0", "typescript": "~5.2.2", "vitest": "^4.0.18" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "dev": true, @@ -72,501 +90,252 @@ } }, "node_modules/@bcoe/v8-coverage": { - "version": "1.0.2", + "version": "0.2.3", "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", "cpu": [ - "ppc64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "aix" + "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=12" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.4.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=12" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "cpu": [ - "x64" - ], + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "8.57.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=12" + "node": ">=10.10.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.4.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=12" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.3", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "MIT" + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, "engines": { - "node": ">=12" + "node": ">= 8" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 8" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "version": "0.27.3", - "cpu": [ - "x64" - ], + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, "engines": { - "node": ">=12" + "node": ">= 8" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@noble/hashes": "^1.1.5" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.1.5" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" + "arm" ], "dev": true, "license": "MIT", @@ -801,6 +570,8 @@ }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ "x64" ], @@ -909,17 +680,22 @@ "win32" ] }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, "node_modules/@scarf/scarf": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", "hasInstallScript": true, "license": "Apache-2.0" }, - "node_modules/@sinclair/typebox": { - "version": "0.27.10", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", - "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", "node_modules/@standard-schema/spec": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, "license": "MIT" }, @@ -934,6 +710,8 @@ }, "node_modules/@types/chai": { "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { @@ -951,6 +729,8 @@ }, "node_modules/@types/cookiejar": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", "dev": true, "license": "MIT" }, @@ -964,11 +744,15 @@ }, "node_modules/@types/deep-eql": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -999,8 +783,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json5": { + "version": "0.0.29", + "dev": true, + "license": "MIT" + }, "node_modules/@types/methods": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", "dev": true, "license": "MIT" }, @@ -1011,7 +802,6 @@ }, "node_modules/@types/node": { "version": "20.19.33", - "version": "20.19.34", "dev": true, "license": "MIT", "dependencies": { @@ -1020,8 +810,6 @@ }, "node_modules/@types/pg": { "version": "8.16.0", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.16.0.tgz", - "integrity": "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1069,6 +857,8 @@ }, "node_modules/@types/superagent": { "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1080,6 +870,8 @@ }, "node_modules/@types/supertest": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-7.2.0.tgz", + "integrity": "sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==", "dev": true, "license": "MIT", "dependencies": { @@ -1089,6 +881,8 @@ }, "node_modules/@types/swagger-ui-express": { "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.8.tgz", + "integrity": "sha512-AhZV8/EIreHFmBV5wAs0gzJUNq9JbbSXgJLQubCC0jtIo6prnI9MIRRxnU4MZX9RB9yXxF1V4R7jtLl/Wcj31g==", "dev": true, "license": "MIT", "dependencies": { @@ -1096,1179 +890,2542 @@ "@types/serve-static": "*" } }, - "node_modules/@vitest/coverage-v8": { - "version": "4.0.18", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", "dev": true, "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.18", - "ast-v8-to-istanbul": "^0.3.10", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.2.0", - "magicast": "^0.5.1", - "obug": "^2.1.1", - "std-env": "^3.10.0", - "tinyrainbow": "^3.0.3" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@vitest/browser": "4.0.18", - "vitest": "4.0.18" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { - "@vitest/browser": { + "typescript": { "optional": true } } }, - "node_modules/@vitest/expect": { - "version": "4.0.18", + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@vitest/mocker": { - "version": "4.0.18", + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.4.3", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "ms": "^2.1.3" }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" + "engines": { + "node": ">=6.0" }, "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { + "supports-color": { "optional": true } } }, - "node_modules/@vitest/pretty-format": { - "version": "4.0.18", + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^3.0.3" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@vitest/runner": { - "version": "4.0.18", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", - "pathe": "^2.0.3" + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@vitest/snapshot": { - "version": "4.0.18", + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.4.3", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" + "ms": "^2.1.3" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@vitest/spy": { - "version": "4.0.18", + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", "dev": true, "license": "MIT", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@vitest/utils": { - "version": "4.0.18", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/accepts": { - "version": "1.3.8", + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "dev": true, "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, "engines": { - "node": ">= 0.6" + "node": "18 || 20 || >=22" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/asap": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/assertion-error": { - "version": "2.0.1", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.3", "dev": true, "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, "engines": { - "node": ">=12" + "node": "18 || 20 || >=22" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/asap": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "node_modules/ast-v8-to-istanbul": { - "version": "0.3.11", + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.4.3", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.31", - "estree-walker": "^3.0.3", - "js-tokens": "^10.0.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/asynckit": { - "version": "0.4.0", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.8", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.3", "dev": true, "license": "MIT" }, - "node_modules/body-parser": { - "version": "1.20.4", + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/bytes": { - "version": "3.1.2", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">= 0.8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitest/coverage-v8": { + "version": "1.6.1", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magic-string": "^0.30.5", + "magicast": "^0.3.3", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "test-exclude": "^6.0.0" }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.1" } }, - "node_modules/call-bound": { - "version": "1.0.4", + "node_modules/@vitest/coverage-v8/node_modules/debug": { + "version": "4.4.3", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/chai": { - "version": "6.2.2", + "node_modules/@vitest/coverage-v8/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/expect": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/combined-stream": { - "version": "1.0.8", + "node_modules/@vitest/mocker": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", "dev": true, "license": "MIT", "dependencies": { - "delayed-stream": "~1.0.0" + "@vitest/spy": "4.0.18", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" }, - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/combined-stream": { - "version": "1.0.8", + "node_modules/@vitest/pretty-format": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", "dev": true, "license": "MIT", "dependencies": { - "delayed-stream": "~1.0.0" + "tinyrainbow": "^3.0.3" }, - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/component-emitter": { - "version": "1.3.1", + "node_modules/@vitest/runner": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", "dev": true, "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.18", + "pathe": "^2.0.3" + }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/@vitest/snapshot": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "node_modules/component-emitter": { - "version": "1.3.1", + "node_modules/@vitest/spy": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", "dev": true, "license": "MIT", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/content-disposition": { - "version": "0.5.4", + "node_modules/@vitest/utils": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "5.2.1" + "@vitest/pretty-format": "4.0.18", + "tinyrainbow": "^3.0.3" }, - "engines": { - "node": ">= 0.6" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/content-type": { - "version": "1.0.5", + "node_modules/accepts": { + "version": "1.3.8", "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, "engines": { "node": ">= 0.6" } }, - "node_modules/cookie": { - "version": "0.7.2", + "node_modules/acorn": { + "version": "8.16.0", + "dev": true, "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">= 0.6" + "node": ">=0.4.0" } }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "license": "MIT" - }, - "node_modules/cookiejar": { - "version": "2.1.4", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", "dev": true, - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.6", "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/debug": { - "version": "2.6.9", + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", + "node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, "engines": { - "node": ">=0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", + "node_modules/array-flatten": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.9", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/depd": { - "version": "2.0.0", + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/destroy": { - "version": "1.2.0", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dezalgo": { - "version": "1.0.4", + "node_modules/array.prototype.flat": { + "version": "1.3.3", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ee-first": { - "version": "1.1.1", + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, "license": "MIT" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" } }, - "node_modules/es-errors": { - "version": "1.3.0", + "node_modules/async-function": { + "version": "1.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, - "node_modules/es-module-lexer": { - "version": "1.7.0", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true, "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "possible-typed-array-names": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", + "node_modules/balanced-match": { + "version": "1.0.2", "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.4", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/esbuild": { - "version": "0.27.3", + "node_modules/brace-expansion": { + "version": "1.1.12", "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/estree-walker": { + "node_modules/braces": { "version": "3.0.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "fill-range": "^7.1.1" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/esbuild/node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "node_modules/etag": { - "version": "1.8.1", + "node_modules/bytes": { + "version": "3.1.2", "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">= 0.8" } }, - "node_modules/esbuild/node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], + "node_modules/call-bind": { + "version": "1.0.8", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "node_modules/expect-type": { - "version": "1.3.0", - "dev": true, - "license": "Apache-2.0", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" } }, - "node_modules/express": { - "version": "4.22.1", + "node_modules/call-bound": { + "version": "1.0.4", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", + "node_modules/callsites": { + "version": "3.1.0", "dev": true, "license": "MIT", "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": ">=6" } }, - "node_modules/finalhandler": { - "version": "1.3.2", + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { "node": ">=18" } }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "node_modules/form-data": { - "version": "4.0.5", + "node_modules/chalk": { + "version": "4.1.2", "dev": true, "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/formidable": { - "version": "3.5.4", + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, "license": "MIT", "dependencies": { - "@paralleldrive/cuid2": "^2.2.2", - "dezalgo": "^1.0.4", - "once": "^1.4.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=8" }, "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/forwarded": { - "version": "0.2.0", + "node_modules/color-convert": { + "version": "2.0.1", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=18" + "node": ">=7.0.0" } }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], + "node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "node_modules/fresh": { - "version": "0.5.2", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "delayed-stream": "~1.0.0" + }, "engines": { - "node": ">=18" + "node": ">= 0.8" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "safe-buffer": "5.2.1" + }, "engines": { - "node": ">=18" + "node": ">= 0.6" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "node_modules/function-bind": { - "version": "1.1.2", + "node_modules/content-type": { + "version": "1.0.5", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">= 0.6" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, + "node_modules/cookie": { + "version": "0.7.2", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">= 0.6" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], + "node_modules/cookie-signature": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, "engines": { - "node": ">=18" + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], + "node_modules/cross-spawn": { + "version": "7.0.6", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 8" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], + "node_modules/data-view-buffer": { + "version": "1.0.2", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], + "node_modules/data-view-byte-length": { + "version": "1.0.2", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/esbuild/node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], + "node_modules/data-view-byte-offset": { + "version": "1.0.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], + "node_modules/debug": { + "version": "2.6.9", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], + "node_modules/define-properties": { + "version": "1.2.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "node_modules/esbuild": { "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-airbnb-typescript": { + "version": "18.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-es": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-node": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "7.2.1", + "dev": true, + "license": "ISC", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/espree": { + "version": "9.6.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/express": { + "version": "4.22.1", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.6", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": ">= 0.10" } }, - "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], + "node_modules/is-array-buffer": { + "version": "3.0.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], + "node_modules/is-async-function": { + "version": "2.1.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild/node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], + "node_modules/is-bigint": { + "version": "1.1.0", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "has-bigints": "^1.0.2" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "node_modules/is-boolean-object": { + "version": "1.2.2", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/etag": { - "version": "1.8.1", + "node_modules/is-callable": { + "version": "1.2.7", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "node_modules/is-core-module": { + "version": "2.16.1", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" + "hasown": "^2.0.2" }, "engines": { - "node": ">=16.17" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express": { - "version": "4.22.1", + "node_modules/is-data-view": { + "version": "1.0.2", + "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", + "node_modules/is-date-object": { + "version": "1.1.0", "dev": true, - "license": "MIT" - }, - "node_modules/finalhandler": { - "version": "1.3.2", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/form-data": { - "version": "4.0.5", + "node_modules/is-extglob": { + "version": "2.1.1", "dev": true, "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/formidable": { - "version": "3.5.4", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", "dev": true, "license": "MIT", "dependencies": { - "@paralleldrive/cuid2": "^2.2.2", - "dezalgo": "^1.0.4", - "once": "^1.4.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=14.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/forwarded": { - "version": "0.2.0", + "node_modules/is-generator-function": { + "version": "1.1.2", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fresh": { - "version": "0.5.2", + "node_modules/is-glob": { + "version": "4.0.3", + "dev": true, "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", + "node_modules/is-map": { + "version": "2.0.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function-bind": { - "version": "1.1.2", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "node_modules/is-number": { + "version": "7.0.0", "dev": true, "license": "MIT", "engines": { - "node": "*" + "node": ">=0.12.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", + "node_modules/is-number-object": { + "version": "1.1.1", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -2277,42 +3434,49 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-proto": { - "version": "1.0.1", + "node_modules/is-path-inside": { + "version": "3.0.3", + "dev": true, "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/get-tsconfig": { - "version": "4.13.6", + "node_modules/is-regex": { + "version": "1.2.1", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, "engines": { - "node": ">=16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-tsconfig": { - "version": "4.13.6", + "node_modules/is-set": { + "version": "2.0.3", "dev": true, "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { - "version": "1.2.0", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, "engines": { "node": ">= 0.4" }, @@ -2320,17 +3484,30 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "4.0.0", + "node_modules/is-string": { + "version": "1.1.1", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.1.0", + "node_modules/is-symbol": { + "version": "1.1.1", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, "engines": { "node": ">= 0.4" }, @@ -2338,12 +3515,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", + "node_modules/is-typed-array": { + "version": "1.1.15", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -2352,59 +3529,55 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasown": { + "node_modules/is-weakmap": { "version": "2.0.2", + "dev": true, "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-escaper": { - "version": "2.0.2", + "node_modules/is-weakref": { + "version": "1.1.1", "dev": true, - "license": "MIT" - }, - "node_modules/http-errors": { - "version": "2.0.1", "license": "MIT", "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "call-bound": "^1.0.3" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", + "node_modules/is-weakset": { + "version": "2.0.4", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" + "node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -2427,6 +3600,40 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, "node_modules/istanbul-reports": { "version": "3.2.0", "dev": true, @@ -2440,7 +3647,83 @@ } }, "node_modules/js-tokens": { - "version": "10.0.0", + "version": "9.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", "dev": true, "license": "MIT" }, @@ -2453,13 +3736,13 @@ } }, "node_modules/magicast": { - "version": "0.5.2", + "version": "0.3.5", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "source-map-js": "^1.2.1" + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" } }, "node_modules/make-dir": { @@ -2497,6 +3780,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/methods": { "version": "1.1.2", "license": "MIT", @@ -2504,71 +3795,197 @@ "node": ">= 0.6" } }, + "node_modules/micromatch": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime": { "version": "1.6.0", "license": "MIT", "bin": { "mime": "cli.js" }, - "engines": { - "node": ">=4" + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mime-db": { - "version": "1.52.0", + "node_modules/object-keys": { + "version": "1.1.1", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.4" } }, - "node_modules/mime-types": { - "version": "2.1.35", + "node_modules/object.assign": { + "version": "4.1.7", + "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", + "node_modules/object.entries": { + "version": "1.1.9", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">= 0.4" } }, - "node_modules/negotiator": { - "version": "0.6.3", + "node_modules/object.fromentries": { + "version": "2.0.8", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-assign": { - "version": "4.1.1", + "node_modules/object.groupby": { + "version": "1.0.3", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/object-inspect": { - "version": "1.13.4", + "node_modules/object.values": { + "version": "1.2.1", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2578,6 +3995,8 @@ }, "node_modules/obug": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", @@ -2603,6 +4022,88 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.9.4", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate/node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parseurl": { "version": "1.3.3", "license": "MIT", @@ -2610,19 +4111,56 @@ "node": ">= 0.8" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, "node_modules/path-to-regexp": { "version": "0.1.12", "license": "MIT" }, + "node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/pathe": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/pg": { "version": "8.19.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.19.0.tgz", - "integrity": "sha512-QIcLGi508BAHkQ3pJNptsFz5WQMlpGbuBGBaIaXsWK8mel2kQ/rThYI+DbgjUvZrIr7MiuEuc9LcChJoEZK1xQ==", "license": "MIT", "dependencies": { "pg-connection-string": "^2.11.0", @@ -2648,21 +4186,15 @@ }, "node_modules/pg-cloudflare": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", - "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { "version": "2.11.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz", - "integrity": "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==", "license": "MIT" }, "node_modules/pg-int8": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", "license": "ISC", "engines": { "node": ">=4.0.0" @@ -2670,8 +4202,6 @@ }, "node_modules/pg-pool": { "version": "3.12.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.12.0.tgz", - "integrity": "sha512-eIJ0DES8BLaziFHW7VgJEBPi5hg3Nyng5iKpYtj3wbcAUV9A1wLgWiY7ajf/f/oO1wfxt83phXPY8Emztg7ITg==", "license": "MIT", "peerDependencies": { "pg": ">=8.0" @@ -2679,14 +4209,10 @@ }, "node_modules/pg-protocol": { "version": "1.12.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.12.0.tgz", - "integrity": "sha512-uOANXNRACNdElMXJ0tPz6RBM0XQ61nONGAwlt8da5zs/iUOOCLBQOHSXnrC6fMsvtjxbOJrZZl5IScGv+7mpbg==", "license": "MIT" }, "node_modules/pg-types": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", "license": "MIT", "dependencies": { "pg-int8": "1.0.1", @@ -2701,8 +4227,6 @@ }, "node_modules/pgpass": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", "license": "MIT", "dependencies": { "split2": "^4.1.0" @@ -2714,18 +4238,28 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", + "version": "2.3.1", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -2753,8 +4287,6 @@ }, "node_modules/postgres-array": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", "license": "MIT", "engines": { "node": ">=4" @@ -2762,8 +4294,6 @@ }, "node_modules/postgres-bytea": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", - "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2771,8 +4301,6 @@ }, "node_modules/postgres-date": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2780,8 +4308,6 @@ }, "node_modules/postgres-interval": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", "license": "MIT", "dependencies": { "xtend": "^4.0.0" @@ -2790,6 +4316,14 @@ "node": ">=0.10.0" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "license": "MIT", @@ -2801,6 +4335,14 @@ "node": ">= 0.10" } }, + "node_modules/punycode": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.14.2", "license": "BSD-3-Clause", @@ -2814,6 +4356,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "license": "MIT", @@ -2821,17 +4382,95 @@ "node": ">= 0.6" } }, - "node_modules/raw-body": { - "version": "2.5.3", + "node_modules/raw-body": { + "version": "2.5.3", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, "node_modules/resolve-pkg-maps": { @@ -2842,8 +4481,33 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/reusify": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", "dependencies": { @@ -2885,6 +4549,46 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "funding": [ @@ -2903,6 +4607,37 @@ ], "license": "MIT" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "license": "MIT" @@ -2957,10 +4692,72 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "license": "ISC" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.1.0", "license": "MIT", @@ -3030,6 +4827,14 @@ "dev": true, "license": "ISC" }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "dev": true, @@ -3040,324 +4845,177 @@ }, "node_modules/split2": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "license": "ISC", "engines": { "node": ">= 10.x" } }, - "node_modules/stackback": { - "version": "0.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/statuses": { - "version": "2.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/std-env": { - "version": "3.10.0", - "dev": true, - "license": "MIT" - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-literal": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", - "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/superagent": { - "version": "10.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "component-emitter": "^1.3.1", - "cookiejar": "^2.1.4", - "debug": "^4.3.7", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.5", - "formidable": "^3.5.4", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.14.1" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "4.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.6.0", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/superagent/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/supertest": { - "version": "7.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cookie-signature": "^1.2.2", - "methods": "^1.1.2", - "superagent": "^10.3.0" - }, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/supertest/node_modules/cookie-signature": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", + "node_modules/stackback": { + "version": "0.0.2", "dev": true, + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/tinybench": { - "version": "2.9.0", + "node_modules/std-env": { + "version": "3.10.0", "dev": true, "license": "MIT" }, - "node_modules/tinyexec": { - "version": "1.0.2", + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" } }, - "node_modules/tinyglobby": { - "version": "0.2.15", + "node_modules/string.prototype.trim": { + "version": "1.2.10", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tinyrainbow": { - "version": "3.0.3", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">=0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tsx": { - "version": "4.21.0", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is": { - "version": "1.6.18", + "node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/typescript": { - "version": "5.2.2", + "node_modules/strip-bom": { + "version": "3.0.0", "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=14.17" + "node": ">=4" } }, - "node_modules/undici-types": { - "version": "6.21.0", + "node_modules/strip-json-comments": { + "version": "3.1.1", "dev": true, - "license": "MIT" - }, - "node_modules/unpipe": { - "version": "1.0.0", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/utils-merge": { - "version": "1.0.1", + "node_modules/strip-literal": { + "version": "2.1.1", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4.0" + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/vary": { - "version": "1.1.2", + "node_modules/superagent": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", + "dev": true, "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.5", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.14.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=14.18.0" } }, - "node_modules/vite": { - "version": "7.3.1", + "node_modules/superagent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" + "ms": "^2.1.3" }, "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" + "node": ">=6.0" }, "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { + "supports-color": { "optional": true } } }, "node_modules/superagent/node_modules/mime": { "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, "license": "MIT", "bin": { @@ -3369,11 +5027,15 @@ }, "node_modules/superagent/node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/supertest": { "version": "7.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz", + "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==", "dev": true, "license": "MIT", "dependencies": { @@ -3387,6 +5049,8 @@ }, "node_modules/supertest/node_modules/cookie-signature": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "dev": true, "license": "MIT", "engines": { @@ -3395,8 +5059,6 @@ }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -3406,8 +5068,21 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/swagger-ui-dist": { "version": "5.31.2", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.31.2.tgz", + "integrity": "sha512-uIoesCjDcxnAKj/C/HG5pjHZMQs2K/qmqpUlwLxxaVryGKlgm8Ri+VOza5xywAqf//pgg/hW16RYa6dDuTCOSg==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -3415,6 +5090,8 @@ }, "node_modules/swagger-ui-express": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", + "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", "license": "MIT", "dependencies": { "swagger-ui-dist": ">=5.0.0" @@ -3428,8 +5105,6 @@ }, "node_modules/test-exclude": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "license": "ISC", "dependencies": { @@ -3441,29 +5116,93 @@ "node": ">=8" } }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, "node_modules/tinybench": { "version": "2.9.0", "dev": true, "license": "MIT" }, - "node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" } }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "node_modules/to-regex-range": { + "version": "5.0.1", "dev": true, "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, "engines": { - "node": ">=14.0.0" + "node": ">=8.0" } }, "node_modules/toidentifier": { @@ -3473,6 +5212,28 @@ "node": ">=0.6" } }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, "node_modules/tsx": { "version": "4.21.0", "dev": true, @@ -3491,14 +5252,26 @@ "fsevents": "~2.3.3" } }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "node_modules/type-check": { + "version": "0.4.0", "dev": true, "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/type-is": { @@ -3512,6 +5285,76 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { "version": "5.2.2", "dev": true, @@ -3524,12 +5367,22 @@ "node": ">=14.17" } }, - "node_modules/ufo": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", - "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "node_modules/unbox-primitive": { + "version": "1.1.0", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/undici-types": { "version": "6.21.0", @@ -3543,6 +5396,14 @@ "node": ">= 0.8" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "license": "MIT", @@ -3558,21 +5419,24 @@ } }, "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -3581,19 +5445,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -3614,80 +5484,50 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, - "node_modules/vite-node": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz", - "integrity": "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==", + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite-node/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" + "node": ">=12.0.0" }, - "engines": { - "node": ">=6.0" + "peerDependencies": { + "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { - "supports-color": { + "picomatch": { "optional": true } } }, - "node_modules/vite-node/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "node_modules/vitest": { "version": "4.0.18", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3762,6 +5602,114 @@ } } }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "dev": true, @@ -3777,6 +5725,14 @@ "node": ">=8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "dev": true, @@ -3784,8 +5740,6 @@ }, "node_modules/xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "license": "MIT", "engines": { "node": ">=0.4" @@ -3793,6 +5747,8 @@ }, "node_modules/yaml": { "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -3803,19 +5759,6 @@ "funding": { "url": "https://github.com/sponsors/eemeli" } - }, - "node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index ad19431..e3bbb94 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "build": "tsc", "start": "node dist/index.js", "dev": "tsx watch src/index.ts", - "typecheck": "tsc --noEmit", - "lint": "eslint 'src/**/*.ts' --max-warnings=0", - "lint:fix": "eslint 'src/**/*.ts' --fix", + "lint": "eslint --ext .ts src", + "lint:fix": "eslint --ext .ts src --fix", + "typecheck": "tsc --noEmit", "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", @@ -32,14 +32,13 @@ "@types/supertest": "^7.2.0", "@types/swagger-ui-express": "^4.1.8", "@vitest/coverage-v8": "^1.6.1", - "@types/supertest": "^6.0.2", - "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0", - "@vitest/coverage-v8": "^1.6.1", - "eslint": "^8.57.0", - "supertest": "^7.0.0", - "@types/supertest": "^7.2.0", - "@vitest/coverage-v8": "^4.0.18", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", + "eslint": "^8.57.1", + "eslint-config-airbnb-typescript": "^18.0.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^7.2.1", "supertest": "^7.2.2", "tsx": "^4.7.0", "typescript": "~5.2.2", diff --git a/src/__test__/adminAuth.test.ts b/src/__test__/adminAuth.test.ts index 5d226e6..5b07daa 100644 --- a/src/__test__/adminAuth.test.ts +++ b/src/__test__/adminAuth.test.ts @@ -1,33 +1,33 @@ import express from "express"; import request from "supertest"; import { adminAuth, ADMIN_KEY_HEADER } from "../../middleware/adminAuth.js"; -import { afterEach, afterEach, beforeEach } from "node:test"; +import { afterEach, beforeEach } from "node:test"; const SECRET = "test-admin-secret-key"; function buildApp() { - const app = express(); - app.use(express.json()); - // A single protected route for testing the middleware - app.post("/protected", adminAuth, (_req, res) => { - res.json({ ok: true }); - }); - return app; + const app = express(); + app.use(express.json()); + // A single protected route for testing the middleware + app.post("/protected", adminAuth, (_req, res) => { + res.json({ ok: true }); + }); + return app; } let originalKey: string | undefined; beforeEach(() => { - originalKey = process.env["ADMIN_API_KEY"]; - process.env["ADMIN_API_KEY"] = SECRET; + originalKey = process.env.ADMIN_API_KEY; + process.env.ADMIN_API_KEY = SECRET; }); afterEach(() => { - if (originalKey === undefined) { - delete process.env["ADMIN_API_KEY"]; - } else { - process.env["ADMIN_API_KEY"] = originalKey; - } + if (originalKey === undefined) { + delete process.env.ADMIN_API_KEY; + } else { + process.env.ADMIN_API_KEY = originalKey; + } }); // --------------------------------------------------------------------------- @@ -35,86 +35,86 @@ afterEach(() => { // --------------------------------------------------------------------------- describe("adminAuth middleware", () => { - describe("when ADMIN_API_KEY env var is configured", () => { - it("calls next() and returns 200 when the correct key is supplied", async () => { - const res = await request(buildApp()) - .post("/protected") - .set(ADMIN_KEY_HEADER, SECRET); - - expect(res.status).toBe(200); - expect(res.body).toEqual({ ok: true }); - }); - - it("returns 401 when the X-Admin-Api-Key header is missing", async () => { - const res = await request(buildApp()).post("/protected"); - - expect(res.status).toBe(401); - expect(res.body.error).toContain("Unauthorized"); - }); - - it("returns 401 when the header value is wrong", async () => { - const res = await request(buildApp()) - .post("/protected") - .set(ADMIN_KEY_HEADER, "wrong-key"); - - expect(res.status).toBe(401); - expect(res.body.error).toContain("Unauthorized"); - }); - - it("returns 401 when the header is an empty string", async () => { - const res = await request(buildApp()) - .post("/protected") - .set(ADMIN_KEY_HEADER, ""); - - expect(res.status).toBe(401); - }); - - it("returns 401 when the header is close but not equal to the secret", async () => { - const res = await request(buildApp()) - .post("/protected") - .set(ADMIN_KEY_HEADER, SECRET + " "); - - expect(res.status).toBe(401); - }); - - it("response body includes X-Admin-Api-Key in the error hint", async () => { - const res = await request(buildApp()).post("/protected"); - - expect(res.body.error).toMatch(/X-Admin-Api-Key/); - }); - - it("returns JSON content-type on 401", async () => { - const res = await request(buildApp()).post("/protected"); - expect(res.headers["content-type"]).toMatch(/application\/json/); - }); + describe("when ADMIN_API_KEY env var is configured", () => { + it("calls next() and returns 200 when the correct key is supplied", async () => { + const res = await request(buildApp()) + .post("/protected") + .set(ADMIN_KEY_HEADER, SECRET); + + expect(res.status).toBe(200); + expect(res.body).toEqual({ ok: true }); + }); + + it("returns 401 when the X-Admin-Api-Key header is missing", async () => { + const res = await request(buildApp()).post("/protected"); + + expect(res.status).toBe(401); + expect(res.body.error).toContain("Unauthorized"); + }); + + it("returns 401 when the header value is wrong", async () => { + const res = await request(buildApp()) + .post("/protected") + .set(ADMIN_KEY_HEADER, "wrong-key"); + + expect(res.status).toBe(401); + expect(res.body.error).toContain("Unauthorized"); + }); + + it("returns 401 when the header is an empty string", async () => { + const res = await request(buildApp()) + .post("/protected") + .set(ADMIN_KEY_HEADER, ""); + + expect(res.status).toBe(401); + }); + + it("returns 401 when the header is close but not equal to the secret", async () => { + const res = await request(buildApp()) + .post("/protected") + .set(ADMIN_KEY_HEADER, SECRET + " "); + + expect(res.status).toBe(401); + }); + + it("response body includes X-Admin-Api-Key in the error hint", async () => { + const res = await request(buildApp()).post("/protected"); + + expect(res.body.error).toMatch(/X-Admin-Api-Key/); + }); + + it("returns JSON content-type on 401", async () => { + const res = await request(buildApp()).post("/protected"); + expect(res.headers["content-type"]).toMatch(/application\/json/); + }); + }); + + describe("when ADMIN_API_KEY env var is NOT configured", () => { + beforeEach(() => { + delete process.env.ADMIN_API_KEY; + }); + + it("returns 503 regardless of what header is sent", async () => { + const res = await request(buildApp()) + .post("/protected") + .set(ADMIN_KEY_HEADER, "anything"); + + expect(res.status).toBe(503); + }); + + it("returns 503 even without a header", async () => { + const res = await request(buildApp()).post("/protected"); + expect(res.status).toBe(503); + }); + + it("body error mentions admin authentication is not configured", async () => { + const res = await request(buildApp()).post("/protected"); + expect(res.body.error).toMatch(/not configured/i); }); - describe("when ADMIN_API_KEY env var is NOT configured", () => { - beforeEach(() => { - delete process.env["ADMIN_API_KEY"]; - }); - - it("returns 503 regardless of what header is sent", async () => { - const res = await request(buildApp()) - .post("/protected") - .set(ADMIN_KEY_HEADER, "anything"); - - expect(res.status).toBe(503); - }); - - it("returns 503 even without a header", async () => { - const res = await request(buildApp()).post("/protected"); - expect(res.status).toBe(503); - }); - - it("body error mentions admin authentication is not configured", async () => { - const res = await request(buildApp()).post("/protected"); - expect(res.body.error).toMatch(/not configured/i); - }); - - it("returns JSON content-type on 503", async () => { - const res = await request(buildApp()).post("/protected"); - expect(res.headers["content-type"]).toMatch(/application\/json/); - }); + it("returns JSON content-type on 503", async () => { + const res = await request(buildApp()).post("/protected"); + expect(res.headers["content-type"]).toMatch(/application\/json/); }); + }); }); \ No newline at end of file diff --git a/src/__test__/creditService.test.ts b/src/__test__/creditService.test.ts index 6d340e0..273545a 100644 --- a/src/__test__/creditService.test.ts +++ b/src/__test__/creditService.test.ts @@ -193,79 +193,79 @@ describe("suspendCreditLine()", () => { describe("closeCreditLine()", () => { - describe("valid transition: active → closed", () => { - it("changes status to 'closed'", () => { - createCreditLine("line-1"); - const updated = closeCreditLine("line-1"); - expect(updated.status).toBe("closed"); - }); - - it("appends a 'closed' event", () => { - createCreditLine("line-1"); - const updated = closeCreditLine("line-1"); - expect(updated.events.at(-1)!.action).toBe("closed"); - }); + describe("valid transition: active → closed", () => { + it("changes status to 'closed'", () => { + createCreditLine("line-1"); + const updated = closeCreditLine("line-1"); + expect(updated.status).toBe("closed"); + }); + + it("appends a 'closed' event", () => { + createCreditLine("line-1"); + const updated = closeCreditLine("line-1"); + expect(updated.events.at(-1)!.action).toBe("closed"); }); + }); - describe("valid transition: suspended → closed", () => { - it("changes status from suspended to closed", () => { - createCreditLine("line-1", "suspended"); - const updated = closeCreditLine("line-1"); - expect(updated.status).toBe("closed"); - }); - - it("appends a 'closed' event after existing events", () => { - createCreditLine("line-1", "suspended"); - const updated = closeCreditLine("line-1"); - expect(updated.events.at(-1)!.action).toBe("closed"); - }); + describe("valid transition: suspended → closed", () => { + it("changes status from suspended to closed", () => { + createCreditLine("line-1", "suspended"); + const updated = closeCreditLine("line-1"); + expect(updated.status).toBe("closed"); }); - describe("invalid transition: closed → closed", () => { - it("throws InvalidTransitionError when line is already closed", () => { - createCreditLine("line-1", "closed"); - expect(() => closeCreditLine("line-1")).toThrow(InvalidTransitionError); - }); - - it("error message mentions 'close' and 'closed'", () => { - createCreditLine("line-1", "closed"); - expect(() => closeCreditLine("line-1")).toThrow(/close.*closed|closed.*close/i); - }); - - it("exposes currentStatus 'closed' and requestedAction 'close'", () => { - createCreditLine("line-1", "closed"); - try { - closeCreditLine("line-1"); - } catch (err) { - const e = err as InvalidTransitionError; - expect(e.currentStatus).toBe("closed"); - expect(e.requestedAction).toBe("close"); - } - }); + it("appends a 'closed' event after existing events", () => { + createCreditLine("line-1", "suspended"); + const updated = closeCreditLine("line-1"); + expect(updated.events.at(-1)!.action).toBe("closed"); }); + }); - describe("not-found error", () => { - it("throws CreditLineNotFoundError for unknown id", () => { - expect(() => closeCreditLine("ghost")).toThrow(CreditLineNotFoundError); - }); + describe("invalid transition: closed → closed", () => { + it("throws InvalidTransitionError when line is already closed", () => { + createCreditLine("line-1", "closed"); + expect(() => closeCreditLine("line-1")).toThrow(InvalidTransitionError); + }); - it("error message includes the id", () => { - expect(() => closeCreditLine("ghost")).toThrow(/ghost/); - }); + it("error message mentions 'close' and 'closed'", () => { + createCreditLine("line-1", "closed"); + expect(() => closeCreditLine("line-1")).toThrow(/close.*closed|closed.*close/i); }); - describe("full lifecycle", () => { - it("supports active → suspend → close transition sequence", () => { - createCreditLine("line-1"); - suspendCreditLine("line-1"); - const closed = closeCreditLine("line-1"); - expect(closed.status).toBe("closed"); - expect(closed.events).toHaveLength(3); - expect(closed.events.map((e) => e.action)).toEqual([ - "created", - "suspended", - "closed", - ]); - }); + it("exposes currentStatus 'closed' and requestedAction 'close'", () => { + createCreditLine("line-1", "closed"); + try { + closeCreditLine("line-1"); + } catch (err) { + const e = err as InvalidTransitionError; + expect(e.currentStatus).toBe("closed"); + expect(e.requestedAction).toBe("close"); + } + }); + }); + + describe("not-found error", () => { + it("throws CreditLineNotFoundError for unknown id", () => { + expect(() => closeCreditLine("ghost")).toThrow(CreditLineNotFoundError); + }); + + it("error message includes the id", () => { + expect(() => closeCreditLine("ghost")).toThrow(/ghost/); + }); + }); + + describe("full lifecycle", () => { + it("supports active → suspend → close transition sequence", () => { + createCreditLine("line-1"); + suspendCreditLine("line-1"); + const closed = closeCreditLine("line-1"); + expect(closed.status).toBe("closed"); + expect(closed.events).toHaveLength(3); + expect(closed.events.map((e) => e.action)).toEqual([ + "created", + "suspended", + "closed", + ]); + }); }); }); \ No newline at end of file diff --git a/src/__test__/horizonListener.test.ts b/src/__test__/horizonListener.test.ts index d694a63..b1f704f 100644 --- a/src/__test__/horizonListener.test.ts +++ b/src/__test__/horizonListener.test.ts @@ -73,10 +73,10 @@ afterEach(() => { describe("resolveConfig()", () => { it("returns sensible defaults when no env vars are set", () => { - delete process.env["HORIZON_URL"]; - delete process.env["CONTRACT_IDS"]; - delete process.env["POLL_INTERVAL_MS"]; - delete process.env["HORIZON_START_LEDGER"]; + delete process.env.HORIZON_URL; + delete process.env.CONTRACT_IDS; + delete process.env.POLL_INTERVAL_MS; + delete process.env.HORIZON_START_LEDGER; const config = resolveConfig(); @@ -178,7 +178,8 @@ describe("start()", () => { it("executes an immediate first poll on start", async () => { jest.useFakeTimers(); - const pollSpy = jest.fn, [HorizonListenerConfig]>(); + // pollSpy is unused but kept for future assertions + const _pollSpy = jest.fn, [HorizonListenerConfig]>(); withEnv({ CONTRACT_IDS: "MY_CONTRACT" }, async () => { const received: HorizonEvent[] = []; diff --git a/src/__test__/riskRoute.test.ts b/src/__test__/riskRoute.test.ts index 4665743..ad7cc46 100644 --- a/src/__test__/riskRoute.test.ts +++ b/src/__test__/riskRoute.test.ts @@ -4,7 +4,7 @@ import request from "supertest"; import { jest } from "@jest/globals"; jest.mock("../../services/riskService.js", () => ({ - evaluateWallet: jest.fn(), + evaluateWallet: jest.fn(), })); import riskRouter from "../../routes/risk.js"; @@ -15,146 +15,146 @@ const mockEvaluateWallet = evaluateWallet as jest.MockedFunction< >; function buildApp(): Express { - const app = express(); - app.use(express.json()); - app.use("/api/risk", riskRouter); - return app; + const app = express(); + app.use(express.json()); + app.use("/api/risk", riskRouter); + return app; } const VALID_ADDRESS = "GCKFBEIYV2U22IO2BJ4KVJOIP7XPWQGZBW3JXDC55CYIXB5NAXMCEKJ"; const MOCK_RESULT = { - walletAddress: VALID_ADDRESS, - score: null, - riskLevel: null, - message: "Risk evaluation placeholder — engine not yet integrated.", - evaluatedAt: "2026-02-26T00:00:00.000Z", + walletAddress: VALID_ADDRESS, + score: null, + riskLevel: null, + message: "Risk evaluation placeholder — engine not yet integrated.", + evaluatedAt: "2026-02-26T00:00:00.000Z", }; describe("POST /api/risk/evaluate", () => { - let app: Express; + let app: Express; - beforeEach(() => { - app = buildApp(); - mockEvaluateWallet.mockReset(); - }); + beforeEach(() => { + app = buildApp(); + mockEvaluateWallet.mockReset(); + }); - it("returns 400 when body is empty", async () => { - const res = await request(app) - .post("/api/risk/evaluate") - .set("Content-Type", "application/json") - .send({}); + it("returns 400 when body is empty", async () => { + const res = await request(app) + .post("/api/risk/evaluate") + .set("Content-Type", "application/json") + .send({}); - expect(res.status).toBe(400); - expect(res.body).toEqual({ error: "walletAddress is required" }); - }); + expect(res.status).toBe(400); + expect(res.body).toEqual({ error: "walletAddress is required" }); + }); - it("returns 400 when walletAddress is missing from body", async () => { - const res = await request(app) - .post("/api/risk/evaluate") - .send({ unrelated: "field" }); + it("returns 400 when walletAddress is missing from body", async () => { + const res = await request(app) + .post("/api/risk/evaluate") + .send({ unrelated: "field" }); - expect(res.status).toBe(400); - expect(res.body.error).toContain("walletAddress is required"); - }); + expect(res.status).toBe(400); + expect(res.body.error).toContain("walletAddress is required"); + }); - it("does NOT call evaluateWallet when walletAddress is absent", async () => { - await request(app).post("/api/risk/evaluate").send({}); - expect(mockEvaluateWallet).not.toHaveBeenCalled(); - }); + it("does NOT call evaluateWallet when walletAddress is absent", async () => { + await request(app).post("/api/risk/evaluate").send({}); + expect(mockEvaluateWallet).not.toHaveBeenCalled(); + }); - it("returns 200 with the service result on a valid address", async () => { - mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); + it("returns 200 with the service result on a valid address", async () => { + mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); - const res = await request(app) - .post("/api/risk/evaluate") - .send({ walletAddress: VALID_ADDRESS }); + const res = await request(app) + .post("/api/risk/evaluate") + .send({ walletAddress: VALID_ADDRESS }); - expect(res.status).toBe(200); - expect(res.body).toEqual(MOCK_RESULT); - }); + expect(res.status).toBe(200); + expect(res.body).toEqual(MOCK_RESULT); + }); - it("calls evaluateWallet with the exact walletAddress from the body", async () => { - mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); + it("calls evaluateWallet with the exact walletAddress from the body", async () => { + mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); - await request(app) - .post("/api/risk/evaluate") - .send({ walletAddress: VALID_ADDRESS }); + await request(app) + .post("/api/risk/evaluate") + .send({ walletAddress: VALID_ADDRESS }); - expect(mockEvaluateWallet).toHaveBeenCalledTimes(1); - expect(mockEvaluateWallet).toHaveBeenCalledWith(VALID_ADDRESS); - }); + expect(mockEvaluateWallet).toHaveBeenCalledTimes(1); + expect(mockEvaluateWallet).toHaveBeenCalledWith(VALID_ADDRESS); + }); - it("response body contains all expected fields", async () => { - mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); + it("response body contains all expected fields", async () => { + mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); - const res = await request(app) - .post("/api/risk/evaluate") - .send({ walletAddress: VALID_ADDRESS }); + const res = await request(app) + .post("/api/risk/evaluate") + .send({ walletAddress: VALID_ADDRESS }); - expect(res.body).toHaveProperty("walletAddress"); - expect(res.body).toHaveProperty("score"); - expect(res.body).toHaveProperty("riskLevel"); - expect(res.body).toHaveProperty("message"); - expect(res.body).toHaveProperty("evaluatedAt"); - }); + expect(res.body).toHaveProperty("walletAddress"); + expect(res.body).toHaveProperty("score"); + expect(res.body).toHaveProperty("riskLevel"); + expect(res.body).toHaveProperty("message"); + expect(res.body).toHaveProperty("evaluatedAt"); + }); - it("returns 400 when evaluateWallet throws an Error", async () => { - mockEvaluateWallet.mockRejectedValueOnce( - new Error("Invalid wallet address: \"BAD\""), - ); + it("returns 400 when evaluateWallet throws an Error", async () => { + mockEvaluateWallet.mockRejectedValueOnce( + new Error("Invalid wallet address: \"BAD\""), + ); - const res = await request(app) - .post("/api/risk/evaluate") - .send({ walletAddress: "BAD" }); + const res = await request(app) + .post("/api/risk/evaluate") + .send({ walletAddress: "BAD" }); - expect(res.status).toBe(400); - expect(res.body.error).toContain("Invalid wallet address"); - }); + expect(res.status).toBe(400); + expect(res.body.error).toContain("Invalid wallet address"); + }); - it("returns 400 with the service error message verbatim", async () => { - const errorMsg = 'Invalid wallet address: "TOOLONG". Must start with \'G\''; - mockEvaluateWallet.mockRejectedValueOnce(new Error(errorMsg)); + it("returns 400 with the service error message verbatim", async () => { + const errorMsg = "Invalid wallet address: \"TOOLONG\". Must start with 'G'"; + mockEvaluateWallet.mockRejectedValueOnce(new Error(errorMsg)); - const res = await request(app) - .post("/api/risk/evaluate") - .send({ walletAddress: "TOOLONG" }); + const res = await request(app) + .post("/api/risk/evaluate") + .send({ walletAddress: "TOOLONG" }); - expect(res.body.error).toBe(errorMsg); - }); + expect(res.body.error).toBe(errorMsg); + }); - it("returns 400 with 'Unknown error' when a non-Error is thrown", async () => { - mockEvaluateWallet.mockRejectedValueOnce("raw string throw"); + it("returns 400 with 'Unknown error' when a non-Error is thrown", async () => { + mockEvaluateWallet.mockRejectedValueOnce("raw string throw"); - const res = await request(app) - .post("/api/risk/evaluate") - .send({ walletAddress: VALID_ADDRESS }); + const res = await request(app) + .post("/api/risk/evaluate") + .send({ walletAddress: VALID_ADDRESS }); - expect(res.status).toBe(400); - expect(res.body.error).toBe("Unknown error"); - }); + expect(res.status).toBe(400); + expect(res.body.error).toBe("Unknown error"); + }); - it("returns JSON content-type on success", async () => { - mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); + it("returns JSON content-type on success", async () => { + mockEvaluateWallet.mockResolvedValueOnce(MOCK_RESULT); - const res = await request(app) - .post("/api/risk/evaluate") - .send({ walletAddress: VALID_ADDRESS }); + const res = await request(app) + .post("/api/risk/evaluate") + .send({ walletAddress: VALID_ADDRESS }); - expect(res.headers["content-type"]).toMatch(/application\/json/); - }); + expect(res.headers["content-type"]).toMatch(/application\/json/); + }); - it("returns JSON content-type on 400 error", async () => { - const res = await request(app) - .post("/api/risk/evaluate") - .send({}); + it("returns JSON content-type on 400 error", async () => { + const res = await request(app) + .post("/api/risk/evaluate") + .send({}); - expect(res.headers["content-type"]).toMatch(/application\/json/); - }); + expect(res.headers["content-type"]).toMatch(/application\/json/); + }); }); \ No newline at end of file diff --git a/src/__test__/riskService.test.ts b/src/__test__/riskService.test.ts index 055491c..2f03afc 100644 --- a/src/__test__/riskService.test.ts +++ b/src/__test__/riskService.test.ts @@ -1,10 +1,10 @@ import { - evaluateWallet, - isValidWalletAddress, - scoreToRiskLevel, - type RiskEvaluationResult, - type RiskLevel, + evaluateWallet, + isValidWalletAddress, + scoreToRiskLevel, + type RiskEvaluationResult, + type RiskLevel, } from "../../services/riskService.js"; const VALID_ADDRESS = "GCKFBEIYV2U22IO2BJ4KVJOIP7XPWQGZBW3JXDC55CYIXB5NAXMCEKJ"; @@ -13,49 +13,49 @@ const VALID_ADDRESS_2 = "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN describe("isValidWalletAddress()", () => { - it("returns true for a well-formed Stellar address", () => { - expect(isValidWalletAddress(VALID_ADDRESS)).toBe(true); - }); - - it("returns true for a second valid address", () => { - expect(isValidWalletAddress(VALID_ADDRESS_2)).toBe(true); - }); - - it("returns false for an empty string", () => { - expect(isValidWalletAddress("")).toBe(false); - }); - - it("returns false when address does not start with G", () => { - const bad = "S" + VALID_ADDRESS.slice(1); - expect(isValidWalletAddress(bad)).toBe(false); - }); - - it("returns false when address is too short", () => { - expect(isValidWalletAddress("GSHORT")).toBe(false); - }); - - it("returns false when address is too long", () => { - expect(isValidWalletAddress(VALID_ADDRESS + "X")).toBe(false); - }); - - it("returns false when address contains lowercase letters", () => { - const bad = VALID_ADDRESS.slice(0, -1) + "a"; - expect(isValidWalletAddress(bad)).toBe(false); - }); - - it("returns false when address contains invalid characters (0, 1, 8, 9)", () => { - // Base-32 excludes 0, 1, 8, 9 - const bad = "G" + "0".repeat(55); - expect(isValidWalletAddress(bad)).toBe(false); - }); - - it("returns false for a purely numeric string", () => { - expect(isValidWalletAddress("1234567890")).toBe(false); - }); - - it("returns false for a plausible but one-char-too-short address", () => { - expect(isValidWalletAddress(VALID_ADDRESS.slice(0, 55))).toBe(false); - }); + it("returns true for a well-formed Stellar address", () => { + expect(isValidWalletAddress(VALID_ADDRESS)).toBe(true); + }); + + it("returns true for a second valid address", () => { + expect(isValidWalletAddress(VALID_ADDRESS_2)).toBe(true); + }); + + it("returns false for an empty string", () => { + expect(isValidWalletAddress("")).toBe(false); + }); + + it("returns false when address does not start with G", () => { + const bad = "S" + VALID_ADDRESS.slice(1); + expect(isValidWalletAddress(bad)).toBe(false); + }); + + it("returns false when address is too short", () => { + expect(isValidWalletAddress("GSHORT")).toBe(false); + }); + + it("returns false when address is too long", () => { + expect(isValidWalletAddress(VALID_ADDRESS + "X")).toBe(false); + }); + + it("returns false when address contains lowercase letters", () => { + const bad = VALID_ADDRESS.slice(0, -1) + "a"; + expect(isValidWalletAddress(bad)).toBe(false); + }); + + it("returns false when address contains invalid characters (0, 1, 8, 9)", () => { + // Base-32 excludes 0, 1, 8, 9 + const bad = "G" + "0".repeat(55); + expect(isValidWalletAddress(bad)).toBe(false); + }); + + it("returns false for a purely numeric string", () => { + expect(isValidWalletAddress("1234567890")).toBe(false); + }); + + it("returns false for a plausible but one-char-too-short address", () => { + expect(isValidWalletAddress(VALID_ADDRESS.slice(0, 55))).toBe(false); + }); }); // --------------------------------------------------------------------------- @@ -63,123 +63,123 @@ describe("isValidWalletAddress()", () => { // --------------------------------------------------------------------------- describe("scoreToRiskLevel()", () => { - it("returns 'low' for score 0", () => { - expect(scoreToRiskLevel(0)).toBe("low"); - }); + it("returns 'low' for score 0", () => { + expect(scoreToRiskLevel(0)).toBe("low"); + }); - it("returns 'low' for score 39 (upper boundary of low)", () => { - expect(scoreToRiskLevel(39)).toBe("low"); - }); + it("returns 'low' for score 39 (upper boundary of low)", () => { + expect(scoreToRiskLevel(39)).toBe("low"); + }); - it("returns 'medium' for score 40 (lower boundary of medium)", () => { - expect(scoreToRiskLevel(40)).toBe("medium"); - }); + it("returns 'medium' for score 40 (lower boundary of medium)", () => { + expect(scoreToRiskLevel(40)).toBe("medium"); + }); - it("returns 'medium' for score 55 (midpoint of medium)", () => { - expect(scoreToRiskLevel(55)).toBe("medium"); - }); + it("returns 'medium' for score 55 (midpoint of medium)", () => { + expect(scoreToRiskLevel(55)).toBe("medium"); + }); - it("returns 'medium' for score 69 (upper boundary of medium)", () => { - expect(scoreToRiskLevel(69)).toBe("medium"); - }); + it("returns 'medium' for score 69 (upper boundary of medium)", () => { + expect(scoreToRiskLevel(69)).toBe("medium"); + }); - it("returns 'high' for score 70 (lower boundary of high)", () => { - expect(scoreToRiskLevel(70)).toBe("high"); - }); + it("returns 'high' for score 70 (lower boundary of high)", () => { + expect(scoreToRiskLevel(70)).toBe("high"); + }); - it("returns 'high' for score 100", () => { - expect(scoreToRiskLevel(100)).toBe("high"); - }); + it("returns 'high' for score 100", () => { + expect(scoreToRiskLevel(100)).toBe("high"); + }); }); // --------------------------------------------------------------------------- // evaluateWallet() // --------------------------------------------------------------------------- - describe("evaluateWallet()", () => { - describe("with a valid wallet address", () => { - let result: RiskEvaluationResult; +describe("evaluateWallet()", () => { + describe("with a valid wallet address", () => { + let result: RiskEvaluationResult; - beforeEach(async () => { - result = await evaluateWallet(VALID_ADDRESS); - }); + beforeEach(async () => { + result = await evaluateWallet(VALID_ADDRESS); + }); - it("resolves without throwing", async () => { - await expect(evaluateWallet(VALID_ADDRESS)).resolves.toBeDefined(); - }); + it("resolves without throwing", async () => { + await expect(evaluateWallet(VALID_ADDRESS)).resolves.toBeDefined(); + }); - it("returns the exact walletAddress that was passed in", () => { - expect(result.walletAddress).toBe(VALID_ADDRESS); - }); + it("returns the exact walletAddress that was passed in", () => { + expect(result.walletAddress).toBe(VALID_ADDRESS); + }); - it("returns score as null (placeholder engine)", () => { - expect(result.score).toBeNull(); - }); + it("returns score as null (placeholder engine)", () => { + expect(result.score).toBeNull(); + }); - it("returns riskLevel as null (placeholder engine)", () => { - expect(result.riskLevel).toBeNull(); - }); + it("returns riskLevel as null (placeholder engine)", () => { + expect(result.riskLevel).toBeNull(); + }); - it("returns a non-empty message string", () => { - expect(typeof result.message).toBe("string"); - expect(result.message.length).toBeGreaterThan(0); - }); + it("returns a non-empty message string", () => { + expect(typeof result.message).toBe("string"); + expect(result.message.length).toBeGreaterThan(0); + }); - it("includes 'placeholder' in the message to indicate engine status", () => { - expect(result.message.toLowerCase()).toContain("placeholder"); - }); + it("includes 'placeholder' in the message to indicate engine status", () => { + expect(result.message.toLowerCase()).toContain("placeholder"); + }); - it("returns a valid ISO-8601 evaluatedAt timestamp", () => { - const date = new Date(result.evaluatedAt); - expect(date.getTime()).not.toBeNaN(); - }); + it("returns a valid ISO-8601 evaluatedAt timestamp", () => { + const date = new Date(result.evaluatedAt); + expect(date.getTime()).not.toBeNaN(); + }); - it("returns an evaluatedAt timestamp close to the current time", () => { - const diff = Date.now() - new Date(result.evaluatedAt).getTime(); - // Should be within 5 seconds of now - expect(diff).toBeGreaterThanOrEqual(0); - expect(diff).toBeLessThan(5000); - }); + it("returns an evaluatedAt timestamp close to the current time", () => { + const diff = Date.now() - new Date(result.evaluatedAt).getTime(); + // Should be within 5 seconds of now + expect(diff).toBeGreaterThanOrEqual(0); + expect(diff).toBeLessThan(5000); + }); - it("result has exactly the expected shape (no extra fields)", () => { - const keys = Object.keys(result).sort(); - expect(keys).toEqual( - ["evaluatedAt", "message", "riskLevel", "score", "walletAddress"].sort(), - ); - }); + it("result has exactly the expected shape (no extra fields)", () => { + const keys = Object.keys(result).sort(); + expect(keys).toEqual( + ["evaluatedAt", "message", "riskLevel", "score", "walletAddress"].sort(), + ); }); + }); - describe("with a second valid address", () => { - it("reflects the correct walletAddress in the result", async () => { - const result = await evaluateWallet(VALID_ADDRESS_2); - expect(result.walletAddress).toBe(VALID_ADDRESS_2); - }); + describe("with a second valid address", () => { + it("reflects the correct walletAddress in the result", async () => { + const result = await evaluateWallet(VALID_ADDRESS_2); + expect(result.walletAddress).toBe(VALID_ADDRESS_2); }); + }); - describe("with an invalid wallet address", () => { - it("throws an Error for an empty string", async () => { - await expect(evaluateWallet("")).rejects.toThrow(Error); - }); + describe("with an invalid wallet address", () => { + it("throws an Error for an empty string", async () => { + await expect(evaluateWallet("")).rejects.toThrow(Error); + }); - it("throws an error containing the invalid address in the message", async () => { - await expect(evaluateWallet("INVALID")).rejects.toThrow("INVALID"); - }); + it("throws an error containing the invalid address in the message", async () => { + await expect(evaluateWallet("INVALID")).rejects.toThrow("INVALID"); + }); - it("throws for an address that does not start with G", async () => { - const bad = "S" + VALID_ADDRESS.slice(1); - await expect(evaluateWallet(bad)).rejects.toThrow(Error); - }); + it("throws for an address that does not start with G", async () => { + const bad = "S" + VALID_ADDRESS.slice(1); + await expect(evaluateWallet(bad)).rejects.toThrow(Error); + }); - it("throws for an address that is too short", async () => { - await expect(evaluateWallet("GSHORT")).rejects.toThrow(Error); - }); + it("throws for an address that is too short", async () => { + await expect(evaluateWallet("GSHORT")).rejects.toThrow(Error); + }); - it("throws for an address that is too long", async () => { - await expect(evaluateWallet(VALID_ADDRESS + "X")).rejects.toThrow(Error); - }); + it("throws for an address that is too long", async () => { + await expect(evaluateWallet(VALID_ADDRESS + "X")).rejects.toThrow(Error); + }); - it("error message hints at the correct format", async () => { - await expect(evaluateWallet("BAD")).rejects.toThrow(/56/); - }); + it("error message hints at the correct format", async () => { + await expect(evaluateWallet("BAD")).rejects.toThrow(/56/); }); + }); }); \ No newline at end of file diff --git a/src/db/client.test.ts b/src/db/client.test.ts index c7e2812..6bf3855 100644 --- a/src/db/client.test.ts +++ b/src/db/client.test.ts @@ -1,7 +1,7 @@ -import { describe, it, expect, beforeEach, afterEach } from 'vitest'; -import { getConnection } from './client.js'; +import { describe, it, expect, beforeEach, afterEach } from "vitest"; +import { getConnection } from "./client.js"; -describe('getConnection', () => { +describe("getConnection", () => { const orig = process.env.DATABASE_URL; beforeEach(() => { @@ -12,12 +12,12 @@ describe('getConnection', () => { if (orig !== undefined) process.env.DATABASE_URL = orig; }); - it('throws when DATABASE_URL is not set', () => { - expect(() => getConnection()).toThrow('DATABASE_URL is required'); + it("throws when DATABASE_URL is not set", () => { + expect(() => getConnection()).toThrow("DATABASE_URL is required"); }); - it('throws when DATABASE_URL is empty string', () => { - process.env.DATABASE_URL = ''; - expect(() => getConnection()).toThrow('DATABASE_URL is required'); + it("throws when DATABASE_URL is empty string", () => { + process.env.DATABASE_URL = ""; + expect(() => getConnection()).toThrow("DATABASE_URL is required"); }); }); diff --git a/src/db/client.ts b/src/db/client.ts index a47e561..766032b 100644 --- a/src/db/client.ts +++ b/src/db/client.ts @@ -1,4 +1,4 @@ -import { createRequire } from 'module'; +import { createRequire } from "module"; /** * Database client interface for migrations and validation. @@ -15,9 +15,9 @@ const require = createRequire(import.meta.url); export function getConnection(): DbClient { const url = process.env.DATABASE_URL; if (!url) { - throw new Error('DATABASE_URL is required'); + throw new Error("DATABASE_URL is required"); } - const pg = require('pg') as { + const pg = require("pg") as { Client: new (opts: { connectionString: string }) => DbClient; }; return new pg.Client({ connectionString: url }); diff --git a/src/db/migrate-cli.ts b/src/db/migrate-cli.ts index 8c8d99b..fb6a261 100644 --- a/src/db/migrate-cli.ts +++ b/src/db/migrate-cli.ts @@ -3,31 +3,31 @@ * CLI: apply pending migrations. * Usage: DATABASE_URL=... node --import tsx src/db/migrate-cli.ts */ -import { join } from 'path'; -import { getConnection } from './client.js'; -import { runPendingMigrations } from './migrations.js'; +import { join } from "path"; +import { getConnection } from "./client.js"; +import { runPendingMigrations } from "./migrations.js"; -const MIGRATIONS_DIR = join(process.cwd(), 'migrations'); +const MIGRATIONS_DIR = join(process.cwd(), "migrations"); async function main(): Promise { const client = getConnection(); try { if (client.connect) await client.connect(); - await client.query('SELECT 1'); + await client.query("SELECT 1"); } catch (e) { - console.error('Cannot connect to database. Set DATABASE_URL.'); + console.error("Cannot connect to database. Set DATABASE_URL."); process.exitCode = 1; return; } try { const run = await runPendingMigrations(client, MIGRATIONS_DIR); if (run.length === 0) { - console.log('No pending migrations.'); + console.log("No pending migrations."); } else { - console.log('Applied migrations:', run.join(', ')); + console.log("Applied migrations:", run.join(", ")); } } catch (err) { - console.error('Migration failed:', err); + console.error("Migration failed:", err); process.exitCode = 1; } finally { await client.end(); diff --git a/src/db/migrations.test.ts b/src/db/migrations.test.ts index a77bafb..e633ddb 100644 --- a/src/db/migrations.test.ts +++ b/src/db/migrations.test.ts @@ -1,5 +1,5 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import type { DbClient } from './client.js'; +import { describe, it, expect, vi } from "vitest"; +import type { DbClient } from "./client.js"; import { ensureSchemaMigrations, listMigrationFiles, @@ -8,7 +8,7 @@ import { applyMigration, runPendingMigrations, EXPECTED_TABLES, -} from './migrations.js'; +} from "./migrations.js"; function createMockClient(overrides: Partial = {}): DbClient { return { @@ -18,40 +18,40 @@ function createMockClient(overrides: Partial = {}): DbClient { }; } -describe('versionFromFilename', () => { - it('strips .sql extension', () => { - expect(versionFromFilename('001_initial_schema.sql')).toBe('001_initial_schema'); +describe("versionFromFilename", () => { + it("strips .sql extension", () => { + expect(versionFromFilename("001_initial_schema.sql")).toBe("001_initial_schema"); }); - it('returns full name if no .sql', () => { - expect(versionFromFilename('001_initial_schema')).toBe('001_initial_schema'); + it("returns full name if no .sql", () => { + expect(versionFromFilename("001_initial_schema")).toBe("001_initial_schema"); }); }); -describe('ensureSchemaMigrations', () => { - it('runs CREATE TABLE IF NOT EXISTS for schema_migrations', async () => { +describe("ensureSchemaMigrations", () => { + it("runs CREATE TABLE IF NOT EXISTS for schema_migrations", async () => { const client = createMockClient(); await ensureSchemaMigrations(client); expect(client.query).toHaveBeenCalledWith( - expect.stringContaining('CREATE TABLE IF NOT EXISTS schema_migrations') + expect.stringContaining("CREATE TABLE IF NOT EXISTS schema_migrations"), ); }); }); -describe('getAppliedVersions', () => { - it('ensures schema_migrations then returns version list', async () => { +describe("getAppliedVersions", () => { + it("ensures schema_migrations then returns version list", async () => { const client = createMockClient(); vi.mocked(client.query) .mockResolvedValueOnce({ rows: [] }) .mockResolvedValueOnce({ - rows: [{ version: '001_initial_schema' }], + rows: [{ version: "001_initial_schema" }], }); const versions = await getAppliedVersions(client); - expect(versions).toEqual(['001_initial_schema']); + expect(versions).toEqual(["001_initial_schema"]); expect(client.query).toHaveBeenCalledTimes(2); }); - it('returns empty array when no migrations applied', async () => { + it("returns empty array when no migrations applied", async () => { const client = createMockClient(); vi.mocked(client.query) .mockResolvedValueOnce({ rows: [] }) @@ -61,69 +61,69 @@ describe('getAppliedVersions', () => { }); }); -describe('listMigrationFiles', () => { - it('returns sorted .sql files from directory', async () => { - const { join } = await import('path'); - const dir = join(process.cwd(), 'migrations'); +describe("listMigrationFiles", () => { + it("returns sorted .sql files from directory", async () => { + const { join } = await import("path"); + const dir = join(process.cwd(), "migrations"); const files = await listMigrationFiles(dir); expect(files.length).toBeGreaterThanOrEqual(1); - expect(files).toContain('001_initial_schema.sql'); - expect(files.every((f) => f.endsWith('.sql'))).toBe(true); + expect(files).toContain("001_initial_schema.sql"); + expect(files.every((f) => f.endsWith(".sql"))).toBe(true); expect(files).toEqual([...files].sort()); }); }); -describe('applyMigration', () => { - it('reads file, runs SQL, then records version', async () => { +describe("applyMigration", () => { + it("reads file, runs SQL, then records version", async () => { const client = createMockClient(); - const migrationsDir = await import('path').then((p) => - p.join(process.cwd(), 'migrations') + const migrationsDir = await import("path").then((p) => + p.join(process.cwd(), "migrations"), ); - await applyMigration(client, migrationsDir, '001_initial_schema.sql'); + await applyMigration(client, migrationsDir, "001_initial_schema.sql"); expect(client.query).toHaveBeenCalled(); const insertCall = vi.mocked(client.query).mock.calls.find( - (c) => typeof c[0] === 'string' && c[0].includes('INSERT INTO schema_migrations') + (c) => typeof c[0] === "string" && c[0].includes("INSERT INTO schema_migrations"), ); expect(insertCall).toBeDefined(); - expect(insertCall![1]).toEqual(['001_initial_schema']); + expect(insertCall![1]).toEqual(["001_initial_schema"]); }); }); -describe('runPendingMigrations', () => { - it('skips already applied migrations', async () => { +describe("runPendingMigrations", () => { + it("skips already applied migrations", async () => { const client = createMockClient(); vi.mocked(client.query) .mockResolvedValueOnce({ rows: [] }) - .mockResolvedValueOnce({ rows: [{ version: '001_initial_schema' }] }); - const migrationsDir = await import('path').then((p) => - p.join(process.cwd(), 'migrations') + .mockResolvedValueOnce({ rows: [{ version: "001_initial_schema" }] }); + const migrationsDir = await import("path").then((p) => + p.join(process.cwd(), "migrations"), ); const run = await runPendingMigrations(client, migrationsDir); expect(run).toEqual([]); }); - it('applies pending migration and returns its version', async () => { + it("applies pending migration and returns its version", async () => { const client = createMockClient(); vi.mocked(client.query) .mockResolvedValueOnce({ rows: [] }) .mockResolvedValueOnce({ rows: [] }); - const migrationsDir = await import('path').then((p) => - p.join(process.cwd(), 'migrations') + const migrationsDir = await import("path").then((p) => + p.join(process.cwd(), "migrations"), ); const run = await runPendingMigrations(client, migrationsDir); - expect(run).toContain('001_initial_schema'); + expect(run).toContain("001_initial_schema"); expect(run.length).toBeGreaterThanOrEqual(1); }); }); -describe('EXPECTED_TABLES', () => { - it('includes all core domain tables', () => { +describe("EXPECTED_TABLES", () => { + it("includes all core domain tables", () => { expect(EXPECTED_TABLES).toEqual([ - 'borrowers', - 'credit_lines', - 'risk_evaluations', - 'transactions', - 'events', + "borrowers", + "credit_lines", + "risk_evaluations", + "transactions", + "events", ]); }); }); diff --git a/src/db/migrations.ts b/src/db/migrations.ts index d5ceb6a..9eecab5 100644 --- a/src/db/migrations.ts +++ b/src/db/migrations.ts @@ -1,6 +1,6 @@ -import { readdir, readFile } from 'fs/promises'; -import { join } from 'path'; -import type { DbClient } from './client.js'; +import { readdir, readFile } from "fs/promises"; +import { join } from "path"; +import type { DbClient } from "./client.js"; const SCHEMA_MIGRATIONS_TABLE = ` CREATE TABLE IF NOT EXISTS schema_migrations ( @@ -11,11 +11,11 @@ CREATE TABLE IF NOT EXISTS schema_migrations ( /** Expected core tables that must exist after initial schema. */ export const EXPECTED_TABLES = [ - 'borrowers', - 'credit_lines', - 'risk_evaluations', - 'transactions', - 'events', + "borrowers", + "credit_lines", + "risk_evaluations", + "transactions", + "events", ] as const; /** @@ -31,7 +31,7 @@ export async function ensureSchemaMigrations(client: DbClient): Promise { export async function listMigrationFiles(dir: string): Promise { const entries = await readdir(dir, { withFileTypes: true }); const files = entries - .filter((e) => e.isFile() && e.name.endsWith('.sql')) + .filter((e) => e.isFile() && e.name.endsWith(".sql")) .map((e) => e.name) .sort(); return files; @@ -41,7 +41,7 @@ export async function listMigrationFiles(dir: string): Promise { * Extract version string from migration filename (e.g. 001_initial_schema.sql -> 001_initial_schema). */ export function versionFromFilename(filename: string): string { - if (!filename.endsWith('.sql')) return filename; + if (!filename.endsWith(".sql")) return filename; return filename.slice(0, -4); } @@ -51,7 +51,7 @@ export function versionFromFilename(filename: string): string { export async function getAppliedVersions(client: DbClient): Promise { await ensureSchemaMigrations(client); const result = await client.query( - 'SELECT version FROM schema_migrations ORDER BY version' + "SELECT version FROM schema_migrations ORDER BY version", ); const rows = result.rows as { version: string }[]; return rows.map((r) => r.version); @@ -63,15 +63,15 @@ export async function getAppliedVersions(client: DbClient): Promise { export async function applyMigration( client: DbClient, migrationsDir: string, - filename: string + filename: string, ): Promise { const path = join(migrationsDir, filename); - const sql = await readFile(path, 'utf-8'); + const sql = await readFile(path, "utf-8"); await client.query(sql); const version = versionFromFilename(filename); await client.query( - 'INSERT INTO schema_migrations (version, applied_at) VALUES ($1, now()) ON CONFLICT (version) DO NOTHING', - [version] + "INSERT INTO schema_migrations (version, applied_at) VALUES ($1, now()) ON CONFLICT (version) DO NOTHING", + [version], ); } @@ -81,7 +81,7 @@ export async function applyMigration( */ export async function runPendingMigrations( client: DbClient, - migrationsDir: string + migrationsDir: string, ): Promise { const applied = await getAppliedVersions(client); const files = await listMigrationFiles(migrationsDir); diff --git a/src/db/validate-cli.ts b/src/db/validate-cli.ts index 74c335f..df6da3e 100644 --- a/src/db/validate-cli.ts +++ b/src/db/validate-cli.ts @@ -3,32 +3,32 @@ * CLI: run pending migrations then validate that core tables exist. * Usage: DATABASE_URL=... node --import tsx src/db/validate-cli.ts */ -import { join } from 'path'; -import { getConnection } from './client.js'; -import { runPendingMigrations } from './migrations.js'; -import { validateSchema } from './validate-schema.js'; +import { join } from "path"; +import { getConnection } from "./client.js"; +import { runPendingMigrations } from "./migrations.js"; +import { validateSchema } from "./validate-schema.js"; -const MIGRATIONS_DIR = join(process.cwd(), 'migrations'); +const MIGRATIONS_DIR = join(process.cwd(), "migrations"); async function main(): Promise { const client = getConnection(); try { if (client.connect) await client.connect(); - await client.query('SELECT 1'); + await client.query("SELECT 1"); } catch { - console.error('Cannot connect to database. Set DATABASE_URL.'); + console.error("Cannot connect to database. Set DATABASE_URL."); process.exitCode = 1; return; } try { const run = await runPendingMigrations(client, MIGRATIONS_DIR); if (run.length > 0) { - console.log('Applied migrations:', run.join(', ')); + console.log("Applied migrations:", run.join(", ")); } await validateSchema(client); - console.log('Schema validation passed.'); + console.log("Schema validation passed."); } catch (err) { - console.error('Validation failed:', err); + console.error("Validation failed:", err); process.exitCode = 1; } finally { await client.end(); diff --git a/src/db/validate-schema.test.ts b/src/db/validate-schema.test.ts index bc81990..a01f465 100644 --- a/src/db/validate-schema.test.ts +++ b/src/db/validate-schema.test.ts @@ -1,6 +1,6 @@ -import { describe, it, expect, vi } from 'vitest'; -import type { DbClient } from './client.js'; -import { missingTables, validateSchema } from './validate-schema.js'; +import { describe, it, expect, vi } from "vitest"; +import type { DbClient } from "./client.js"; +import { missingTables, validateSchema } from "./validate-schema.js"; function createMockClient(overrides: Partial = {}): DbClient { return { @@ -10,74 +10,74 @@ function createMockClient(overrides: Partial = {}): DbClient { }; } -describe('missingTables', () => { - it('returns empty when all tables exist', async () => { +describe("missingTables", () => { + it("returns empty when all tables exist", async () => { const client = createMockClient(); vi.mocked(client.query).mockResolvedValue({ rows: [ - { table_name: 'borrowers' }, - { table_name: 'credit_lines' }, - { table_name: 'risk_evaluations' }, - { table_name: 'transactions' }, - { table_name: 'events' }, + { table_name: "borrowers" }, + { table_name: "credit_lines" }, + { table_name: "risk_evaluations" }, + { table_name: "transactions" }, + { table_name: "events" }, ], }); const missing = await missingTables(client); expect(missing).toEqual([]); }); - it('returns missing table names', async () => { + it("returns missing table names", async () => { const client = createMockClient(); vi.mocked(client.query).mockResolvedValue({ - rows: [{ table_name: 'borrowers' }, { table_name: 'events' }], + rows: [{ table_name: "borrowers" }, { table_name: "events" }], }); const missing = await missingTables(client, [ - 'borrowers', - 'credit_lines', - 'events', + "borrowers", + "credit_lines", + "events", ]); - expect(missing).toEqual(['credit_lines']); + expect(missing).toEqual(["credit_lines"]); }); - it('returns all when none exist', async () => { + it("returns all when none exist", async () => { const client = createMockClient(); vi.mocked(client.query).mockResolvedValue({ rows: [] }); - const missing = await missingTables(client, ['borrowers', 'events']); - expect(missing).toEqual(['borrowers', 'events']); + const missing = await missingTables(client, ["borrowers", "events"]); + expect(missing).toEqual(["borrowers", "events"]); }); - it('uses default EXPECTED_TABLES when no list given', async () => { + it("uses default EXPECTED_TABLES when no list given", async () => { const client = createMockClient(); vi.mocked(client.query).mockResolvedValue({ - rows: [{ table_name: 'borrowers' }], + rows: [{ table_name: "borrowers" }], }); const missing = await missingTables(client); expect(missing.length).toBeGreaterThan(0); - expect(missing).toContain('credit_lines'); + expect(missing).toContain("credit_lines"); }); }); -describe('validateSchema', () => { - it('does not throw when all expected tables exist', async () => { +describe("validateSchema", () => { + it("does not throw when all expected tables exist", async () => { const client = createMockClient(); vi.mocked(client.query).mockResolvedValue({ rows: [ - { table_name: 'borrowers' }, - { table_name: 'credit_lines' }, - { table_name: 'risk_evaluations' }, - { table_name: 'transactions' }, - { table_name: 'events' }, + { table_name: "borrowers" }, + { table_name: "credit_lines" }, + { table_name: "risk_evaluations" }, + { table_name: "transactions" }, + { table_name: "events" }, ], }); await expect(validateSchema(client)).resolves.toBeUndefined(); }); - it('throws when any table is missing', async () => { + it("throws when any table is missing", async () => { const client = createMockClient(); vi.mocked(client.query).mockResolvedValue({ - rows: [{ table_name: 'borrowers' }], + rows: [{ table_name: "borrowers" }], }); - await expect(validateSchema(client)).rejects.toThrow('Missing tables:'); - await expect(validateSchema(client)).rejects.toThrow('credit_lines'); + await expect(validateSchema(client)).rejects.toThrow("Missing tables:"); + await expect(validateSchema(client)).rejects.toThrow("credit_lines"); }); }); diff --git a/src/db/validate-schema.ts b/src/db/validate-schema.ts index 7c90b7d..0e5d140 100644 --- a/src/db/validate-schema.ts +++ b/src/db/validate-schema.ts @@ -1,5 +1,5 @@ -import type { DbClient } from './client.js'; -import { EXPECTED_TABLES } from './migrations.js'; +import type { DbClient } from "./client.js"; +import { EXPECTED_TABLES } from "./migrations.js"; /** * Check that the given tables exist in the current schema (public). @@ -7,16 +7,16 @@ import { EXPECTED_TABLES } from './migrations.js'; */ export async function missingTables( client: DbClient, - tables: readonly string[] = EXPECTED_TABLES + tables: readonly string[] = EXPECTED_TABLES, ): Promise { - const placeholders = tables.map((_, i) => `$${i + 1}`).join(', '); + const placeholders = tables.map((_, i) => `$${i + 1}`).join(", "); const result = await client.query( `SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name IN (${placeholders})`, - [...tables] + [...tables], ); const found = (result.rows as { table_name: string }[]).map( - (r) => r.table_name + (r) => r.table_name, ); const foundSet = new Set(found); return tables.filter((t) => !foundSet.has(t)); @@ -29,6 +29,6 @@ export async function missingTables( export async function validateSchema(client: DbClient): Promise { const missing = await missingTables(client); if (missing.length > 0) { - throw new Error(`Missing tables: ${missing.join(', ')}`); + throw new Error(`Missing tables: ${missing.join(", ")}`); } } diff --git a/src/index.ts b/src/index.ts index c0b0571..2802f16 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +<<<<<<< HEAD import express from 'express'; import cors from 'cors'; import { readFileSync } from 'fs'; @@ -14,6 +15,12 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); const openapiSpec = yaml.parse( readFileSync(join(__dirname, 'openapi.yaml'), 'utf8') ); +======= +import express from "express"; +import cors from "cors"; +import { creditRouter } from "./routes/credit.js"; +import { riskRouter } from "./routes/risk.js"; +>>>>>>> b7964ce (prep) const app = express(); export const app = express(); @@ -22,6 +29,7 @@ const port = process.env.PORT ?? 3000; app.use(cors()); app.use(express.json()); +<<<<<<< HEAD // ── Docs ──────────────────────────────────────────────────────────────────── app.use('/docs', swaggerUi.serve, swaggerUi.setup(openapiSpec)); app.get('/docs.json', (_req, res) => res.json(openapiSpec)); @@ -29,10 +37,14 @@ app.get('/docs.json', (_req, res) => res.json(openapiSpec)); // ── Routes ─────────────────────────────────────────────────────────────────── app.get('/health', (_req, res) => { ok(res, { status: 'ok', service: 'creditra-backend' }); +======= +app.get("/health", (_req, res) => { + res.json({ status: "ok", service: "creditra-backend" }); +>>>>>>> b7964ce (prep) }); -app.use('/api/credit', creditRouter); -app.use('/api/risk', riskRouter); +app.use("/api/credit", creditRouter); +app.use("/api/risk", riskRouter); app.listen(port, () => { console.log(`Creditra API listening on http://localhost:${port}`); diff --git a/src/middleware/adminAuth.ts b/src/middleware/adminAuth.ts index 1746e7a..0972d26 100644 --- a/src/middleware/adminAuth.ts +++ b/src/middleware/adminAuth.ts @@ -3,27 +3,27 @@ import { Request, Response, NextFunction } from "express"; export const ADMIN_KEY_HEADER = "x-admin-api-key" as const; export function adminAuth( - req: Request, - res: Response, - next: NextFunction, - ): void { - const expectedKey = process.env["ADMIN_API_KEY"]; + req: Request, + res: Response, + next: NextFunction, +): void { + const expectedKey = process.env.ADMIN_API_KEY; - if (!expectedKey) { - res.status(503).json({ - error: "Admin authentication is not configured on this server.", - }); - return; - } + if (!expectedKey) { + res.status(503).json({ + error: "Admin authentication is not configured on this server.", + }); + return; + } - const providedKey = req.headers[ADMIN_KEY_HEADER]; + const providedKey = req.headers[ADMIN_KEY_HEADER]; - if (!providedKey || providedKey !== expectedKey) { - res.status(401).json({ - error: "Unauthorized: valid X-Admin-Api-Key header is required.", - }); - return; - } + if (!providedKey || providedKey !== expectedKey) { + res.status(401).json({ + error: "Unauthorized: valid X-Admin-Api-Key header is required.", + }); + return; + } - next(); + next(); } \ No newline at end of file diff --git a/src/routes/credit.ts b/src/routes/credit.ts index 1bb3bff..7a49919 100644 --- a/src/routes/credit.ts +++ b/src/routes/credit.ts @@ -28,10 +28,18 @@ creditRouter.get("/lines", (_req: Request, res: Response): void => { ok(res, listCreditLines()); }); +<<<<<<< HEAD creditRouter.get("/lines/:id", (req: Request, res: Response): void => { const line = getCreditLine(req.params["id"] as string); if (!line) { fail(res, `Credit line "${req.params["id"]}" not found.`, 404); +======= + +router.get("/lines/:id", (req: Request, res: Response): void => { + const line = getCreditLine(req.params.id as string); + if (!line) { + res.status(404).json({ error: `Credit line "${req.params.id}" not found.` }); +>>>>>>> b7964ce (prep) return; } ok(res, line); @@ -42,8 +50,13 @@ creditRouter.post( adminAuth, async (req: Request, res: Response): Promise => { try { +<<<<<<< HEAD const line = suspendCreditLine(req.params["id"] as string); ok(res, { line, message: "Credit line suspended." }); +======= + const line = suspendCreditLine(req.params.id as string); + res.json({ data: line, message: "Credit line suspended." }); +>>>>>>> b7964ce (prep) } catch (err) { handleServiceError(err, res); } @@ -55,8 +68,13 @@ creditRouter.post( adminAuth, async (req: Request, res: Response): Promise => { try { +<<<<<<< HEAD const line = closeCreditLine(req.params["id"] as string); ok(res, { line, message: "Credit line closed." }); +======= + const line = closeCreditLine(req.params.id as string); + res.json({ data: line, message: "Credit line closed." }); +>>>>>>> b7964ce (prep) } catch (err) { handleServiceError(err, res); } diff --git a/src/services/creditService.ts b/src/services/creditService.ts index 11eb703..7b8499e 100644 --- a/src/services/creditService.ts +++ b/src/services/creditService.ts @@ -2,100 +2,100 @@ export type CreditLineStatus = "active" | "suspended" | "closed"; export interface CreditLineEvent { - action: "created" | "suspended" | "closed"; - timestamp: string; - actor?: string; + action: "created" | "suspended" | "closed"; + timestamp: string; + actor?: string; } export interface CreditLine { - id: string; - status: CreditLineStatus; - createdAt: string; - updatedAt: string; - events: CreditLineEvent[]; + id: string; + status: CreditLineStatus; + createdAt: string; + updatedAt: string; + events: CreditLineEvent[]; } export class InvalidTransitionError extends Error { - constructor( - public readonly currentStatus: CreditLineStatus, - public readonly requestedAction: string, - ) { - super( - `Cannot "${requestedAction}" a credit line that is already "${currentStatus}".`, - ); - this.name = "InvalidTransitionError"; - } + constructor( + public readonly currentStatus: CreditLineStatus, + public readonly requestedAction: string, + ) { + super( + `Cannot "${requestedAction}" a credit line that is already "${currentStatus}".`, + ); + this.name = "InvalidTransitionError"; + } } export class CreditLineNotFoundError extends Error { - constructor(public readonly id: string) { - super(`Credit line "${id}" not found.`); - this.name = "CreditLineNotFoundError"; - } + constructor(public readonly id: string) { + super(`Credit line "${id}" not found.`); + this.name = "CreditLineNotFoundError"; + } } export const _store = new Map(); export function _resetStore(): void { - _store.clear(); + _store.clear(); } function now(): string { - return new Date().toISOString(); + return new Date().toISOString(); } export function createCreditLine( - id: string, - status: CreditLineStatus = "active", - ): CreditLine { - const ts = now(); - const line: CreditLine = { - id, - status, - createdAt: ts, - updatedAt: ts, - events: [{ action: "created", timestamp: ts }], - }; - _store.set(id, line); - return line; + id: string, + status: CreditLineStatus = "active", +): CreditLine { + const ts = now(); + const line: CreditLine = { + id, + status, + createdAt: ts, + updatedAt: ts, + events: [{ action: "created", timestamp: ts }], + }; + _store.set(id, line); + return line; } export function getCreditLine(id: string): CreditLine | undefined { - return _store.get(id); + return _store.get(id); } export function listCreditLines(): CreditLine[] { - return Array.from(_store.values()); + return Array.from(_store.values()); } export function suspendCreditLine(id: string): CreditLine { - const line = _store.get(id); - if (!line) throw new CreditLineNotFoundError(id); + const line = _store.get(id); + if (!line) throw new CreditLineNotFoundError(id); - if (line.status !== "active") { - throw new InvalidTransitionError(line.status, "suspend"); - } + if (line.status !== "active") { + throw new InvalidTransitionError(line.status, "suspend"); + } - const ts = now(); - line.status = "suspended"; - line.updatedAt = ts; - line.events.push({ action: "suspended", timestamp: ts }); + const ts = now(); + line.status = "suspended"; + line.updatedAt = ts; + line.events.push({ action: "suspended", timestamp: ts }); - return line; + return line; } export function closeCreditLine(id: string): CreditLine { - const line = _store.get(id); - if (!line) throw new CreditLineNotFoundError(id); + const line = _store.get(id); + if (!line) throw new CreditLineNotFoundError(id); - if (line.status === "closed") { - throw new InvalidTransitionError(line.status, "close"); - } + if (line.status === "closed") { + throw new InvalidTransitionError(line.status, "close"); + } - const ts = now(); - line.status = "closed"; - line.updatedAt = ts; - line.events.push({ action: "closed", timestamp: ts }); + const ts = now(); + line.status = "closed"; + line.updatedAt = ts; + line.events.push({ action: "closed", timestamp: ts }); - return line; + return line; } \ No newline at end of file diff --git a/src/services/horizonListener.ts b/src/services/horizonListener.ts index 22a36ff..1fe0f1f 100644 --- a/src/services/horizonListener.ts +++ b/src/services/horizonListener.ts @@ -4,26 +4,26 @@ // --------------------------------------------------------------------------- export interface HorizonEvent { - /** Ledger sequence number in which the event was recorded. */ - ledger: number; - /** ISO-8601 timestamp of the ledger close. */ - timestamp: string; - /** The Soroban contract ID that emitted this event. */ - contractId: string; - /** Decoded event topic array (stringified for the skeleton). */ - topics: string[]; - /** Decoded event data payload (stringified for the skeleton). */ - data: string; + /** Ledger sequence number in which the event was recorded. */ + ledger: number; + /** ISO-8601 timestamp of the ledger close. */ + timestamp: string; + /** The Soroban contract ID that emitted this event. */ + contractId: string; + /** Decoded event topic array (stringified for the skeleton). */ + topics: string[]; + /** Decoded event data payload (stringified for the skeleton). */ + data: string; } export type EventHandler = (event: HorizonEvent) => void | Promise; export interface HorizonListenerConfig { - horizonUrl: string; - contractIds: string[]; - pollIntervalMs: number; - startLedger: string; + horizonUrl: string; + contractIds: string[]; + pollIntervalMs: number; + startLedger: string; } // --------------------------------------------------------------------------- @@ -47,22 +47,22 @@ let activeConfig: HorizonListenerConfig | null = null; // --------------------------------------------------------------------------- export function resolveConfig(): HorizonListenerConfig { - const horizonUrl = - process.env["HORIZON_URL"] ?? "https://horizon-testnet.stellar.org"; + const horizonUrl = + process.env.HORIZON_URL ?? "https://horizon-testnet.stellar.org"; - const contractIdsRaw = process.env["CONTRACT_IDS"] ?? ""; - const contractIds = contractIdsRaw - ? contractIdsRaw.split(",").map((id) => id.trim()).filter(Boolean) - : []; + const contractIdsRaw = process.env.CONTRACT_IDS ?? ""; + const contractIds = contractIdsRaw + ? contractIdsRaw.split(",").map((id) => id.trim()).filter(Boolean) + : []; - const pollIntervalMs = parseInt( - process.env["POLL_INTERVAL_MS"] ?? "5000", - 10, - ); + const pollIntervalMs = parseInt( + process.env.POLL_INTERVAL_MS ?? "5000", + 10, + ); - const startLedger = process.env["HORIZON_START_LEDGER"] ?? "latest"; + const startLedger = process.env.HORIZON_START_LEDGER ?? "latest"; - return { horizonUrl, contractIds, pollIntervalMs, startLedger }; + return { horizonUrl, contractIds, pollIntervalMs, startLedger }; } // --------------------------------------------------------------------------- @@ -70,25 +70,25 @@ export function resolveConfig(): HorizonListenerConfig { // --------------------------------------------------------------------------- export function onEvent(handler: EventHandler): void { - eventHandlers.push(handler); + eventHandlers.push(handler); } export function clearEventHandlers(): void { - eventHandlers.length = 0; + eventHandlers.length = 0; } async function dispatchEvent(event: HorizonEvent): Promise { - for (const handler of eventHandlers) { - try { - await handler(event); - } catch (err) { - console.error( - "[HorizonListener] Event handler threw an error:", - err, - ); - } + for (const handler of eventHandlers) { + try { + await handler(event); + } catch (err) { + console.error( + "[HorizonListener] Event handler threw an error:", + err, + ); } + } } // --------------------------------------------------------------------------- @@ -97,28 +97,28 @@ async function dispatchEvent(event: HorizonEvent): Promise { export async function pollOnce(config: HorizonListenerConfig): Promise { - console.log( - `[HorizonListener] Polling ${config.horizonUrl} ` + + console.log( + `[HorizonListener] Polling ${config.horizonUrl} ` + `(contracts: ${config.contractIds.length > 0 ? config.contractIds.join(", ") : "none"}, ` + `startLedger: ${config.startLedger})`, + ); + + if (config.contractIds.length > 0) { + const simulatedEvent: HorizonEvent = { + ledger: 1000, + timestamp: new Date().toISOString(), + contractId: config.contractIds[0]!, + topics: ["credit_line_created"], + data: JSON.stringify({ walletAddress: "GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }), + }; + + console.log( + "[HorizonListener] Simulated event received:", + JSON.stringify(simulatedEvent), ); - if (config.contractIds.length > 0) { - const simulatedEvent: HorizonEvent = { - ledger: 1000, - timestamp: new Date().toISOString(), - contractId: config.contractIds[0]!, - topics: ["credit_line_created"], - data: JSON.stringify({ walletAddress: "GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }), - }; - - console.log( - "[HorizonListener] Simulated event received:", - JSON.stringify(simulatedEvent), - ); - - await dispatchEvent(simulatedEvent); - } + await dispatchEvent(simulatedEvent); + } } // --------------------------------------------------------------------------- @@ -126,54 +126,54 @@ export async function pollOnce(config: HorizonListenerConfig): Promise { // --------------------------------------------------------------------------- export function isRunning(): boolean { - return running; + return running; } export function getConfig(): HorizonListenerConfig | null { - return activeConfig; + return activeConfig; } export async function start(): Promise { - if (running) { - console.warn("[HorizonListener] Already running — ignoring start() call."); - return; - } - - const config = resolveConfig(); - activeConfig = config; - running = true; - - console.log("[HorizonListener] Starting with config:", { - horizonUrl: config.horizonUrl, - contractIds: config.contractIds, - pollIntervalMs: config.pollIntervalMs, - startLedger: config.startLedger, - }); - - await pollOnce(config); - - intervalHandle = setInterval(() => { - void pollOnce(config); - }, config.pollIntervalMs); - - console.log( - `[HorizonListener] Started. Polling every ${config.pollIntervalMs}ms.`, - ); + if (running) { + console.warn("[HorizonListener] Already running — ignoring start() call."); + return; + } + + const config = resolveConfig(); + activeConfig = config; + running = true; + + console.log("[HorizonListener] Starting with config:", { + horizonUrl: config.horizonUrl, + contractIds: config.contractIds, + pollIntervalMs: config.pollIntervalMs, + startLedger: config.startLedger, + }); + + await pollOnce(config); + + intervalHandle = setInterval(() => { + void pollOnce(config); + }, config.pollIntervalMs); + + console.log( + `[HorizonListener] Started. Polling every ${config.pollIntervalMs}ms.`, + ); } export function stop(): void { - if (!running) { - console.warn("[HorizonListener] Not running — ignoring stop() call."); - return; - } + if (!running) { + console.warn("[HorizonListener] Not running — ignoring stop() call."); + return; + } - if (intervalHandle !== null) { - clearInterval(intervalHandle); - intervalHandle = null; - } + if (intervalHandle !== null) { + clearInterval(intervalHandle); + intervalHandle = null; + } - running = false; - activeConfig = null; + running = false; + activeConfig = null; - console.log("[HorizonListener] Stopped."); + console.log("[HorizonListener] Stopped."); } \ No newline at end of file diff --git a/src/services/riskService.ts b/src/services/riskService.ts index 3244b54..f47c05a 100644 --- a/src/services/riskService.ts +++ b/src/services/riskService.ts @@ -6,11 +6,11 @@ export type RiskLevel = "low" | "medium" | "high"; export interface RiskEvaluationResult { - walletAddress: string; - score: number | null; - riskLevel: RiskLevel | null; - message: string; - evaluatedAt: string; + walletAddress: string; + score: number | null; + riskLevel: RiskLevel | null; + message: string; + evaluatedAt: string; } // --------------------------------------------------------------------------- @@ -18,14 +18,14 @@ export interface RiskEvaluationResult { // --------------------------------------------------------------------------- export function isValidWalletAddress(address: string): boolean { - return /^G[A-Z2-7]{55}$/.test(address); + return /^G[A-Z2-7]{55}$/.test(address); } export function scoreToRiskLevel(score: number): RiskLevel { - if (score < 40) return "low"; - if (score < 70) return "medium"; - return "high"; + if (score < 40) return "low"; + if (score < 70) return "medium"; + return "high"; } // --------------------------------------------------------------------------- @@ -33,20 +33,20 @@ export function scoreToRiskLevel(score: number): RiskLevel { // --------------------------------------------------------------------------- export async function evaluateWallet( - walletAddress: string, - ): Promise { - if (!isValidWalletAddress(walletAddress)) { - throw new Error( - `Invalid wallet address: "${walletAddress}". ` + + walletAddress: string, +): Promise { + if (!isValidWalletAddress(walletAddress)) { + throw new Error( + `Invalid wallet address: "${walletAddress}". ` + "Must start with 'G' and be 56 alphanumeric characters.", - ); - } - - return { - walletAddress, - score: null, - riskLevel: null, - message: "Risk evaluation placeholder — engine not yet integrated.", - evaluatedAt: new Date().toISOString(), - }; + ); + } + + return { + walletAddress, + score: null, + riskLevel: null, + message: "Risk evaluation placeholder — engine not yet integrated.", + evaluatedAt: new Date().toISOString(), + }; } \ No newline at end of file