From e8a4304a8f71165e7012f1d5685f76db36a31d04 Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Wed, 1 Mar 2023 14:57:14 -0500 Subject: [PATCH 01/14] feat(json-rpc): sketch of package --- .vscode/settings.json | 3 +- yarn-project/.pnp.cjs | 1346 ++++++++++++++++- yarn-project/json-rpc/.eslintrc.cjs | 6 + yarn-project/json-rpc/Dockerfile | 7 + yarn-project/json-rpc/README.md | 29 + yarn-project/json-rpc/package.json | 46 + yarn-project/json-rpc/src/ClassConverter.ts | 33 + .../json-rpc/src/client/JsonRpcClient.ts | 3 + yarn-project/json-rpc/src/client/index.ts | 1 + yarn-project/json-rpc/src/jsUtils.ts | 7 + yarn-project/json-rpc/src/server/JsonProxy.ts | 23 + .../json-rpc/src/server/JsonRpcServer.test.ts | 18 + .../json-rpc/src/server/JsonRpcServer.ts | 63 + yarn-project/json-rpc/src/server/index.ts | 2 + yarn-project/json-rpc/tsconfig.dest.json | 4 + yarn-project/json-rpc/tsconfig.json | 10 + yarn-project/package.json | 1 + yarn-project/yarn.lock | 1132 +++++++++++++- 18 files changed, 2723 insertions(+), 11 deletions(-) create mode 100644 yarn-project/json-rpc/.eslintrc.cjs create mode 100644 yarn-project/json-rpc/Dockerfile create mode 100644 yarn-project/json-rpc/README.md create mode 100644 yarn-project/json-rpc/package.json create mode 100644 yarn-project/json-rpc/src/ClassConverter.ts create mode 100644 yarn-project/json-rpc/src/client/JsonRpcClient.ts create mode 100644 yarn-project/json-rpc/src/client/index.ts create mode 100644 yarn-project/json-rpc/src/jsUtils.ts create mode 100644 yarn-project/json-rpc/src/server/JsonProxy.ts create mode 100644 yarn-project/json-rpc/src/server/JsonRpcServer.test.ts create mode 100644 yarn-project/json-rpc/src/server/JsonRpcServer.ts create mode 100644 yarn-project/json-rpc/src/server/index.ts create mode 100644 yarn-project/json-rpc/tsconfig.dest.json create mode 100644 yarn-project/json-rpc/tsconfig.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 12af39373c4..64b124c8ddb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -126,5 +126,6 @@ }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "cmake.sourceDirectory": "${workspaceFolder}/circuits" } diff --git a/yarn-project/.pnp.cjs b/yarn-project/.pnp.cjs index 9c39534842c..bb7d7c3079f 100755 --- a/yarn-project/.pnp.cjs +++ b/yarn-project/.pnp.cjs @@ -43,6 +43,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "name": "@aztec/ethereum.js",\ "reference": "workspace:ethereum.js"\ },\ + {\ + "name": "@aztec/json-rpc",\ + "reference": "workspace:json-rpc"\ + },\ {\ "name": "@aztec/kernel-simulator",\ "reference": "workspace:kernel-simulator"\ @@ -87,6 +91,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@aztec/end-to-end", ["workspace:end-to-end"]],\ ["@aztec/eslint-config", ["workspace:eslint-config"]],\ ["@aztec/ethereum.js", ["workspace:ethereum.js"]],\ + ["@aztec/json-rpc", ["workspace:json-rpc"]],\ ["@aztec/kernel-simulator", ["workspace:kernel-simulator"]],\ ["@aztec/p2p", ["workspace:p2p"]],\ ["@aztec/prettier-config", ["workspace:prettier-config"]],\ @@ -262,6 +267,31 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "SOFT"\ }]\ ]],\ + ["@aztec/json-rpc", [\ + ["workspace:json-rpc", {\ + "packageLocation": "./json-rpc/",\ + "packageDependencies": [\ + ["@aztec/json-rpc", "workspace:json-rpc"],\ + ["@aztec/eslint-config", "workspace:eslint-config"],\ + ["@jest/globals", "npm:29.4.3"],\ + ["@rushstack/eslint-patch", "npm:1.2.0"],\ + ["@types/jest", "npm:29.4.0"],\ + ["@types/koa", "npm:2.13.5"],\ + ["@types/koa-bodyparser", "npm:4.3.10"],\ + ["@types/koa-router", "npm:7.4.4"],\ + ["@types/node", "npm:18.14.2"],\ + ["jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.4.3"],\ + ["koa", "npm:2.14.1"],\ + ["koa-bodyparser", "npm:4.3.0"],\ + ["koa-router", "npm:12.0.0"],\ + ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:28.0.8"],\ + ["ts-node", "virtual:97973ff51783dc29efdf1c1cff3bd542763fb1d8ea565946db4f6425a5a443923944d5f46e5672160073e5b792b61ec2b3a0e9df4f007033f07c728780e0e4e7#npm:10.9.1"],\ + ["tslib", "npm:2.5.0"],\ + ["typescript", "patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["@aztec/kernel-simulator", [\ ["workspace:kernel-simulator", {\ "packageLocation": "./kernel-simulator/",\ @@ -1289,6 +1319,19 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["slash", "npm:3.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/@jest-console-npm-29.4.3-6be041e832-8d9b163feb.zip/node_modules/@jest/console/",\ + "packageDependencies": [\ + ["@jest/console", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["chalk", "npm:4.1.2"],\ + ["jest-message-util", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["slash", "npm:3.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@jest/core", [\ @@ -1299,6 +1342,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/@jest-core-npm-29.4.3-dcfc01f4ce-4aa10644d6.zip/node_modules/@jest/core/",\ + "packageDependencies": [\ + ["@jest/core", "npm:29.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:6bdd9c1efd7f39881e139201d9b4d45546e91918f4fa49d247c582b0114608910962ea603eb40bf12d8d37f2fc8ba5e11f85fe36914243bff343bb4641eae4d2#npm:28.1.3", {\ "packageLocation": "./.yarn/__virtual__/@jest-core-virtual-287831168d/0/cache/@jest-core-npm-28.1.3-4b9647f71c-cb79f34baf.zip/node_modules/@jest/core/",\ "packageDependencies": [\ @@ -1340,6 +1390,47 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "node-notifier"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:b2bdd5a21f99e40fc4b2cd551446cfd8283877dcfd9ef4a39f49cf680c71e2ae3dcf4c40ea52360716d54b42a7b42daeafcb1e3e24b8fb2b8bcf88ddcbe9ef08#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/@jest-core-virtual-5b1b199af3/0/cache/@jest-core-npm-29.4.3-dcfc01f4ce-4aa10644d6.zip/node_modules/@jest/core/",\ + "packageDependencies": [\ + ["@jest/core", "virtual:b2bdd5a21f99e40fc4b2cd551446cfd8283877dcfd9ef4a39f49cf680c71e2ae3dcf4c40ea52360716d54b42a7b42daeafcb1e3e24b8fb2b8bcf88ddcbe9ef08#npm:29.4.3"],\ + ["@jest/console", "npm:29.4.3"],\ + ["@jest/reporters", "virtual:5b1b199af3999b570be412773171e96a110f54546390476f7adaf5ed9bc709a264da9c27d870bfa96738dfdd8ea58132964f33bf251b903f849695c40ee8bdfd#npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/transform", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["@types/node-notifier", null],\ + ["ansi-escapes", "npm:4.3.2"],\ + ["chalk", "npm:4.1.2"],\ + ["ci-info", "npm:3.8.0"],\ + ["exit", "npm:0.1.2"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["jest-changed-files", "npm:29.4.3"],\ + ["jest-config", "virtual:5b1b199af3999b570be412773171e96a110f54546390476f7adaf5ed9bc709a264da9c27d870bfa96738dfdd8ea58132964f33bf251b903f849695c40ee8bdfd#npm:29.4.3"],\ + ["jest-haste-map", "npm:29.4.3"],\ + ["jest-message-util", "npm:29.4.3"],\ + ["jest-regex-util", "npm:29.4.3"],\ + ["jest-resolve", "npm:29.4.3"],\ + ["jest-resolve-dependencies", "npm:29.4.3"],\ + ["jest-runner", "npm:29.4.3"],\ + ["jest-runtime", "npm:29.4.3"],\ + ["jest-snapshot", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["jest-validate", "npm:29.4.3"],\ + ["jest-watcher", "npm:29.4.3"],\ + ["micromatch", "npm:4.0.5"],\ + ["node-notifier", null],\ + ["pretty-format", "npm:29.4.3"],\ + ["slash", "npm:3.0.0"],\ + ["strip-ansi", "npm:6.0.1"]\ + ],\ + "packagePeers": [\ + "@types/node-notifier",\ + "node-notifier"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@jest/environment", [\ @@ -1463,6 +1554,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/@jest-reporters-npm-29.4.3-69702cb368-7aa2e429c9.zip/node_modules/@jest/reporters/",\ + "packageDependencies": [\ + ["@jest/reporters", "npm:29.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:287831168d7cc447c4e1767d27bba70f4e93c72b390452a351232162ee6cbb5c9abecc54ca9ef5e6754f4a1a455fe01598263a21653e80d507856f26261adaa1#npm:28.1.3", {\ "packageLocation": "./.yarn/__virtual__/@jest-reporters-virtual-871f7778ac/0/cache/@jest-reporters-npm-28.1.3-548703b241-a7440887ce.zip/node_modules/@jest/reporters/",\ "packageDependencies": [\ @@ -1500,6 +1598,43 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "node-notifier"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:5b1b199af3999b570be412773171e96a110f54546390476f7adaf5ed9bc709a264da9c27d870bfa96738dfdd8ea58132964f33bf251b903f849695c40ee8bdfd#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/@jest-reporters-virtual-20a8d537a7/0/cache/@jest-reporters-npm-29.4.3-69702cb368-7aa2e429c9.zip/node_modules/@jest/reporters/",\ + "packageDependencies": [\ + ["@jest/reporters", "virtual:5b1b199af3999b570be412773171e96a110f54546390476f7adaf5ed9bc709a264da9c27d870bfa96738dfdd8ea58132964f33bf251b903f849695c40ee8bdfd#npm:29.4.3"],\ + ["@bcoe/v8-coverage", "npm:0.2.3"],\ + ["@jest/console", "npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/transform", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@jridgewell/trace-mapping", "npm:0.3.17"],\ + ["@types/node", "npm:18.14.2"],\ + ["@types/node-notifier", null],\ + ["chalk", "npm:4.1.2"],\ + ["collect-v8-coverage", "npm:1.0.1"],\ + ["exit", "npm:0.1.2"],\ + ["glob", "npm:7.2.3"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["istanbul-lib-coverage", "npm:3.2.0"],\ + ["istanbul-lib-instrument", "npm:5.2.1"],\ + ["istanbul-lib-report", "npm:3.0.0"],\ + ["istanbul-lib-source-maps", "npm:4.0.1"],\ + ["istanbul-reports", "npm:3.1.5"],\ + ["jest-message-util", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["jest-worker", "npm:29.4.3"],\ + ["node-notifier", null],\ + ["slash", "npm:3.0.0"],\ + ["string-length", "npm:4.0.2"],\ + ["strip-ansi", "npm:6.0.1"],\ + ["v8-to-istanbul", "npm:9.1.0"]\ + ],\ + "packagePeers": [\ + "@types/node-notifier",\ + "node-notifier"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@jest/schemas", [\ @@ -1530,6 +1665,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["graceful-fs", "npm:4.2.10"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/@jest-source-map-npm-29.4.3-5978e0c3b9-2301d22514.zip/node_modules/@jest/source-map/",\ + "packageDependencies": [\ + ["@jest/source-map", "npm:29.4.3"],\ + ["@jridgewell/trace-mapping", "npm:0.3.17"],\ + ["callsites", "npm:3.1.0"],\ + ["graceful-fs", "npm:4.2.10"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@jest/test-result", [\ @@ -1543,6 +1688,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["collect-v8-coverage", "npm:1.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/@jest-test-result-npm-29.4.3-4dfbd088b6-164f102b96.zip/node_modules/@jest/test-result/",\ + "packageDependencies": [\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/console", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/istanbul-lib-coverage", "npm:2.0.4"],\ + ["collect-v8-coverage", "npm:1.0.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@jest/test-sequencer", [\ @@ -1556,6 +1712,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["slash", "npm:3.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/@jest-test-sequencer-npm-29.4.3-1bf90ec84b-145e1fa937.zip/node_modules/@jest/test-sequencer/",\ + "packageDependencies": [\ + ["@jest/test-sequencer", "npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["jest-haste-map", "npm:29.4.3"],\ + ["slash", "npm:3.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@jest/transform", [\ @@ -1859,6 +2026,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/accepts", [\ + ["npm:1.3.5", {\ + "packageLocation": "./.yarn/cache/@types-accepts-npm-1.3.5-1d59cd2a7a-590b758057.zip/node_modules/@types/accepts/",\ + "packageDependencies": [\ + ["@types/accepts", "npm:1.3.5"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/babel__core", [\ ["npm:7.20.0", {\ "packageLocation": "./.yarn/cache/@types-babel__core-npm-7.20.0-cf2ab39970-49b601a0a7.zip/node_modules/@types/babel__core/",\ @@ -1904,6 +2081,74 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/body-parser", [\ + ["npm:1.19.2", {\ + "packageLocation": "./.yarn/cache/@types-body-parser-npm-1.19.2-f845b7b538-e17840c7d7.zip/node_modules/@types/body-parser/",\ + "packageDependencies": [\ + ["@types/body-parser", "npm:1.19.2"],\ + ["@types/connect", "npm:3.4.35"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/connect", [\ + ["npm:3.4.35", {\ + "packageLocation": "./.yarn/cache/@types-connect-npm-3.4.35-7337eee0a3-fe81351470.zip/node_modules/@types/connect/",\ + "packageDependencies": [\ + ["@types/connect", "npm:3.4.35"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/content-disposition", [\ + ["npm:0.5.5", {\ + "packageLocation": "./.yarn/cache/@types-content-disposition-npm-0.5.5-2219aba782-fdf7379db1.zip/node_modules/@types/content-disposition/",\ + "packageDependencies": [\ + ["@types/content-disposition", "npm:0.5.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/cookies", [\ + ["npm:0.7.7", {\ + "packageLocation": "./.yarn/cache/@types-cookies-npm-0.7.7-0fbdd53be5-d3759efc11.zip/node_modules/@types/cookies/",\ + "packageDependencies": [\ + ["@types/cookies", "npm:0.7.7"],\ + ["@types/connect", "npm:3.4.35"],\ + ["@types/express", "npm:4.17.17"],\ + ["@types/keygrip", "npm:1.0.2"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/express", [\ + ["npm:4.17.17", {\ + "packageLocation": "./.yarn/cache/@types-express-npm-4.17.17-46fe8173db-0196dacc27.zip/node_modules/@types/express/",\ + "packageDependencies": [\ + ["@types/express", "npm:4.17.17"],\ + ["@types/body-parser", "npm:1.19.2"],\ + ["@types/express-serve-static-core", "npm:4.17.33"],\ + ["@types/qs", "npm:6.9.7"],\ + ["@types/serve-static", "npm:1.15.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/express-serve-static-core", [\ + ["npm:4.17.33", {\ + "packageLocation": "./.yarn/cache/@types-express-serve-static-core-npm-4.17.33-0366bd5654-dce580d16b.zip/node_modules/@types/express-serve-static-core/",\ + "packageDependencies": [\ + ["@types/express-serve-static-core", "npm:4.17.33"],\ + ["@types/node", "npm:18.14.2"],\ + ["@types/qs", "npm:6.9.7"],\ + ["@types/range-parser", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/graceful-fs", [\ ["npm:4.1.6", {\ "packageLocation": "./.yarn/cache/@types-graceful-fs-npm-4.1.6-1eadcf742d-c3070ccdc9.zip/node_modules/@types/graceful-fs/",\ @@ -1914,6 +2159,24 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/http-assert", [\ + ["npm:1.5.3", {\ + "packageLocation": "./.yarn/cache/@types-http-assert-npm-1.5.3-d45bf58309-9553e5a0b8.zip/node_modules/@types/http-assert/",\ + "packageDependencies": [\ + ["@types/http-assert", "npm:1.5.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/http-errors", [\ + ["npm:2.0.1", {\ + "packageLocation": "./.yarn/cache/@types-http-errors-npm-2.0.1-c59d5079a7-3bb0c50b0a.zip/node_modules/@types/http-errors/",\ + "packageDependencies": [\ + ["@types/http-errors", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/istanbul-lib-coverage", [\ ["npm:2.0.4", {\ "packageLocation": "./.yarn/cache/@types-istanbul-lib-coverage-npm-2.0.4-734954bb56-a25d7589ee.zip/node_modules/@types/istanbul-lib-coverage/",\ @@ -1963,6 +2226,71 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/keygrip", [\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/@types-keygrip-npm-1.0.2-2e57be51bc-60bc2738a4.zip/node_modules/@types/keygrip/",\ + "packageDependencies": [\ + ["@types/keygrip", "npm:1.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/koa", [\ + ["npm:2.13.5", {\ + "packageLocation": "./.yarn/cache/@types-koa-npm-2.13.5-ee6d93204c-e3b634d934.zip/node_modules/@types/koa/",\ + "packageDependencies": [\ + ["@types/koa", "npm:2.13.5"],\ + ["@types/accepts", "npm:1.3.5"],\ + ["@types/content-disposition", "npm:0.5.5"],\ + ["@types/cookies", "npm:0.7.7"],\ + ["@types/http-assert", "npm:1.5.3"],\ + ["@types/http-errors", "npm:2.0.1"],\ + ["@types/keygrip", "npm:1.0.2"],\ + ["@types/koa-compose", "npm:3.2.5"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/koa-bodyparser", [\ + ["npm:4.3.10", {\ + "packageLocation": "./.yarn/cache/@types-koa-bodyparser-npm-4.3.10-281609ae41-4b4cd17681.zip/node_modules/@types/koa-bodyparser/",\ + "packageDependencies": [\ + ["@types/koa-bodyparser", "npm:4.3.10"],\ + ["@types/koa", "npm:2.13.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/koa-compose", [\ + ["npm:3.2.5", {\ + "packageLocation": "./.yarn/cache/@types-koa-compose-npm-3.2.5-b9ab25d904-5d1147c4b0.zip/node_modules/@types/koa-compose/",\ + "packageDependencies": [\ + ["@types/koa-compose", "npm:3.2.5"],\ + ["@types/koa", "npm:2.13.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/koa-router", [\ + ["npm:7.4.4", {\ + "packageLocation": "./.yarn/cache/@types-koa-router-npm-7.4.4-ea72843f67-23ff5b725d.zip/node_modules/@types/koa-router/",\ + "packageDependencies": [\ + ["@types/koa-router", "npm:7.4.4"],\ + ["@types/koa", "npm:2.13.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/mime", [\ + ["npm:3.0.1", {\ + "packageLocation": "./.yarn/cache/@types-mime-npm-3.0.1-dec03536dc-4040fac73f.zip/node_modules/@types/mime/",\ + "packageDependencies": [\ + ["@types/mime", "npm:3.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/node", [\ ["npm:18.14.2", {\ "packageLocation": "./.yarn/cache/@types-node-npm-18.14.2-ba0496d563-53c07e721f.zip/node_modules/@types/node/",\ @@ -1981,6 +2309,24 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/qs", [\ + ["npm:6.9.7", {\ + "packageLocation": "./.yarn/cache/@types-qs-npm-6.9.7-4a3e6ca0d0-7fd6f9c250.zip/node_modules/@types/qs/",\ + "packageDependencies": [\ + ["@types/qs", "npm:6.9.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/range-parser", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/cache/@types-range-parser-npm-1.2.4-23d797fbde-b7c0dfd508.zip/node_modules/@types/range-parser/",\ + "packageDependencies": [\ + ["@types/range-parser", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/semver", [\ ["npm:7.3.13", {\ "packageLocation": "./.yarn/cache/@types-semver-npm-7.3.13-56212b60da-00c0724d54.zip/node_modules/@types/semver/",\ @@ -1990,6 +2336,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/serve-static", [\ + ["npm:1.15.1", {\ + "packageLocation": "./.yarn/cache/@types-serve-static-npm-1.15.1-27b3deb72c-2e078bdc1e.zip/node_modules/@types/serve-static/",\ + "packageDependencies": [\ + ["@types/serve-static", "npm:1.15.1"],\ + ["@types/mime", "npm:3.0.1"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/stack-utils", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/@types-stack-utils-npm-2.0.1-867718ab70-205fdbe332.zip/node_modules/@types/stack-utils/",\ @@ -2217,6 +2574,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["accepts", [\ + ["npm:1.3.8", {\ + "packageLocation": "./.yarn/cache/accepts-npm-1.3.8-9a812371c9-50c43d32e7.zip/node_modules/accepts/",\ + "packageDependencies": [\ + ["accepts", "npm:1.3.8"],\ + ["mime-types", "npm:2.1.35"],\ + ["negotiator", "npm:0.6.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["acorn", [\ ["npm:8.8.2", {\ "packageLocation": "./.yarn/cache/acorn-npm-8.8.2-9d518fd7d3-f790b99a1b.zip/node_modules/acorn/",\ @@ -2421,6 +2789,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/babel-jest-npm-29.4.3-d864a10050-a1a95937ad.zip/node_modules/babel-jest/",\ + "packageDependencies": [\ + ["babel-jest", "npm:29.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:21663eca01d249e4de7061e45ba79182a5d2a74579dc7b76257006815cf5595e6c16052d8a24fe20604792b588cf559a620e327bb61f90fab6ab515903cf1997#npm:28.1.3", {\ "packageLocation": "./.yarn/__virtual__/babel-jest-virtual-65ff6aa41a/0/cache/babel-jest-npm-28.1.3-3bb56d0efd-57ccd2296e.zip/node_modules/babel-jest/",\ "packageDependencies": [\ @@ -2438,6 +2813,24 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "@babel/core"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:f7057c576a1d00b928412986b6ab2562057d679c976a9560dd0fe438b890870219d2d1233c6e19b890d8bd1a7a1871f24c4868ce4c2e549bec4af42aea3ee4b3#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/babel-jest-virtual-f0ddbe0412/0/cache/babel-jest-npm-29.4.3-d864a10050-a1a95937ad.zip/node_modules/babel-jest/",\ + "packageDependencies": [\ + ["babel-jest", "virtual:f7057c576a1d00b928412986b6ab2562057d679c976a9560dd0fe438b890870219d2d1233c6e19b890d8bd1a7a1871f24c4868ce4c2e549bec4af42aea3ee4b3#npm:29.4.3"],\ + ["@babel/core", "npm:7.21.0"],\ + ["@jest/transform", "npm:29.4.3"],\ + ["@types/babel__core", "npm:7.20.0"],\ + ["babel-plugin-istanbul", "npm:6.1.1"],\ + ["babel-preset-jest", "virtual:f0ddbe0412b42fd9790d481546d81294ebd75ef9a8b72e3dbe68e16dd6f5e0e235fb6b17810c0efa5c6b9314efb669eda8119bb56cc0f17edb61fd98f49aab6c#npm:29.4.3"],\ + ["chalk", "npm:4.1.2"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["slash", "npm:3.0.0"]\ + ],\ + "packagePeers": [\ + "@babel/core"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["babel-plugin-istanbul", [\ @@ -2465,6 +2858,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/babel__traverse", "npm:7.18.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/babel-plugin-jest-hoist-npm-29.4.3-1f8b9befa4-c8702a6db6.zip/node_modules/babel-plugin-jest-hoist/",\ + "packageDependencies": [\ + ["babel-plugin-jest-hoist", "npm:29.4.3"],\ + ["@babel/template", "npm:7.20.7"],\ + ["@babel/types", "npm:7.21.2"],\ + ["@types/babel__core", "npm:7.20.0"],\ + ["@types/babel__traverse", "npm:7.18.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["babel-preset-current-node-syntax", [\ @@ -2534,8 +2938,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ - ["virtual:65ff6aa41a0c2e8e802c0ee8cf59a016c718123cb429445b22d1c2f4471404bc85481fc353ebf216e40d7919025c13178d6f92e4350ac197cbded422dd5855c9#npm:28.1.3", {\ - "packageLocation": "./.yarn/__virtual__/babel-preset-jest-virtual-57d4070216/0/cache/babel-preset-jest-npm-28.1.3-8e610faead-8248a4a5ca.zip/node_modules/babel-preset-jest/",\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/babel-preset-jest-npm-29.4.3-e2b3c9d538-a091721861.zip/node_modules/babel-preset-jest/",\ + "packageDependencies": [\ + ["babel-preset-jest", "npm:29.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:65ff6aa41a0c2e8e802c0ee8cf59a016c718123cb429445b22d1c2f4471404bc85481fc353ebf216e40d7919025c13178d6f92e4350ac197cbded422dd5855c9#npm:28.1.3", {\ + "packageLocation": "./.yarn/__virtual__/babel-preset-jest-virtual-57d4070216/0/cache/babel-preset-jest-npm-28.1.3-8e610faead-8248a4a5ca.zip/node_modules/babel-preset-jest/",\ "packageDependencies": [\ ["babel-preset-jest", "virtual:65ff6aa41a0c2e8e802c0ee8cf59a016c718123cb429445b22d1c2f4471404bc85481fc353ebf216e40d7919025c13178d6f92e4350ac197cbded422dd5855c9#npm:28.1.3"],\ ["@babel/core", "npm:7.21.0"],\ @@ -2548,6 +2959,21 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "@types/babel__core"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:f0ddbe0412b42fd9790d481546d81294ebd75ef9a8b72e3dbe68e16dd6f5e0e235fb6b17810c0efa5c6b9314efb669eda8119bb56cc0f17edb61fd98f49aab6c#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/babel-preset-jest-virtual-42e231caf2/0/cache/babel-preset-jest-npm-29.4.3-e2b3c9d538-a091721861.zip/node_modules/babel-preset-jest/",\ + "packageDependencies": [\ + ["babel-preset-jest", "virtual:f0ddbe0412b42fd9790d481546d81294ebd75ef9a8b72e3dbe68e16dd6f5e0e235fb6b17810c0efa5c6b9314efb669eda8119bb56cc0f17edb61fd98f49aab6c#npm:29.4.3"],\ + ["@babel/core", "npm:7.21.0"],\ + ["@types/babel__core", "npm:7.20.0"],\ + ["babel-plugin-jest-hoist", "npm:29.4.3"],\ + ["babel-preset-current-node-syntax", "virtual:57d40702162dfd779a528ef2591db01a74757c9351794bc11a1e69539c576c2efcb4730c624468ac38262f25cdb19589431b5d880e29877786f6373425ae06b8#npm:1.0.1"]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@types/babel__core"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["balanced-match", [\ @@ -2630,6 +3056,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["bytes", [\ + ["npm:3.1.2", {\ + "packageLocation": "./.yarn/cache/bytes-npm-3.1.2-28b8643004-e4bcd3948d.zip/node_modules/bytes/",\ + "packageDependencies": [\ + ["bytes", "npm:3.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["cacache", [\ ["npm:16.1.3", {\ "packageLocation": "./.yarn/cache/cacache-npm-16.1.3-4e2088ed0d-d91409e6e5.zip/node_modules/cacache/",\ @@ -2657,6 +3092,28 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["cache-content-type", [\ + ["npm:1.0.1", {\ + "packageLocation": "./.yarn/cache/cache-content-type-npm-1.0.1-f709f8c309-18db4d5945.zip/node_modules/cache-content-type/",\ + "packageDependencies": [\ + ["cache-content-type", "npm:1.0.1"],\ + ["mime-types", "npm:2.1.35"],\ + ["ylru", "npm:1.3.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["call-bind", [\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/call-bind-npm-1.0.2-c957124861-f8e31de9d1.zip/node_modules/call-bind/",\ + "packageDependencies": [\ + ["call-bind", "npm:1.0.2"],\ + ["function-bind", "npm:1.1.1"],\ + ["get-intrinsic", "npm:1.2.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["callsites", [\ ["npm:3.1.0", {\ "packageLocation": "./.yarn/cache/callsites-npm-3.1.0-268f989910-072d17b6ab.zip/node_modules/callsites/",\ @@ -2778,6 +3235,19 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["co-body", [\ + ["npm:6.1.0", {\ + "packageLocation": "./.yarn/cache/co-body-npm-6.1.0-8102b96671-d0a78831a6.zip/node_modules/co-body/",\ + "packageDependencies": [\ + ["co-body", "npm:6.1.0"],\ + ["inflation", "npm:2.0.0"],\ + ["qs", "npm:6.11.0"],\ + ["raw-body", "npm:2.5.2"],\ + ["type-is", "npm:1.6.18"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["collect-v8-coverage", [\ ["npm:1.0.1", {\ "packageLocation": "./.yarn/cache/collect-v8-coverage-npm-1.0.1-39dec86bad-4efe0a1fcc.zip/node_modules/collect-v8-coverage/",\ @@ -2857,6 +3327,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["content-disposition", [\ + ["npm:0.5.4", {\ + "packageLocation": "./.yarn/cache/content-disposition-npm-0.5.4-2d93678616-afb9d545e2.zip/node_modules/content-disposition/",\ + "packageDependencies": [\ + ["content-disposition", "npm:0.5.4"],\ + ["safe-buffer", "npm:5.2.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["content-type", [\ + ["npm:1.0.5", {\ + "packageLocation": "./.yarn/cache/content-type-npm-1.0.5-3e037bf9ab-566271e0a2.zip/node_modules/content-type/",\ + "packageDependencies": [\ + ["content-type", "npm:1.0.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["convert-source-map", [\ ["npm:1.9.0", {\ "packageLocation": "./.yarn/cache/convert-source-map-npm-1.9.0-e294555f4b-dc55a1f28d.zip/node_modules/convert-source-map/",\ @@ -2873,6 +3362,26 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["cookies", [\ + ["npm:0.8.0", {\ + "packageLocation": "./.yarn/cache/cookies-npm-0.8.0-d7388cbd94-806055a44f.zip/node_modules/cookies/",\ + "packageDependencies": [\ + ["cookies", "npm:0.8.0"],\ + ["depd", "npm:2.0.0"],\ + ["keygrip", "npm:1.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["copy-to", [\ + ["npm:2.0.1", {\ + "packageLocation": "./.yarn/cache/copy-to-npm-2.0.1-474b7b678b-05ea12875b.zip/node_modules/copy-to/",\ + "packageDependencies": [\ + ["copy-to", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["create-require", [\ ["npm:1.1.1", {\ "packageLocation": "./.yarn/cache/create-require-npm-1.1.1-839884ca2e-a9a1503d43.zip/node_modules/create-require/",\ @@ -2926,6 +3435,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["deep-equal", [\ + ["npm:1.0.1", {\ + "packageLocation": "./.yarn/cache/deep-equal-npm-1.0.1-f05565c4e5-5af8cbfceb.zip/node_modules/deep-equal/",\ + "packageDependencies": [\ + ["deep-equal", "npm:1.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["deep-is", [\ ["npm:0.1.4", {\ "packageLocation": "./.yarn/cache/deep-is-npm-0.1.4-88938b5a67-edb65dd0d7.zip/node_modules/deep-is/",\ @@ -2960,6 +3478,22 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["depd", "npm:1.1.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/depd-npm-2.0.0-b6c51a4b43-abbe19c768.zip/node_modules/depd/",\ + "packageDependencies": [\ + ["depd", "npm:2.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["destroy", [\ + ["npm:1.2.0", {\ + "packageLocation": "./.yarn/cache/destroy-npm-1.2.0-6a511802e2-0acb300b74.zip/node_modules/destroy/",\ + "packageDependencies": [\ + ["destroy", "npm:1.2.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["detect-newline", [\ @@ -3016,6 +3550,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["ee-first", [\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/ee-first-npm-1.1.1-33f8535b39-1b4cac778d.zip/node_modules/ee-first/",\ + "packageDependencies": [\ + ["ee-first", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["electron-to-chromium", [\ ["npm:1.4.311", {\ "packageLocation": "./.yarn/cache/electron-to-chromium-npm-1.4.311-275bc01bd3-663fde5d90.zip/node_modules/electron-to-chromium/",\ @@ -3032,6 +3575,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["emittery", "npm:0.10.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.13.1", {\ + "packageLocation": "./.yarn/cache/emittery-npm-0.13.1-cb6cd1bb03-2b089ab630.zip/node_modules/emittery/",\ + "packageDependencies": [\ + ["emittery", "npm:0.13.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["emoji-regex", [\ @@ -3043,6 +3593,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["encodeurl", [\ + ["npm:1.0.2", {\ + "packageLocation": "./.yarn/cache/encodeurl-npm-1.0.2-f8c8454c41-e50e3d508c.zip/node_modules/encodeurl/",\ + "packageDependencies": [\ + ["encodeurl", "npm:1.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["encoding", [\ ["npm:0.1.13", {\ "packageLocation": "./.yarn/cache/encoding-npm-0.1.13-82a1837d30-bb98632f8f.zip/node_modules/encoding/",\ @@ -3090,6 +3649,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["escape-html", [\ + ["npm:1.0.3", {\ + "packageLocation": "./.yarn/cache/escape-html-npm-1.0.3-376c22ee74-6213ca9ae0.zip/node_modules/escape-html/",\ + "packageDependencies": [\ + ["escape-html", "npm:1.0.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["escape-string-regexp", [\ ["npm:1.0.5", {\ "packageLocation": "./.yarn/cache/escape-string-regexp-npm-1.0.5-3284de402f-6092fda75c.zip/node_modules/escape-string-regexp/",\ @@ -3483,6 +4051,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["fresh", [\ + ["npm:0.5.2", {\ + "packageLocation": "./.yarn/cache/fresh-npm-0.5.2-ad2bb4c0a2-13ea8b08f9.zip/node_modules/fresh/",\ + "packageDependencies": [\ + ["fresh", "npm:0.5.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["fs-minipass", [\ ["npm:2.1.0", {\ "packageLocation": "./.yarn/cache/fs-minipass-npm-2.1.0-501ef87306-1b8d128dae.zip/node_modules/fs-minipass/",\ @@ -3556,6 +4133,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["get-intrinsic", [\ + ["npm:1.2.0", {\ + "packageLocation": "./.yarn/cache/get-intrinsic-npm-1.2.0-eb08ea9b1d-78fc0487b7.zip/node_modules/get-intrinsic/",\ + "packageDependencies": [\ + ["get-intrinsic", "npm:1.2.0"],\ + ["function-bind", "npm:1.1.1"],\ + ["has", "npm:1.0.3"],\ + ["has-symbols", "npm:1.0.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["get-package-type", [\ ["npm:0.1.0", {\ "packageLocation": "./.yarn/cache/get-package-type-npm-0.1.0-6c70cdc8ab-bba0811116.zip/node_modules/get-package-type/",\ @@ -3695,6 +4284,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["has-symbols", [\ + ["npm:1.0.3", {\ + "packageLocation": "./.yarn/cache/has-symbols-npm-1.0.3-1986bff2c4-a054c40c63.zip/node_modules/has-symbols/",\ + "packageDependencies": [\ + ["has-symbols", "npm:1.0.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["has-tostringtag", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/has-tostringtag-npm-1.0.0-b1fcf3ab55-cc12eb28cb.zip/node_modules/has-tostringtag/",\ + "packageDependencies": [\ + ["has-tostringtag", "npm:1.0.0"],\ + ["has-symbols", "npm:1.0.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["has-unicode", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/has-unicode-npm-2.0.1-893adb4747-1eab07a743.zip/node_modules/has-unicode/",\ @@ -3713,6 +4321,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["http-assert", [\ + ["npm:1.5.0", {\ + "packageLocation": "./.yarn/cache/http-assert-npm-1.5.0-bf7ea4ffcf-69c9b3c14c.zip/node_modules/http-assert/",\ + "packageDependencies": [\ + ["http-assert", "npm:1.5.0"],\ + ["deep-equal", "npm:1.0.1"],\ + ["http-errors", "npm:1.8.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["http-cache-semantics", [\ ["npm:4.1.1", {\ "packageLocation": "./.yarn/cache/http-cache-semantics-npm-4.1.1-1120131375-83ac0bc60b.zip/node_modules/http-cache-semantics/",\ @@ -3722,6 +4341,32 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["http-errors", [\ + ["npm:1.8.1", {\ + "packageLocation": "./.yarn/cache/http-errors-npm-1.8.1-fb60d9f6ae-d3c7e7e776.zip/node_modules/http-errors/",\ + "packageDependencies": [\ + ["http-errors", "npm:1.8.1"],\ + ["depd", "npm:1.1.2"],\ + ["inherits", "npm:2.0.4"],\ + ["setprototypeof", "npm:1.2.0"],\ + ["statuses", "npm:1.5.0"],\ + ["toidentifier", "npm:1.0.1"]\ + ],\ + "linkType": "HARD"\ + }],\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/http-errors-npm-2.0.0-3f1c503428-9b0a378266.zip/node_modules/http-errors/",\ + "packageDependencies": [\ + ["http-errors", "npm:2.0.0"],\ + ["depd", "npm:2.0.0"],\ + ["inherits", "npm:2.0.4"],\ + ["setprototypeof", "npm:1.2.0"],\ + ["statuses", "npm:2.0.1"],\ + ["toidentifier", "npm:1.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["http-proxy-agent", [\ ["npm:5.0.0", {\ "packageLocation": "./.yarn/cache/http-proxy-agent-npm-5.0.0-7f1f121b83-e2ee1ff165.zip/node_modules/http-proxy-agent/",\ @@ -3765,6 +4410,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }]\ ]],\ ["iconv-lite", [\ + ["npm:0.4.24", {\ + "packageLocation": "./.yarn/cache/iconv-lite-npm-0.4.24-c5c4ac6695-bd9f120f5a.zip/node_modules/iconv-lite/",\ + "packageDependencies": [\ + ["iconv-lite", "npm:0.4.24"],\ + ["safer-buffer", "npm:2.1.2"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:0.6.3", {\ "packageLocation": "./.yarn/cache/iconv-lite-npm-0.6.3-24b8aae27e-3f60d47a5c.zip/node_modules/iconv-lite/",\ "packageDependencies": [\ @@ -3832,6 +4485,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["inflation", [\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/inflation-npm-2.0.0-e638c91672-a0494871b1.zip/node_modules/inflation/",\ + "packageDependencies": [\ + ["inflation", "npm:2.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["inflight", [\ ["npm:1.0.6", {\ "packageLocation": "./.yarn/cache/inflight-npm-1.0.6-ccedb4b908-f4f76aa072.zip/node_modules/inflight/",\ @@ -3907,6 +4569,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["is-generator-function", [\ + ["npm:1.0.10", {\ + "packageLocation": "./.yarn/cache/is-generator-function-npm-1.0.10-1d0f3809ef-d54644e7db.zip/node_modules/is-generator-function/",\ + "packageDependencies": [\ + ["is-generator-function", "npm:1.0.10"],\ + ["has-tostringtag", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["is-glob", [\ ["npm:4.0.3", {\ "packageLocation": "./.yarn/cache/is-glob-npm-4.0.3-cb87bf1bdb-d381c1319f.zip/node_modules/is-glob/",\ @@ -4028,6 +4700,30 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-npm-29.4.3-d77fc52218-084d10d1ce.zip/node_modules/jest/",\ + "packageDependencies": [\ + ["jest", "npm:29.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/jest-virtual-b2bdd5a21f/0/cache/jest-npm-29.4.3-d77fc52218-084d10d1ce.zip/node_modules/jest/",\ + "packageDependencies": [\ + ["jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.4.3"],\ + ["@jest/core", "virtual:b2bdd5a21f99e40fc4b2cd551446cfd8283877dcfd9ef4a39f49cf680c71e2ae3dcf4c40ea52360716d54b42a7b42daeafcb1e3e24b8fb2b8bcf88ddcbe9ef08#npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node-notifier", null],\ + ["import-local", "npm:3.1.0"],\ + ["jest-cli", "virtual:b2bdd5a21f99e40fc4b2cd551446cfd8283877dcfd9ef4a39f49cf680c71e2ae3dcf4c40ea52360716d54b42a7b42daeafcb1e3e24b8fb2b8bcf88ddcbe9ef08#npm:29.4.3"],\ + ["node-notifier", null]\ + ],\ + "packagePeers": [\ + "@types/node-notifier",\ + "node-notifier"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:97973ff51783dc29efdf1c1cff3bd542763fb1d8ea565946db4f6425a5a443923944d5f46e5672160073e5b792b61ec2b3a0e9df4f007033f07c728780e0e4e7#npm:28.1.3", {\ "packageLocation": "./.yarn/__virtual__/jest-virtual-6bdd9c1efd/0/cache/jest-npm-28.1.3-207c50e059-b9dcb542eb.zip/node_modules/jest/",\ "packageDependencies": [\ @@ -4055,6 +4751,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["p-limit", "npm:3.1.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-changed-files-npm-29.4.3-7102b696f2-9a70bd8e92.zip/node_modules/jest-changed-files/",\ + "packageDependencies": [\ + ["jest-changed-files", "npm:29.4.3"],\ + ["execa", "npm:5.1.1"],\ + ["p-limit", "npm:3.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-circus", [\ @@ -4083,6 +4788,32 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["stack-utils", "npm:2.0.6"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-circus-npm-29.4.3-6829bca05e-2739bef9c8.zip/node_modules/jest-circus/",\ + "packageDependencies": [\ + ["jest-circus", "npm:29.4.3"],\ + ["@jest/environment", "npm:29.4.3"],\ + ["@jest/expect", "npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["chalk", "npm:4.1.2"],\ + ["co", "npm:4.6.0"],\ + ["dedent", "npm:0.7.0"],\ + ["is-generator-fn", "npm:2.1.0"],\ + ["jest-each", "npm:29.4.3"],\ + ["jest-matcher-utils", "npm:29.4.3"],\ + ["jest-message-util", "npm:29.4.3"],\ + ["jest-runtime", "npm:29.4.3"],\ + ["jest-snapshot", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["p-limit", "npm:3.1.0"],\ + ["pretty-format", "npm:29.4.3"],\ + ["slash", "npm:3.0.0"],\ + ["stack-utils", "npm:2.0.6"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-cli", [\ @@ -4093,6 +4824,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-cli-npm-29.4.3-33f23222d0-f4c9f6d76c.zip/node_modules/jest-cli/",\ + "packageDependencies": [\ + ["jest-cli", "npm:29.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:6bdd9c1efd7f39881e139201d9b4d45546e91918f4fa49d247c582b0114608910962ea603eb40bf12d8d37f2fc8ba5e11f85fe36914243bff343bb4641eae4d2#npm:28.1.3", {\ "packageLocation": "./.yarn/__virtual__/jest-cli-virtual-381c53ab9b/0/cache/jest-cli-npm-28.1.3-aab5c7389d-fb424576bf.zip/node_modules/jest-cli/",\ "packageDependencies": [\ @@ -4117,6 +4855,31 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "node-notifier"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:b2bdd5a21f99e40fc4b2cd551446cfd8283877dcfd9ef4a39f49cf680c71e2ae3dcf4c40ea52360716d54b42a7b42daeafcb1e3e24b8fb2b8bcf88ddcbe9ef08#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/jest-cli-virtual-953904e9ab/0/cache/jest-cli-npm-29.4.3-33f23222d0-f4c9f6d76c.zip/node_modules/jest-cli/",\ + "packageDependencies": [\ + ["jest-cli", "virtual:b2bdd5a21f99e40fc4b2cd551446cfd8283877dcfd9ef4a39f49cf680c71e2ae3dcf4c40ea52360716d54b42a7b42daeafcb1e3e24b8fb2b8bcf88ddcbe9ef08#npm:29.4.3"],\ + ["@jest/core", "virtual:b2bdd5a21f99e40fc4b2cd551446cfd8283877dcfd9ef4a39f49cf680c71e2ae3dcf4c40ea52360716d54b42a7b42daeafcb1e3e24b8fb2b8bcf88ddcbe9ef08#npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node-notifier", null],\ + ["chalk", "npm:4.1.2"],\ + ["exit", "npm:0.1.2"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["import-local", "npm:3.1.0"],\ + ["jest-config", "virtual:953904e9ab77567c2fcc8ffaef99738a057ab32768a3071a4d0648ba590c2fbd5b71c39c740e784dccbaf12e452550f6ebd35609c97de4c512a54cad3dbc6720#npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["jest-validate", "npm:29.4.3"],\ + ["node-notifier", null],\ + ["prompts", "npm:2.4.2"],\ + ["yargs", "npm:17.7.1"]\ + ],\ + "packagePeers": [\ + "@types/node-notifier",\ + "node-notifier"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-config", [\ @@ -4127,6 +4890,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-config-npm-29.4.3-40ed5da9c7-92f9a9c685.zip/node_modules/jest-config/",\ + "packageDependencies": [\ + ["jest-config", "npm:29.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:287831168d7cc447c4e1767d27bba70f4e93c72b390452a351232162ee6cbb5c9abecc54ca9ef5e6754f4a1a455fe01598263a21653e80d507856f26261adaa1#npm:28.1.3", {\ "packageLocation": "./.yarn/__virtual__/jest-config-virtual-21663eca01/0/cache/jest-config-npm-28.1.3-47d1c91477-ddabffd3a3.zip/node_modules/jest-config/",\ "packageDependencies": [\ @@ -4200,6 +4970,80 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "ts-node"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:5b1b199af3999b570be412773171e96a110f54546390476f7adaf5ed9bc709a264da9c27d870bfa96738dfdd8ea58132964f33bf251b903f849695c40ee8bdfd#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/jest-config-virtual-f7057c576a/0/cache/jest-config-npm-29.4.3-40ed5da9c7-92f9a9c685.zip/node_modules/jest-config/",\ + "packageDependencies": [\ + ["jest-config", "virtual:5b1b199af3999b570be412773171e96a110f54546390476f7adaf5ed9bc709a264da9c27d870bfa96738dfdd8ea58132964f33bf251b903f849695c40ee8bdfd#npm:29.4.3"],\ + ["@babel/core", "npm:7.21.0"],\ + ["@jest/test-sequencer", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["@types/ts-node", null],\ + ["babel-jest", "virtual:f7057c576a1d00b928412986b6ab2562057d679c976a9560dd0fe438b890870219d2d1233c6e19b890d8bd1a7a1871f24c4868ce4c2e549bec4af42aea3ee4b3#npm:29.4.3"],\ + ["chalk", "npm:4.1.2"],\ + ["ci-info", "npm:3.8.0"],\ + ["deepmerge", "npm:4.3.0"],\ + ["glob", "npm:7.2.3"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["jest-circus", "npm:29.4.3"],\ + ["jest-environment-node", "npm:29.4.3"],\ + ["jest-get-type", "npm:29.4.3"],\ + ["jest-regex-util", "npm:29.4.3"],\ + ["jest-resolve", "npm:29.4.3"],\ + ["jest-runner", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["jest-validate", "npm:29.4.3"],\ + ["micromatch", "npm:4.0.5"],\ + ["parse-json", "npm:5.2.0"],\ + ["pretty-format", "npm:29.4.3"],\ + ["slash", "npm:3.0.0"],\ + ["strip-json-comments", "npm:3.1.1"],\ + ["ts-node", null]\ + ],\ + "packagePeers": [\ + "@types/node",\ + "@types/ts-node",\ + "ts-node"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:953904e9ab77567c2fcc8ffaef99738a057ab32768a3071a4d0648ba590c2fbd5b71c39c740e784dccbaf12e452550f6ebd35609c97de4c512a54cad3dbc6720#npm:29.4.3", {\ + "packageLocation": "./.yarn/__virtual__/jest-config-virtual-9b47ce0f1a/0/cache/jest-config-npm-29.4.3-40ed5da9c7-92f9a9c685.zip/node_modules/jest-config/",\ + "packageDependencies": [\ + ["jest-config", "virtual:953904e9ab77567c2fcc8ffaef99738a057ab32768a3071a4d0648ba590c2fbd5b71c39c740e784dccbaf12e452550f6ebd35609c97de4c512a54cad3dbc6720#npm:29.4.3"],\ + ["@babel/core", "npm:7.21.0"],\ + ["@jest/test-sequencer", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", null],\ + ["@types/ts-node", null],\ + ["babel-jest", "virtual:f7057c576a1d00b928412986b6ab2562057d679c976a9560dd0fe438b890870219d2d1233c6e19b890d8bd1a7a1871f24c4868ce4c2e549bec4af42aea3ee4b3#npm:29.4.3"],\ + ["chalk", "npm:4.1.2"],\ + ["ci-info", "npm:3.8.0"],\ + ["deepmerge", "npm:4.3.0"],\ + ["glob", "npm:7.2.3"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["jest-circus", "npm:29.4.3"],\ + ["jest-environment-node", "npm:29.4.3"],\ + ["jest-get-type", "npm:29.4.3"],\ + ["jest-regex-util", "npm:29.4.3"],\ + ["jest-resolve", "npm:29.4.3"],\ + ["jest-runner", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["jest-validate", "npm:29.4.3"],\ + ["micromatch", "npm:4.0.5"],\ + ["parse-json", "npm:5.2.0"],\ + ["pretty-format", "npm:29.4.3"],\ + ["slash", "npm:3.0.0"],\ + ["strip-json-comments", "npm:3.1.1"],\ + ["ts-node", null]\ + ],\ + "packagePeers": [\ + "@types/node",\ + "@types/ts-node",\ + "ts-node"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-diff", [\ @@ -4234,6 +5078,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["detect-newline", "npm:3.1.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-docblock-npm-29.4.3-0fa9ff492b-e0e9df1485.zip/node_modules/jest-docblock/",\ + "packageDependencies": [\ + ["jest-docblock", "npm:29.4.3"],\ + ["detect-newline", "npm:3.1.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-each", [\ @@ -4248,6 +5100,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["pretty-format", "npm:28.1.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-each-npm-29.4.3-711c0f15ad-1f72738338.zip/node_modules/jest-each/",\ + "packageDependencies": [\ + ["jest-each", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["chalk", "npm:4.1.2"],\ + ["jest-get-type", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["pretty-format", "npm:29.4.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-environment-node", [\ @@ -4263,6 +5127,19 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["jest-util", "npm:28.1.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-environment-node-npm-29.4.3-97945b9a48-3c7362edfd.zip/node_modules/jest-environment-node/",\ + "packageDependencies": [\ + ["jest-environment-node", "npm:29.4.3"],\ + ["@jest/environment", "npm:29.4.3"],\ + ["@jest/fake-timers", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["jest-mock", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-get-type", [\ @@ -4330,6 +5207,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["pretty-format", "npm:28.1.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-leak-detector-npm-29.4.3-86751397c4-ec2b45e6f0.zip/node_modules/jest-leak-detector/",\ + "packageDependencies": [\ + ["jest-leak-detector", "npm:29.4.3"],\ + ["jest-get-type", "npm:29.4.3"],\ + ["pretty-format", "npm:29.4.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-matcher-utils", [\ @@ -4419,6 +5305,19 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["virtual:272db5328e2b2454604ee594f98200c728315a00ae096872165145a6671a332e15b02726073906e9847940b5dbdec2a6cb11c8b24dd9a36cec5ff70c0bec5d58#npm:1.2.3", {\ + "packageLocation": "./.yarn/__virtual__/jest-pnp-resolver-virtual-a3e03b702c/0/cache/jest-pnp-resolver-npm-1.2.3-70e06bf27c-db1a8ab2cb.zip/node_modules/jest-pnp-resolver/",\ + "packageDependencies": [\ + ["jest-pnp-resolver", "virtual:272db5328e2b2454604ee594f98200c728315a00ae096872165145a6671a332e15b02726073906e9847940b5dbdec2a6cb11c8b24dd9a36cec5ff70c0bec5d58#npm:1.2.3"],\ + ["@types/jest-resolve", null],\ + ["jest-resolve", "npm:29.4.3"]\ + ],\ + "packagePeers": [\ + "@types/jest-resolve",\ + "jest-resolve"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:acd3a0d26baa9b0c8a965135854f495ae31b9cd3fc8d42755bb6234e7643800b9c65432ff170ecb4d83e6749df839503d229d31338fdb14d3c5789bf43206739#npm:1.2.3", {\ "packageLocation": "./.yarn/__virtual__/jest-pnp-resolver-virtual-0573b412e0/0/cache/jest-pnp-resolver-npm-1.2.3-70e06bf27c-db1a8ab2cb.zip/node_modules/jest-pnp-resolver/",\ "packageDependencies": [\ @@ -4465,6 +5364,22 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["slash", "npm:3.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-resolve-npm-29.4.3-272db5328e-056a66becc.zip/node_modules/jest-resolve/",\ + "packageDependencies": [\ + ["jest-resolve", "npm:29.4.3"],\ + ["chalk", "npm:4.1.2"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["jest-haste-map", "npm:29.4.3"],\ + ["jest-pnp-resolver", "virtual:272db5328e2b2454604ee594f98200c728315a00ae096872165145a6671a332e15b02726073906e9847940b5dbdec2a6cb11c8b24dd9a36cec5ff70c0bec5d58#npm:1.2.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["jest-validate", "npm:29.4.3"],\ + ["resolve", "patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=c3c19d"],\ + ["resolve.exports", "npm:2.0.0"],\ + ["slash", "npm:3.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-resolve-dependencies", [\ @@ -4476,6 +5391,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["jest-snapshot", "npm:28.1.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-resolve-dependencies-npm-29.4.3-fec3ab63f6-3ad934cd21.zip/node_modules/jest-resolve-dependencies/",\ + "packageDependencies": [\ + ["jest-resolve-dependencies", "npm:29.4.3"],\ + ["jest-regex-util", "npm:29.4.3"],\ + ["jest-snapshot", "npm:29.4.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-runner", [\ @@ -4506,6 +5430,34 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["source-map-support", "npm:0.5.13"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-runner-npm-29.4.3-dac13ce85e-c41108e5da.zip/node_modules/jest-runner/",\ + "packageDependencies": [\ + ["jest-runner", "npm:29.4.3"],\ + ["@jest/console", "npm:29.4.3"],\ + ["@jest/environment", "npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/transform", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["chalk", "npm:4.1.2"],\ + ["emittery", "npm:0.13.1"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["jest-docblock", "npm:29.4.3"],\ + ["jest-environment-node", "npm:29.4.3"],\ + ["jest-haste-map", "npm:29.4.3"],\ + ["jest-leak-detector", "npm:29.4.3"],\ + ["jest-message-util", "npm:29.4.3"],\ + ["jest-resolve", "npm:29.4.3"],\ + ["jest-runtime", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["jest-watcher", "npm:29.4.3"],\ + ["jest-worker", "npm:29.4.3"],\ + ["p-limit", "npm:3.1.0"],\ + ["source-map-support", "npm:0.5.13"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-runtime", [\ @@ -4537,6 +5489,35 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["strip-bom", "npm:4.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-runtime-npm-29.4.3-09e5a4f695-b99f8a910d.zip/node_modules/jest-runtime/",\ + "packageDependencies": [\ + ["jest-runtime", "npm:29.4.3"],\ + ["@jest/environment", "npm:29.4.3"],\ + ["@jest/fake-timers", "npm:29.4.3"],\ + ["@jest/globals", "npm:29.4.3"],\ + ["@jest/source-map", "npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/transform", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["chalk", "npm:4.1.2"],\ + ["cjs-module-lexer", "npm:1.2.2"],\ + ["collect-v8-coverage", "npm:1.0.1"],\ + ["glob", "npm:7.2.3"],\ + ["graceful-fs", "npm:4.2.10"],\ + ["jest-haste-map", "npm:29.4.3"],\ + ["jest-message-util", "npm:29.4.3"],\ + ["jest-mock", "npm:29.4.3"],\ + ["jest-regex-util", "npm:29.4.3"],\ + ["jest-resolve", "npm:29.4.3"],\ + ["jest-snapshot", "npm:29.4.3"],\ + ["jest-util", "npm:29.4.3"],\ + ["slash", "npm:3.0.0"],\ + ["strip-bom", "npm:4.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-snapshot", [\ @@ -4643,6 +5624,19 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["pretty-format", "npm:28.1.3"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-validate-npm-29.4.3-2a6cf52c2d-983e56430d.zip/node_modules/jest-validate/",\ + "packageDependencies": [\ + ["jest-validate", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["camelcase", "npm:6.3.0"],\ + ["chalk", "npm:4.1.2"],\ + ["jest-get-type", "npm:29.4.3"],\ + ["leven", "npm:3.1.0"],\ + ["pretty-format", "npm:29.4.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-watcher", [\ @@ -4660,6 +5654,21 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["string-length", "npm:4.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:29.4.3", {\ + "packageLocation": "./.yarn/cache/jest-watcher-npm-29.4.3-3c0d4930a3-44b64991b3.zip/node_modules/jest-watcher/",\ + "packageDependencies": [\ + ["jest-watcher", "npm:29.4.3"],\ + ["@jest/test-result", "npm:29.4.3"],\ + ["@jest/types", "npm:29.4.3"],\ + ["@types/node", "npm:18.14.2"],\ + ["ansi-escapes", "npm:4.3.2"],\ + ["chalk", "npm:4.1.2"],\ + ["emittery", "npm:0.13.1"],\ + ["jest-util", "npm:29.4.3"],\ + ["string-length", "npm:4.0.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jest-worker", [\ @@ -4767,6 +5776,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["keygrip", [\ + ["npm:1.1.0", {\ + "packageLocation": "./.yarn/cache/keygrip-npm-1.1.0-8da030c3ff-078cd16a46.zip/node_modules/keygrip/",\ + "packageDependencies": [\ + ["keygrip", "npm:1.1.0"],\ + ["tsscmp", "npm:1.0.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["kleur", [\ ["npm:3.0.3", {\ "packageLocation": "./.yarn/cache/kleur-npm-3.0.3-f6f53649a4-df82cd1e17.zip/node_modules/kleur/",\ @@ -4776,6 +5795,82 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["koa", [\ + ["npm:2.14.1", {\ + "packageLocation": "./.yarn/cache/koa-npm-2.14.1-92dad86c35-84cfce48d7.zip/node_modules/koa/",\ + "packageDependencies": [\ + ["koa", "npm:2.14.1"],\ + ["accepts", "npm:1.3.8"],\ + ["cache-content-type", "npm:1.0.1"],\ + ["content-disposition", "npm:0.5.4"],\ + ["content-type", "npm:1.0.5"],\ + ["cookies", "npm:0.8.0"],\ + ["debug", "virtual:0c9322b41fab7d59285768a0e9d661e38864eba0258adfe39a8253e14f176a6b908423ed1fe2a13cb929c471127e6c8d9e2ce76373907f467366a10dca15a138#npm:4.3.4"],\ + ["delegates", "npm:1.0.0"],\ + ["depd", "npm:2.0.0"],\ + ["destroy", "npm:1.2.0"],\ + ["encodeurl", "npm:1.0.2"],\ + ["escape-html", "npm:1.0.3"],\ + ["fresh", "npm:0.5.2"],\ + ["http-assert", "npm:1.5.0"],\ + ["http-errors", "npm:1.8.1"],\ + ["is-generator-function", "npm:1.0.10"],\ + ["koa-compose", "npm:4.1.0"],\ + ["koa-convert", "npm:2.0.0"],\ + ["on-finished", "npm:2.4.1"],\ + ["only", "npm:0.0.2"],\ + ["parseurl", "npm:1.3.3"],\ + ["statuses", "npm:1.5.0"],\ + ["type-is", "npm:1.6.18"],\ + ["vary", "npm:1.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["koa-bodyparser", [\ + ["npm:4.3.0", {\ + "packageLocation": "./.yarn/cache/koa-bodyparser-npm-4.3.0-1bf6ca26ab-c227fe0fb5.zip/node_modules/koa-bodyparser/",\ + "packageDependencies": [\ + ["koa-bodyparser", "npm:4.3.0"],\ + ["co-body", "npm:6.1.0"],\ + ["copy-to", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["koa-compose", [\ + ["npm:4.1.0", {\ + "packageLocation": "./.yarn/cache/koa-compose-npm-4.1.0-b682d9324e-46cb16792d.zip/node_modules/koa-compose/",\ + "packageDependencies": [\ + ["koa-compose", "npm:4.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["koa-convert", [\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/koa-convert-npm-2.0.0-d709eca55c-7385b33919.zip/node_modules/koa-convert/",\ + "packageDependencies": [\ + ["koa-convert", "npm:2.0.0"],\ + ["co", "npm:4.6.0"],\ + ["koa-compose", "npm:4.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["koa-router", [\ + ["npm:12.0.0", {\ + "packageLocation": "./.yarn/cache/koa-router-npm-12.0.0-ac2780adae-29b02fd969.zip/node_modules/koa-router/",\ + "packageDependencies": [\ + ["koa-router", "npm:12.0.0"],\ + ["http-errors", "npm:2.0.0"],\ + ["koa-compose", "npm:4.1.0"],\ + ["methods", "npm:1.1.2"],\ + ["path-to-regexp", "npm:6.2.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["leven", [\ ["npm:3.1.0", {\ "packageLocation": "./.yarn/cache/leven-npm-3.1.0-b7697736a3-638401d534.zip/node_modules/leven/",\ @@ -4920,6 +6015,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["media-typer", [\ + ["npm:0.3.0", {\ + "packageLocation": "./.yarn/cache/media-typer-npm-0.3.0-8674f8f0f5-af1b38516c.zip/node_modules/media-typer/",\ + "packageDependencies": [\ + ["media-typer", "npm:0.3.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["merge-stream", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/merge-stream-npm-2.0.0-2ac83efea5-6fa4dcc8d8.zip/node_modules/merge-stream/",\ @@ -4938,6 +6042,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["methods", [\ + ["npm:1.1.2", {\ + "packageLocation": "./.yarn/cache/methods-npm-1.1.2-92f6fdb39b-0917ff4041.zip/node_modules/methods/",\ + "packageDependencies": [\ + ["methods", "npm:1.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["micromatch", [\ ["npm:4.0.5", {\ "packageLocation": "./.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-02a17b671c.zip/node_modules/micromatch/",\ @@ -4949,6 +6062,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["mime-db", [\ + ["npm:1.52.0", {\ + "packageLocation": "./.yarn/cache/mime-db-npm-1.52.0-b5371d6fd2-0d99a03585.zip/node_modules/mime-db/",\ + "packageDependencies": [\ + ["mime-db", "npm:1.52.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["mime-types", [\ + ["npm:2.1.35", {\ + "packageLocation": "./.yarn/cache/mime-types-npm-2.1.35-dd9ea9f3e2-89a5b7f1de.zip/node_modules/mime-types/",\ + "packageDependencies": [\ + ["mime-types", "npm:2.1.35"],\ + ["mime-db", "npm:1.52.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["mimic-fn", [\ ["npm:2.1.0", {\ "packageLocation": "./.yarn/cache/mimic-fn-npm-2.1.0-4fbeb3abb4-d2421a3444.zip/node_modules/mimic-fn/",\ @@ -5188,6 +6320,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["object-inspect", [\ + ["npm:1.12.3", {\ + "packageLocation": "./.yarn/cache/object-inspect-npm-1.12.3-1e7d20f5ff-dabfd824d9.zip/node_modules/object-inspect/",\ + "packageDependencies": [\ + ["object-inspect", "npm:1.12.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["on-finished", [\ + ["npm:2.4.1", {\ + "packageLocation": "./.yarn/cache/on-finished-npm-2.4.1-907af70f88-d20929a25e.zip/node_modules/on-finished/",\ + "packageDependencies": [\ + ["on-finished", "npm:2.4.1"],\ + ["ee-first", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["once", [\ ["npm:1.4.0", {\ "packageLocation": "./.yarn/cache/once-npm-1.4.0-ccf03ef07a-cd0a885013.zip/node_modules/once/",\ @@ -5208,6 +6359,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["only", [\ + ["npm:0.0.2", {\ + "packageLocation": "./.yarn/cache/only-npm-0.0.2-122402a3f9-d399710db8.zip/node_modules/only/",\ + "packageDependencies": [\ + ["only", "npm:0.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["optionator", [\ ["npm:0.9.1", {\ "packageLocation": "./.yarn/cache/optionator-npm-0.9.1-577e397aae-dbc6fa0656.zip/node_modules/optionator/",\ @@ -5301,6 +6461,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["parseurl", [\ + ["npm:1.3.3", {\ + "packageLocation": "./.yarn/cache/parseurl-npm-1.3.3-1542397e00-407cee8e0a.zip/node_modules/parseurl/",\ + "packageDependencies": [\ + ["parseurl", "npm:1.3.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["path-exists", [\ ["npm:4.0.0", {\ "packageLocation": "./.yarn/cache/path-exists-npm-4.0.0-e9e4f63eb0-505807199d.zip/node_modules/path-exists/",\ @@ -5337,6 +6506,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["path-to-regexp", [\ + ["npm:6.2.1", {\ + "packageLocation": "./.yarn/cache/path-to-regexp-npm-6.2.1-8ebfe03654-f0227af828.zip/node_modules/path-to-regexp/",\ + "packageDependencies": [\ + ["path-to-regexp", "npm:6.2.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["path-type", [\ ["npm:4.0.0", {\ "packageLocation": "./.yarn/cache/path-type-npm-4.0.0-10d47fc86a-5b1e2daa24.zip/node_modules/path-type/",\ @@ -5477,6 +6655,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["qs", [\ + ["npm:6.11.0", {\ + "packageLocation": "./.yarn/cache/qs-npm-6.11.0-caf1bc9dea-6e1f29dd53.zip/node_modules/qs/",\ + "packageDependencies": [\ + ["qs", "npm:6.11.0"],\ + ["side-channel", "npm:1.0.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["queue-microtask", [\ ["npm:1.2.3", {\ "packageLocation": "./.yarn/cache/queue-microtask-npm-1.2.3-fcc98e4e2d-b676f8c040.zip/node_modules/queue-microtask/",\ @@ -5486,6 +6674,19 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["raw-body", [\ + ["npm:2.5.2", {\ + "packageLocation": "./.yarn/cache/raw-body-npm-2.5.2-5cb9dfebc1-ba1583c8d8.zip/node_modules/raw-body/",\ + "packageDependencies": [\ + ["raw-body", "npm:2.5.2"],\ + ["bytes", "npm:3.1.2"],\ + ["http-errors", "npm:2.0.0"],\ + ["iconv-lite", "npm:0.4.24"],\ + ["unpipe", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["react-is", [\ ["npm:18.2.0", {\ "packageLocation": "./.yarn/cache/react-is-npm-18.2.0-0cc5edb910-e72d0ba81b.zip/node_modules/react-is/",\ @@ -5570,6 +6771,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["resolve.exports", "npm:1.1.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/resolve.exports-npm-2.0.0-c49416621c-d8bee3b0cc.zip/node_modules/resolve.exports/",\ + "packageDependencies": [\ + ["resolve.exports", "npm:2.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["retry", [\ @@ -5654,6 +6862,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["setprototypeof", [\ + ["npm:1.2.0", {\ + "packageLocation": "./.yarn/cache/setprototypeof-npm-1.2.0-0fedbdcd3a-be18cbbf70.zip/node_modules/setprototypeof/",\ + "packageDependencies": [\ + ["setprototypeof", "npm:1.2.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["shebang-command", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-6b52fe8727.zip/node_modules/shebang-command/",\ @@ -5673,6 +6890,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["side-channel", [\ + ["npm:1.0.4", {\ + "packageLocation": "./.yarn/cache/side-channel-npm-1.0.4-e1f38b9e06-351e41b947.zip/node_modules/side-channel/",\ + "packageDependencies": [\ + ["side-channel", "npm:1.0.4"],\ + ["call-bind", "npm:1.0.2"],\ + ["get-intrinsic", "npm:1.2.0"],\ + ["object-inspect", "npm:1.12.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["signal-exit", [\ ["npm:3.0.7", {\ "packageLocation": "./.yarn/cache/signal-exit-npm-3.0.7-bd270458a3-a2f098f247.zip/node_modules/signal-exit/",\ @@ -5781,6 +7010,22 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["statuses", [\ + ["npm:1.5.0", {\ + "packageLocation": "./.yarn/cache/statuses-npm-1.5.0-f88f91b2e9-c469b9519d.zip/node_modules/statuses/",\ + "packageDependencies": [\ + ["statuses", "npm:1.5.0"]\ + ],\ + "linkType": "HARD"\ + }],\ + ["npm:2.0.1", {\ + "packageLocation": "./.yarn/cache/statuses-npm-2.0.1-81d2b97fee-18c7623fdb.zip/node_modules/statuses/",\ + "packageDependencies": [\ + ["statuses", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["string-length", [\ ["npm:4.0.2", {\ "packageLocation": "./.yarn/cache/string-length-npm-4.0.2-675173c7a2-ce85533ef5.zip/node_modules/string-length/",\ @@ -5972,6 +7217,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["toidentifier", [\ + ["npm:1.0.1", {\ + "packageLocation": "./.yarn/cache/toidentifier-npm-1.0.1-f759712599-952c29e2a8.zip/node_modules/toidentifier/",\ + "packageDependencies": [\ + ["toidentifier", "npm:1.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["ts-jest", [\ ["npm:28.0.8", {\ "packageLocation": "./.yarn/cache/ts-jest-npm-28.0.8-eeca582fd6-c72e929270.zip/node_modules/ts-jest/",\ @@ -5980,6 +7234,47 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ + ["virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:28.0.8", {\ + "packageLocation": "./.yarn/__virtual__/ts-jest-virtual-8e2c80f3cb/0/cache/ts-jest-npm-28.0.8-eeca582fd6-c72e929270.zip/node_modules/ts-jest/",\ + "packageDependencies": [\ + ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:28.0.8"],\ + ["@babel/core", null],\ + ["@jest/types", null],\ + ["@types/babel-jest", null],\ + ["@types/babel__core", null],\ + ["@types/esbuild", null],\ + ["@types/jest", "npm:29.4.0"],\ + ["@types/jest__types", null],\ + ["@types/typescript", null],\ + ["babel-jest", null],\ + ["bs-logger", "npm:0.2.6"],\ + ["esbuild", null],\ + ["fast-json-stable-stringify", "npm:2.1.0"],\ + ["jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.4.3"],\ + ["jest-util", "npm:28.1.3"],\ + ["json5", "npm:2.2.3"],\ + ["lodash.memoize", "npm:4.1.2"],\ + ["make-error", "npm:1.3.6"],\ + ["semver", "npm:7.3.8"],\ + ["typescript", "patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76"],\ + ["yargs-parser", "npm:21.1.1"]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@jest/types",\ + "@types/babel-jest",\ + "@types/babel__core",\ + "@types/esbuild",\ + "@types/jest",\ + "@types/jest__types",\ + "@types/typescript",\ + "babel-jest",\ + "esbuild",\ + "jest",\ + "typescript"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:97973ff51783dc29efdf1c1cff3bd542763fb1d8ea565946db4f6425a5a443923944d5f46e5672160073e5b792b61ec2b3a0e9df4f007033f07c728780e0e4e7#npm:28.0.8", {\ "packageLocation": "./.yarn/__virtual__/ts-jest-virtual-2205321c58/0/cache/ts-jest-npm-28.0.8-eeca582fd6-c72e929270.zip/node_modules/ts-jest/",\ "packageDependencies": [\ @@ -6083,6 +7378,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["tsscmp", [\ + ["npm:1.0.6", {\ + "packageLocation": "./.yarn/cache/tsscmp-npm-1.0.6-3223087558-1512384def.zip/node_modules/tsscmp/",\ + "packageDependencies": [\ + ["tsscmp", "npm:1.0.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["tsutils", [\ ["npm:3.21.0", {\ "packageLocation": "./.yarn/cache/tsutils-npm-3.21.0-347e6636c5-1843f4c1b2.zip/node_modules/tsutils/",\ @@ -6141,6 +7445,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["type-is", [\ + ["npm:1.6.18", {\ + "packageLocation": "./.yarn/cache/type-is-npm-1.6.18-6dee4d4961-2c8e47675d.zip/node_modules/type-is/",\ + "packageDependencies": [\ + ["type-is", "npm:1.6.18"],\ + ["media-typer", "npm:0.3.0"],\ + ["mime-types", "npm:2.1.35"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["typescript", [\ ["patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76", {\ "packageLocation": "./.yarn/cache/typescript-patch-72dc6f164f-ab417a2f39.zip/node_modules/typescript/",\ @@ -6170,6 +7485,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["unpipe", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/unpipe-npm-1.0.0-2ed2a3c2bf-4fa18d8d8d.zip/node_modules/unpipe/",\ + "packageDependencies": [\ + ["unpipe", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["update-browserslist-db", [\ ["npm:1.0.10", {\ "packageLocation": "./.yarn/cache/update-browserslist-db-npm-1.0.10-676baf0b9f-12db73b4f6.zip/node_modules/update-browserslist-db/",\ @@ -6234,6 +7558,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["vary", [\ + ["npm:1.1.2", {\ + "packageLocation": "./.yarn/cache/vary-npm-1.1.2-b49f70ae63-ae0123222c.zip/node_modules/vary/",\ + "packageDependencies": [\ + ["vary", "npm:1.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["walker", [\ ["npm:1.0.8", {\ "packageLocation": "./.yarn/cache/walker-npm-1.0.8-b0a05b9478-ad7a257ea1.zip/node_modules/walker/",\ @@ -6355,6 +7688,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["ylru", [\ + ["npm:1.3.2", {\ + "packageLocation": "./.yarn/cache/ylru-npm-1.3.2-81969d097f-b6bb393114.zip/node_modules/ylru/",\ + "packageDependencies": [\ + ["ylru", "npm:1.3.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["yn", [\ ["npm:3.1.1", {\ "packageLocation": "./.yarn/cache/yn-npm-3.1.1-8ad4259784-2c487b0e14.zip/node_modules/yn/",\ diff --git a/yarn-project/json-rpc/.eslintrc.cjs b/yarn-project/json-rpc/.eslintrc.cjs new file mode 100644 index 00000000000..9cf806b1500 --- /dev/null +++ b/yarn-project/json-rpc/.eslintrc.cjs @@ -0,0 +1,6 @@ +require('@rushstack/eslint-patch/modern-module-resolution'); + +module.exports = { + extends: ['@aztec/eslint-config'], + parserOptions: { tsconfigRootDir: __dirname }, +}; diff --git a/yarn-project/json-rpc/Dockerfile b/yarn-project/json-rpc/Dockerfile new file mode 100644 index 00000000000..fae8b679966 --- /dev/null +++ b/yarn-project/json-rpc/Dockerfile @@ -0,0 +1,7 @@ +FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder +COPY aztec.js aztec.js +WORKDIR /usr/src/yarn-project/aztec.js +RUN yarn build && yarn formatting && yarn test + +FROM alpine:latest +COPY --from=builder /usr/src/yarn-project/aztec.js /usr/src/yarn-project/aztec.js \ No newline at end of file diff --git a/yarn-project/json-rpc/README.md b/yarn-project/json-rpc/README.md new file mode 100644 index 00000000000..361d4fcfee0 --- /dev/null +++ b/yarn-project/json-rpc/README.md @@ -0,0 +1,29 @@ +# json-rpc + +json-rpc +-- src +-- client +In Dapp: + +``` +const wallet = new JsonRpcClient('wallet-server.com'); +wallet.signTxRequest(accountPubKey, txRequest); +The client will send [{ name: 'PublicKey', value: accountPubKey.toString() }, { name: 'TxRequest', txRequest.toString() }] to the server. +``` + +In wallet: + +``` +const publicClient = new JsonRpcClient('public-client.com'); +const keyStore = new JsonRpcClient('key-store.com'); +Different clients for different services. +``` + +-- server +Running a wallet server: + +``` +const wallet = new WalletImplementation(); +const server = new JsonRpcServer(wallet); +server.start(8080); +``` diff --git a/yarn-project/json-rpc/package.json b/yarn-project/json-rpc/package.json new file mode 100644 index 00000000000..c54fa4eb89c --- /dev/null +++ b/yarn-project/json-rpc/package.json @@ -0,0 +1,46 @@ +{ + "name": "@aztec/json-rpc", + "version": "0.0.0", + "type": "module", + "exports": "./dest/index.js", + "scripts": { + "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", + "build:dev": "tsc -b tsconfig.dest.json --watch", + "clean": "rm -rf ./dest .tsbuildinfo", + "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" + }, + "jest": { + "preset": "ts-jest/presets/default-esm", + "globals": { + "ts-jest": { + "useESM": true + } + }, + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + "testRegex": "./src/.*\\.test\\.ts$", + "rootDir": "./src" + }, + "dependencies": { + "koa": "^2.14.1", + "koa-bodyparser": "^4.3.0", + "koa-router": "^12.0.0", + "tslib": "^2.4.0" + }, + "devDependencies": { + "@aztec/eslint-config": "workspace:^", + "@jest/globals": "^29.4.3", + "@rushstack/eslint-patch": "^1.1.4", + "@types/jest": "^29.4.0", + "@types/koa-bodyparser": "^4.3.10", + "@types/koa": "^2.0.49", + "@types/koa-router": "^7.0.42", + "@types/node": "^18.7.23", + "jest": "^29.4.3", + "ts-jest": "^28.0.7", + "ts-node": "^10.9.1", + "typescript": "^4.9.5" + } +} diff --git a/yarn-project/json-rpc/src/ClassConverter.ts b/yarn-project/json-rpc/src/ClassConverter.ts new file mode 100644 index 00000000000..aef7c43bfee --- /dev/null +++ b/yarn-project/json-rpc/src/ClassConverter.ts @@ -0,0 +1,33 @@ +import { assert, hasOwnProperty } from './jsUtils.js'; + +type AnyClass = { new (): any; fromString: (str: string) => any }; +export interface ClassConverterInput { + [className: string]: AnyClass; +} + +export class ClassConverter { + private toClass = new Map(); + private toName = new Map(); + + constructor(input: ClassConverterInput) { + for (const key of Object.keys(input)) { + this.register(key, input[key]); + } + } + register(type: string, class_: AnyClass) { + assert(hasOwnProperty(class_.prototype, 'toString'), `Class ${type} must define a toString() method.`); + assert(class_['fromString'], `Class ${type} must define a fromString() static method.`); + this.toName.set(class_, type); + this.toClass.set(type, class_); + } + toClassObj(jsonObj: { type: string; data: string }) { + const class_ = this.toClass.get(jsonObj.type); + assert(class_, `Could not find type in lookup.`); + return class_!.fromString(jsonObj.data); + } + toJsonObj(classObj: any) { + const type = this.toName.get(classObj.constructor); + assert(type, `Could not find class in lookup.`); + return { type: type!, data: classObj.toString() }; + } +} diff --git a/yarn-project/json-rpc/src/client/JsonRpcClient.ts b/yarn-project/json-rpc/src/client/JsonRpcClient.ts new file mode 100644 index 00000000000..f4bd53a9532 --- /dev/null +++ b/yarn-project/json-rpc/src/client/JsonRpcClient.ts @@ -0,0 +1,3 @@ +export class JsonRpcClient { + constructor() {} +} diff --git a/yarn-project/json-rpc/src/client/index.ts b/yarn-project/json-rpc/src/client/index.ts new file mode 100644 index 00000000000..21c164ac322 --- /dev/null +++ b/yarn-project/json-rpc/src/client/index.ts @@ -0,0 +1 @@ +export { JsonRpcClient } from './JsonRpcClient.js'; diff --git a/yarn-project/json-rpc/src/jsUtils.ts b/yarn-project/json-rpc/src/jsUtils.ts new file mode 100644 index 00000000000..362e7989230 --- /dev/null +++ b/yarn-project/json-rpc/src/jsUtils.ts @@ -0,0 +1,7 @@ +// Make sure this property was not inherited +export const hasOwnProperty = (class_: any, method: string) => Object.prototype.hasOwnProperty.call(class_, method); +export const assert = (x: any, err: string) => { + if (!x) { + throw new Error(err); + } +}; diff --git a/yarn-project/json-rpc/src/server/JsonProxy.ts b/yarn-project/json-rpc/src/server/JsonProxy.ts new file mode 100644 index 00000000000..21fce7da44b --- /dev/null +++ b/yarn-project/json-rpc/src/server/JsonProxy.ts @@ -0,0 +1,23 @@ +import { ClassConverter, ClassConverterInput } from '../ClassConverter.js'; +import { assert, hasOwnProperty } from '../jsUtils.js'; + +export class JsonProxy { + classMap: ClassConverter; + constructor(private handler: any, input: ClassConverterInput) { + this.classMap = new ClassConverter(input); + } + public call(method: string, jsonParams: any[] = []) { + const convert = (obj: any) => { + // Is this a convertable type? + if (obj?.constructor?.fromString) { + return this.classMap.toClassObj(obj); + } + // Leave alone, assume JSON-friendly + return obj; + }; + assert(hasOwnProperty(this.handler, method), 'JsonProxy: Method not found!'); + // convert the params from json representation to classes + const convertedParams = jsonParams.map(convert); + return convert(this.handler[method](...convertedParams)); + } +} diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts new file mode 100644 index 00000000000..b0d9f37e58d --- /dev/null +++ b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts @@ -0,0 +1,18 @@ +import { jest } from '@jest/globals'; + +// Contrived example +class Tree { + constructor() {} +} + +class State { + constructor(private publicTree: Tree, private privateTree: Tree) {} + getPrivateTree(): Tree { + return this.publicTree; + } + getPublicTree(): Tree { + return this.privateTree; + } +} + +describe('block_context', () => {}); diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.ts b/yarn-project/json-rpc/src/server/JsonRpcServer.ts new file mode 100644 index 00000000000..fa7aef6d422 --- /dev/null +++ b/yarn-project/json-rpc/src/server/JsonRpcServer.ts @@ -0,0 +1,63 @@ +import http from 'http'; +import Router from 'koa-router'; +import { ClassConverterInput } from '../ClassConverter.js'; +import { JsonRpcProxy } from './index.js'; +import Koa, { Context, DefaultState } from 'koa'; +import bodyParser from 'koa-bodyparser'; + +/** + * JsonRpcServer: + * minimal, dev-friendly mechanism to + */ +export class JsonRpcServer { + proxy: JsonRpcProxy; + constructor(private handler: T, input: ClassConverterInput) { + this.proxy = new JsonRpcProxy(handler, input); + } + + private getApp(prefix: string) { + const router = new Router({ prefix }); + for (const method of Object.keys(this.handler)) { + // Make sure this is a function + if (typeof (this.handler as any)[method] !== 'function') { + continue; + } + router.post(`/${method}`, async (ctx: Koa.Context) => { + const { params = [], jsonrpc, id } = ctx.request.body as any; + const result = await this.proxy.call(method, params); + ctx.body = { jsonrpc, id, result }; + ctx.status = 200; + }); + } + const exceptionHandler = async (ctx: Koa.Context, next: () => Promise) => { + try { + await next(); + } catch (err: any) { + console.log(err); + ctx.status = 400; + ctx.body = { error: err.message }; + } + }; + const app = new Koa(); + app.on('error', error => { + console.log(`KOA app-level error. ${JSON.stringify({ error })}`); + }); + app.proxy = true; + + // TODO use? + // app.use(compress({ br: false } as any)); + app.use(bodyParser()); + // TODO use? + // app.use(cors()); + app.use(exceptionHandler); + app.use(router.routes()); + app.use(router.allowedMethods()); + + return app; + } + + start(port: number, prefix = '') { + const httpServer = http.createServer(this.getApp(prefix).callback()); + httpServer.listen(port); + } +} diff --git a/yarn-project/json-rpc/src/server/index.ts b/yarn-project/json-rpc/src/server/index.ts new file mode 100644 index 00000000000..3b62ef7aba5 --- /dev/null +++ b/yarn-project/json-rpc/src/server/index.ts @@ -0,0 +1,2 @@ +export { JsonRpcServer } from './JsonRpcServer.js'; +export { JsonRpcProxy } from './JsonProxy.js'; diff --git a/yarn-project/json-rpc/tsconfig.dest.json b/yarn-project/json-rpc/tsconfig.dest.json new file mode 100644 index 00000000000..08a9c1ff256 --- /dev/null +++ b/yarn-project/json-rpc/tsconfig.dest.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["**/*.test.*", "**/fixtures/*"] +} diff --git a/yarn-project/json-rpc/tsconfig.json b/yarn-project/json-rpc/tsconfig.json new file mode 100644 index 00000000000..f2365870584 --- /dev/null +++ b/yarn-project/json-rpc/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "dest", + "rootDir": "src", + "tsBuildInfoFile": ".tsbuildinfo", + "types": ["node", "jest"] + }, + "include": ["src"] +} diff --git a/yarn-project/package.json b/yarn-project/package.json index 578aaa8833e..e3336f1294a 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -10,6 +10,7 @@ "end-to-end", "eslint-config", "ethereum.js", + "json-rpc", "kernel-simulator", "p2p", "prettier-config", diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 1cc9b1aa7d9..0127dd98642 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -142,6 +142,29 @@ __metadata: languageName: unknown linkType: soft +"@aztec/json-rpc@workspace:json-rpc": + version: 0.0.0-use.local + resolution: "@aztec/json-rpc@workspace:json-rpc" + dependencies: + "@aztec/eslint-config": "workspace:^" + "@jest/globals": ^29.4.3 + "@rushstack/eslint-patch": ^1.1.4 + "@types/jest": ^29.4.0 + "@types/koa": ^2.0.49 + "@types/koa-bodyparser": ^4.3.10 + "@types/koa-router": ^7.0.42 + "@types/node": ^18.7.23 + jest: ^29.4.3 + koa: ^2.14.1 + koa-bodyparser: ^4.3.0 + koa-router: ^12.0.0 + ts-jest: ^28.0.7 + ts-node: ^10.9.1 + tslib: ^2.4.0 + typescript: ^4.9.5 + languageName: unknown + linkType: soft + "@aztec/kernel-simulator@workspace:kernel-simulator": version: 0.0.0-use.local resolution: "@aztec/kernel-simulator@workspace:kernel-simulator" @@ -763,6 +786,20 @@ __metadata: languageName: node linkType: hard +"@jest/console@npm:^29.4.3": + version: 29.4.3 + resolution: "@jest/console@npm:29.4.3" + dependencies: + "@jest/types": ^29.4.3 + "@types/node": "*" + chalk: ^4.0.0 + jest-message-util: ^29.4.3 + jest-util: ^29.4.3 + slash: ^3.0.0 + checksum: 8d9b163febe735153b523db527742309f4d598eda22f17f04e030060329bd3da4de7420fc1f7812f7a16f08273654a7de094c4b4e8b81a99dbfc17cfb1629008 + languageName: node + linkType: hard + "@jest/core@npm:^28.1.3": version: 28.1.3 resolution: "@jest/core@npm:28.1.3" @@ -805,6 +842,47 @@ __metadata: languageName: node linkType: hard +"@jest/core@npm:^29.4.3": + version: 29.4.3 + resolution: "@jest/core@npm:29.4.3" + dependencies: + "@jest/console": ^29.4.3 + "@jest/reporters": ^29.4.3 + "@jest/test-result": ^29.4.3 + "@jest/transform": ^29.4.3 + "@jest/types": ^29.4.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + ci-info: ^3.2.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-changed-files: ^29.4.3 + jest-config: ^29.4.3 + jest-haste-map: ^29.4.3 + jest-message-util: ^29.4.3 + jest-regex-util: ^29.4.3 + jest-resolve: ^29.4.3 + jest-resolve-dependencies: ^29.4.3 + jest-runner: ^29.4.3 + jest-runtime: ^29.4.3 + jest-snapshot: ^29.4.3 + jest-util: ^29.4.3 + jest-validate: ^29.4.3 + jest-watcher: ^29.4.3 + micromatch: ^4.0.4 + pretty-format: ^29.4.3 + slash: ^3.0.0 + strip-ansi: ^6.0.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 4aa10644d66f44f051d5dd9cdcedce27acc71216dbcc5e7adebdea458e27aefe27c78f457d7efd49f58b968c35f42de5a521590876e2013593e675120b9e6ab1 + languageName: node + linkType: hard + "@jest/environment@npm:^28.1.3": version: 28.1.3 resolution: "@jest/environment@npm:28.1.3" @@ -956,6 +1034,43 @@ __metadata: languageName: node linkType: hard +"@jest/reporters@npm:^29.4.3": + version: 29.4.3 + resolution: "@jest/reporters@npm:29.4.3" + dependencies: + "@bcoe/v8-coverage": ^0.2.3 + "@jest/console": ^29.4.3 + "@jest/test-result": ^29.4.3 + "@jest/transform": ^29.4.3 + "@jest/types": ^29.4.3 + "@jridgewell/trace-mapping": ^0.3.15 + "@types/node": "*" + chalk: ^4.0.0 + collect-v8-coverage: ^1.0.0 + exit: ^0.1.2 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + istanbul-lib-coverage: ^3.0.0 + istanbul-lib-instrument: ^5.1.0 + istanbul-lib-report: ^3.0.0 + istanbul-lib-source-maps: ^4.0.0 + istanbul-reports: ^3.1.3 + jest-message-util: ^29.4.3 + jest-util: ^29.4.3 + jest-worker: ^29.4.3 + slash: ^3.0.0 + string-length: ^4.0.1 + strip-ansi: ^6.0.0 + v8-to-istanbul: ^9.0.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 7aa2e429c915bd96c3334962addd69d2bbf52065725757ddde26b293f8c4420a1e8c65363cc3e1e5ec89100a5273ccd3771bec58325a2cc0d97afdc81995073a + languageName: node + linkType: hard + "@jest/schemas@npm:^28.1.3": version: 28.1.3 resolution: "@jest/schemas@npm:28.1.3" @@ -985,6 +1100,17 @@ __metadata: languageName: node linkType: hard +"@jest/source-map@npm:^29.4.3": + version: 29.4.3 + resolution: "@jest/source-map@npm:29.4.3" + dependencies: + "@jridgewell/trace-mapping": ^0.3.15 + callsites: ^3.0.0 + graceful-fs: ^4.2.9 + checksum: 2301d225145f8123540c0be073f35a80fd26a2f5e59550fd68525d8cea580fb896d12bf65106591ffb7366a8a19790076dbebc70e0f5e6ceb51f81827ed1f89c + languageName: node + linkType: hard + "@jest/test-result@npm:^28.1.3": version: 28.1.3 resolution: "@jest/test-result@npm:28.1.3" @@ -997,6 +1123,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-result@npm:^29.4.3": + version: 29.4.3 + resolution: "@jest/test-result@npm:29.4.3" + dependencies: + "@jest/console": ^29.4.3 + "@jest/types": ^29.4.3 + "@types/istanbul-lib-coverage": ^2.0.0 + collect-v8-coverage: ^1.0.0 + checksum: 164f102b96619ec283c2c39e208b8048e4674f75bf3c3a4f2e95048ae0f9226105add684b25f10d286d91c221625f877e2c1cfc3da46c42d7e1804da239318cb + languageName: node + linkType: hard + "@jest/test-sequencer@npm:^28.1.3": version: 28.1.3 resolution: "@jest/test-sequencer@npm:28.1.3" @@ -1009,6 +1147,18 @@ __metadata: languageName: node linkType: hard +"@jest/test-sequencer@npm:^29.4.3": + version: 29.4.3 + resolution: "@jest/test-sequencer@npm:29.4.3" + dependencies: + "@jest/test-result": ^29.4.3 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.4.3 + slash: ^3.0.0 + checksum: 145e1fa9379e5be3587bde6d585b8aee5cf4442b06926928a87e9aec7de5be91b581711d627c6ca13144d244fe05e5d248c13b366b51bedc404f9dcfbfd79e9e + languageName: node + linkType: hard + "@jest/transform@npm:^28.1.3": version: 28.1.3 resolution: "@jest/transform@npm:28.1.3" @@ -1284,6 +1434,15 @@ __metadata: languageName: node linkType: hard +"@types/accepts@npm:*": + version: 1.3.5 + resolution: "@types/accepts@npm:1.3.5" + dependencies: + "@types/node": "*" + checksum: 590b7580570534a640510c071e09074cf63b5958b237a728f94322567350aea4d239f8a9d897a12b15c856b992ee4d7907e9812bb079886af2c00714e7fb3f60 + languageName: node + linkType: hard + "@types/babel__core@npm:^7.1.14": version: 7.20.0 resolution: "@types/babel__core@npm:7.20.0" @@ -1325,6 +1484,67 @@ __metadata: languageName: node linkType: hard +"@types/body-parser@npm:*": + version: 1.19.2 + resolution: "@types/body-parser@npm:1.19.2" + dependencies: + "@types/connect": "*" + "@types/node": "*" + checksum: e17840c7d747a549f00aebe72c89313d09fbc4b632b949b2470c5cb3b1cb73863901ae84d9335b567a79ec5efcfb8a28ff8e3f36bc8748a9686756b6d5681f40 + languageName: node + linkType: hard + +"@types/connect@npm:*": + version: 3.4.35 + resolution: "@types/connect@npm:3.4.35" + dependencies: + "@types/node": "*" + checksum: fe81351470f2d3165e8b12ce33542eef89ea893e36dd62e8f7d72566dfb7e448376ae962f9f3ea888547ce8b55a40020ca0e01d637fab5d99567673084542641 + languageName: node + linkType: hard + +"@types/content-disposition@npm:*": + version: 0.5.5 + resolution: "@types/content-disposition@npm:0.5.5" + checksum: fdf7379db1d509990bcf9a21d85f05aad878596f28b1418f9179f6436cb22513262c670ce88c6055054a7f5804a9303eeacb70aa59a5e11ffdc1434559db9692 + languageName: node + linkType: hard + +"@types/cookies@npm:*": + version: 0.7.7 + resolution: "@types/cookies@npm:0.7.7" + dependencies: + "@types/connect": "*" + "@types/express": "*" + "@types/keygrip": "*" + "@types/node": "*" + checksum: d3759efc1182cb0651808570ae13638677b67b0ea724eef7b174e58ffe6ea044b62c7c2715e532f76f88fce4dd8101ed32ac6fbb73226db654017924e8a2a1e6 + languageName: node + linkType: hard + +"@types/express-serve-static-core@npm:^4.17.33": + version: 4.17.33 + resolution: "@types/express-serve-static-core@npm:4.17.33" + dependencies: + "@types/node": "*" + "@types/qs": "*" + "@types/range-parser": "*" + checksum: dce580d16b85f207445af9d4053d66942b27d0c72e86153089fa00feee3e96ae336b7bedb31ed4eea9e553c99d6dd356ed6e0928f135375d9f862a1a8015adf2 + languageName: node + linkType: hard + +"@types/express@npm:*": + version: 4.17.17 + resolution: "@types/express@npm:4.17.17" + dependencies: + "@types/body-parser": "*" + "@types/express-serve-static-core": ^4.17.33 + "@types/qs": "*" + "@types/serve-static": "*" + checksum: 0196dacc275ac3ce89d7364885cb08e7fb61f53ca101f65886dbf1daf9b7eb05c0943e2e4bbd01b0cc5e50f37e0eea7e4cbe97d0304094411ac73e1b7998f4da + languageName: node + linkType: hard + "@types/graceful-fs@npm:^4.1.3": version: 4.1.6 resolution: "@types/graceful-fs@npm:4.1.6" @@ -1334,6 +1554,20 @@ __metadata: languageName: node linkType: hard +"@types/http-assert@npm:*": + version: 1.5.3 + resolution: "@types/http-assert@npm:1.5.3" + checksum: 9553e5a0b8bcfdac4b51d3fa3b89a91b5450171861a667a5b4c47204e0f4a1ca865d97396e6ceaf220e87b64d06b7a8bad7bfba15ef97acb41a87507c9940dbc + languageName: node + linkType: hard + +"@types/http-errors@npm:*": + version: 2.0.1 + resolution: "@types/http-errors@npm:2.0.1" + checksum: 3bb0c50b0a652e679a84c30cd0340d696c32ef6558518268c238840346c077f899315daaf1c26c09c57ddd5dc80510f2a7f46acd52bf949e339e35ed3ee9654f + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.4 resolution: "@types/istanbul-lib-coverage@npm:2.0.4" @@ -1376,6 +1610,63 @@ __metadata: languageName: node linkType: hard +"@types/keygrip@npm:*": + version: 1.0.2 + resolution: "@types/keygrip@npm:1.0.2" + checksum: 60bc2738a4f107070ee3d96f44709cb38f3a96c7ccabab09f56c1b2b4d85f869fd8fb9f1f2937e863d0e9e781f005c2223b823bf32b859185b4f52370c352669 + languageName: node + linkType: hard + +"@types/koa-bodyparser@npm:^4.3.10": + version: 4.3.10 + resolution: "@types/koa-bodyparser@npm:4.3.10" + dependencies: + "@types/koa": "*" + checksum: 4b4cd176815a6c1fb0d593bfea03de1285e606d3a96e56ad3691144e35061750ed95e4ecf2ff8e25599d360a93646e29dbb167fdfaaa73ccf87ca5b6141ff0db + languageName: node + linkType: hard + +"@types/koa-compose@npm:*": + version: 3.2.5 + resolution: "@types/koa-compose@npm:3.2.5" + dependencies: + "@types/koa": "*" + checksum: 5d1147c4b057eb158195f442f0384f06503f3e69dba99fb517b30a05261a9f92928945c12bb1cfc17a5b7d60db003f38b455a3a9b125f12e4fc81fffa396b3cf + languageName: node + linkType: hard + +"@types/koa-router@npm:^7.0.42": + version: 7.4.4 + resolution: "@types/koa-router@npm:7.4.4" + dependencies: + "@types/koa": "*" + checksum: 23ff5b725daa1427dc822602f5d4fdcecca5f990595af48879e41338a9c71819ae312326028eef4645beb6ea32ea852416e2f0761a2abd5bf80c2575a3301837 + languageName: node + linkType: hard + +"@types/koa@npm:*, @types/koa@npm:^2.0.49": + version: 2.13.5 + resolution: "@types/koa@npm:2.13.5" + dependencies: + "@types/accepts": "*" + "@types/content-disposition": "*" + "@types/cookies": "*" + "@types/http-assert": "*" + "@types/http-errors": "*" + "@types/keygrip": "*" + "@types/koa-compose": "*" + "@types/node": "*" + checksum: e3b634d934b79ce8f394bf4130511596081f9c073dbfb4309aa32e4c421c47049a002b65111f8d9687eabec55d5a27b1b9ae0699afa83894cb7032c3536bfa17 + languageName: node + linkType: hard + +"@types/mime@npm:*": + version: 3.0.1 + resolution: "@types/mime@npm:3.0.1" + checksum: 4040fac73fd0cea2460e29b348c1a6173da747f3a87da0dbce80dd7a9355a3d0e51d6d9a401654f3e5550620e3718b5a899b2ec1debf18424e298a2c605346e7 + languageName: node + linkType: hard + "@types/node@npm:*, @types/node@npm:^18.7.23": version: 18.14.2 resolution: "@types/node@npm:18.14.2" @@ -1390,6 +1681,20 @@ __metadata: languageName: node linkType: hard +"@types/qs@npm:*": + version: 6.9.7 + resolution: "@types/qs@npm:6.9.7" + checksum: 7fd6f9c25053e9b5bb6bc9f9f76c1d89e6c04f7707a7ba0e44cc01f17ef5284adb82f230f542c2d5557d69407c9a40f0f3515e8319afd14e1e16b5543ac6cdba + languageName: node + linkType: hard + +"@types/range-parser@npm:*": + version: 1.2.4 + resolution: "@types/range-parser@npm:1.2.4" + checksum: b7c0dfd5080a989d6c8bb0b6750fc0933d9acabeb476da6fe71d8bdf1ab65e37c136169d84148034802f48378ab94e3c37bb4ef7656b2bec2cb9c0f8d4146a95 + languageName: node + linkType: hard + "@types/semver@npm:^7.3.12": version: 7.3.13 resolution: "@types/semver@npm:7.3.13" @@ -1397,6 +1702,16 @@ __metadata: languageName: node linkType: hard +"@types/serve-static@npm:*": + version: 1.15.1 + resolution: "@types/serve-static@npm:1.15.1" + dependencies: + "@types/mime": "*" + "@types/node": "*" + checksum: 2e078bdc1e458c7dfe69e9faa83cc69194b8896cce57cb745016580543c7ab5af07fdaa8ac1765eb79524208c81017546f66056f44d1204f812d72810613de36 + languageName: node + linkType: hard + "@types/stack-utils@npm:^2.0.0": version: 2.0.1 resolution: "@types/stack-utils@npm:2.0.1" @@ -1548,6 +1863,16 @@ __metadata: languageName: node linkType: hard +"accepts@npm:^1.3.5": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: ~2.1.34 + negotiator: 0.6.3 + checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4 + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -1730,6 +2055,23 @@ __metadata: languageName: node linkType: hard +"babel-jest@npm:^29.4.3": + version: 29.4.3 + resolution: "babel-jest@npm:29.4.3" + dependencies: + "@jest/transform": ^29.4.3 + "@types/babel__core": ^7.1.14 + babel-plugin-istanbul: ^6.1.1 + babel-preset-jest: ^29.4.3 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + slash: ^3.0.0 + peerDependencies: + "@babel/core": ^7.8.0 + checksum: a1a95937adb5e717dbffc2eb9e583fa6d26c7e5d5b07bb492a2d7f68631510a363e9ff097eafb642ad642dfac9dc2b13872b584f680e166a4f0922c98ea95853 + languageName: node + linkType: hard + "babel-plugin-istanbul@npm:^6.1.1": version: 6.1.1 resolution: "babel-plugin-istanbul@npm:6.1.1" @@ -1755,6 +2097,18 @@ __metadata: languageName: node linkType: hard +"babel-plugin-jest-hoist@npm:^29.4.3": + version: 29.4.3 + resolution: "babel-plugin-jest-hoist@npm:29.4.3" + dependencies: + "@babel/template": ^7.3.3 + "@babel/types": ^7.3.3 + "@types/babel__core": ^7.1.14 + "@types/babel__traverse": ^7.0.6 + checksum: c8702a6db6b30ec39dfb9f8e72b501c13895231ed80b15ed2648448f9f0c7b7cc4b1529beac31802ae655f63479a05110ca612815aa25fb1b0e6c874e1589137 + languageName: node + linkType: hard + "babel-preset-current-node-syntax@npm:^1.0.0": version: 1.0.1 resolution: "babel-preset-current-node-syntax@npm:1.0.1" @@ -1789,6 +2143,18 @@ __metadata: languageName: node linkType: hard +"babel-preset-jest@npm:^29.4.3": + version: 29.4.3 + resolution: "babel-preset-jest@npm:29.4.3" + dependencies: + babel-plugin-jest-hoist: ^29.4.3 + babel-preset-current-node-syntax: ^1.0.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a091721861ea2f8d969ace8fe06570cff8f2e847dbc6e4800abacbe63f72131abde615ce0a3b6648472c97e55a5be7f8bf7ae381e2b194ad2fa1737096febcf5 + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -1863,6 +2229,13 @@ __metadata: languageName: node linkType: hard +"bytes@npm:3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: e4bcd3948d289c5127591fbedf10c0b639ccbf00243504e4e127374a15c3bc8eed0d28d4aaab08ff6f1cf2abc0cce6ba3085ed32f4f90e82a5683ce0014e1b6e + languageName: node + linkType: hard + "cacache@npm:^16.1.0": version: 16.1.3 resolution: "cacache@npm:16.1.3" @@ -1889,6 +2262,26 @@ __metadata: languageName: node linkType: hard +"cache-content-type@npm:^1.0.0": + version: 1.0.1 + resolution: "cache-content-type@npm:1.0.1" + dependencies: + mime-types: ^2.1.18 + ylru: ^1.2.0 + checksum: 18db4d59452669ccbfd7146a1510a37eb28e9eccf18ca7a4eb603dff2edc5cccdca7498fc3042a2978f76f11151fba486eb9eb69d9afa3fb124957870aef4fd3 + languageName: node + linkType: hard + +"call-bind@npm:^1.0.0": + version: 1.0.2 + resolution: "call-bind@npm:1.0.2" + dependencies: + function-bind: ^1.1.1 + get-intrinsic: ^1.0.2 + checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 + languageName: node + linkType: hard + "callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -1984,6 +2377,18 @@ __metadata: languageName: node linkType: hard +"co-body@npm:^6.0.0": + version: 6.1.0 + resolution: "co-body@npm:6.1.0" + dependencies: + inflation: ^2.0.0 + qs: ^6.5.2 + raw-body: ^2.3.3 + type-is: ^1.6.16 + checksum: d0a78831a6651f2085fce16b0ecdc49f45fb5baf4f94148c2f499e7ec89d188205362548b9c500eae15a819360cfda208079e68a72c204cf66ca3ffa2fc0f57e + languageName: node + linkType: hard + "co@npm:^4.6.0": version: 4.6.0 resolution: "co@npm:4.6.0" @@ -2060,6 +2465,22 @@ __metadata: languageName: node linkType: hard +"content-disposition@npm:~0.5.2": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: 5.2.1 + checksum: afb9d545e296a5171d7574fcad634b2fdf698875f4006a9dd04a3e1333880c5c0c98d47b560d01216fb6505a54a2ba6a843ee3a02ec86d7e911e8315255f56c3 + languageName: node + linkType: hard + +"content-type@npm:^1.0.4": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 + languageName: node + linkType: hard + "convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": version: 1.9.0 resolution: "convert-source-map@npm:1.9.0" @@ -2074,6 +2495,23 @@ __metadata: languageName: node linkType: hard +"cookies@npm:~0.8.0": + version: 0.8.0 + resolution: "cookies@npm:0.8.0" + dependencies: + depd: ~2.0.0 + keygrip: ~1.1.0 + checksum: 806055a44f128705265b1bc6a853058da18bf80dea3654ad99be20985b1fa1b14f86c1eef73644aab8071241f8a78acd57202b54c4c5c70769fc694fbb9c4edc + languageName: node + linkType: hard + +"copy-to@npm:^2.0.1": + version: 2.0.1 + resolution: "copy-to@npm:2.0.1" + checksum: 05ea12875bdc96ae053a3b30148e9d992026035ff2bfcc0b615e8d49d1cf8fc3d1f40843f9a4b7b1b6d9118eeebcba31e621076d7de525828aa9c07d22a81dab + languageName: node + linkType: hard + "create-require@npm:^1.1.0": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -2111,9 +2549,16 @@ __metadata: languageName: node linkType: hard -"deep-is@npm:^0.1.3": - version: 0.1.4 - resolution: "deep-is@npm:0.1.4" +"deep-equal@npm:~1.0.1": + version: 1.0.1 + resolution: "deep-equal@npm:1.0.1" + checksum: 5af8cbfcebf190491878a498caccc7dc9592f8ebd1685b976eacc3825619d222b5e929923163b92c4f414494e2b884f7ebf00c022e8198e8292deb70dd9785f4 + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 languageName: node linkType: hard @@ -2132,13 +2577,27 @@ __metadata: languageName: node linkType: hard -"depd@npm:^1.1.2": +"depd@npm:2.0.0, depd@npm:^2.0.0, depd@npm:~2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: abbe19c768c97ee2eed6282d8ce3031126662252c58d711f646921c9623f9052e3e1906443066beec1095832f534e57c523b7333f8e7e0d93051ab6baef5ab3a + languageName: node + linkType: hard + +"depd@npm:^1.1.2, depd@npm:~1.1.2": version: 1.1.2 resolution: "depd@npm:1.1.2" checksum: 6b406620d269619852885ce15965272b829df6f409724415e0002c8632ab6a8c0a08ec1f0bd2add05dc7bd7507606f7e2cc034fa24224ab829580040b835ecd9 languageName: node linkType: hard +"destroy@npm:^1.0.4": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 + languageName: node + linkType: hard + "detect-newline@npm:^3.0.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" @@ -2185,6 +2644,13 @@ __metadata: languageName: node linkType: hard +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f + languageName: node + linkType: hard + "electron-to-chromium@npm:^1.4.284": version: 1.4.311 resolution: "electron-to-chromium@npm:1.4.311" @@ -2199,6 +2665,13 @@ __metadata: languageName: node linkType: hard +"emittery@npm:^0.13.1": + version: 0.13.1 + resolution: "emittery@npm:0.13.1" + checksum: 2b089ab6306f38feaabf4f6f02792f9ec85fc054fda79f44f6790e61bbf6bc4e1616afb9b232e0c5ec5289a8a452f79bfa6d905a6fd64e94b49981f0934001c6 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -2206,6 +2679,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:^1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -2245,6 +2725,13 @@ __metadata: languageName: node linkType: hard +"escape-html@npm:^1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 + languageName: node + linkType: hard + "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -2589,6 +3076,13 @@ __metadata: languageName: node linkType: hard +"fresh@npm:~0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 + languageName: node + linkType: hard + "fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -2661,6 +3155,17 @@ __metadata: languageName: node linkType: hard +"get-intrinsic@npm:^1.0.2": + version: 1.2.0 + resolution: "get-intrinsic@npm:1.2.0" + dependencies: + function-bind: ^1.1.1 + has: ^1.0.3 + has-symbols: ^1.0.3 + checksum: 78fc0487b783f5c58cf2dccafc3ae656ee8d2d8062a8831ce4a95e7057af4587a1d4882246c033aca0a7b4965276f4802b45cc300338d1b77a73d3e3e3f4877d + languageName: node + linkType: hard + "get-package-type@npm:^0.1.0": version: 0.1.0 resolution: "get-package-type@npm:0.1.0" @@ -2778,6 +3283,22 @@ __metadata: languageName: node linkType: hard +"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.0": + version: 1.0.0 + resolution: "has-tostringtag@npm:1.0.0" + dependencies: + has-symbols: ^1.0.2 + checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c + languageName: node + linkType: hard + "has-unicode@npm:^2.0.1": version: 2.0.1 resolution: "has-unicode@npm:2.0.1" @@ -2801,6 +3322,16 @@ __metadata: languageName: node linkType: hard +"http-assert@npm:^1.3.0": + version: 1.5.0 + resolution: "http-assert@npm:1.5.0" + dependencies: + deep-equal: ~1.0.1 + http-errors: ~1.8.0 + checksum: 69c9b3c14cf8b2822916360a365089ce936c883c49068f91c365eccba5c141a9964d19fdda589150a480013bf503bf37d8936c732e9635819339e730ab0e7527 + languageName: node + linkType: hard + "http-cache-semantics@npm:^4.1.0": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -2808,6 +3339,32 @@ __metadata: languageName: node linkType: hard +"http-errors@npm:2.0.0, http-errors@npm:^2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920 + languageName: node + linkType: hard + +"http-errors@npm:^1.6.3, http-errors@npm:~1.8.0": + version: 1.8.1 + resolution: "http-errors@npm:1.8.1" + dependencies: + depd: ~1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: ">= 1.5.0 < 2" + toidentifier: 1.0.1 + checksum: d3c7e7e776fd51c0a812baff570bdf06fe49a5dc448b700ab6171b1250e4cf7db8b8f4c0b133e4bfe2451022a5790c1ca6c2cae4094dedd6ac8304a1267f91d2 + languageName: node + linkType: hard + "http-proxy-agent@npm:^5.0.0": version: 5.0.0 resolution: "http-proxy-agent@npm:5.0.0" @@ -2845,6 +3402,15 @@ __metadata: languageName: node linkType: hard +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: ">= 2.1.2 < 3" + checksum: bd9f120f5a5b306f0bc0b9ae1edeb1577161503f5f8252a20f1a9e56ef8775c9959fd01c55f2d3a39d9a8abaf3e30c1abeb1895f367dcbbe0a8fd1c9ca01c4f6 + languageName: node + linkType: hard + "iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" @@ -2904,6 +3470,13 @@ __metadata: languageName: node linkType: hard +"inflation@npm:^2.0.0": + version: 2.0.0 + resolution: "inflation@npm:2.0.0" + checksum: a0494871b12275afdef9e2710ee1af1e0fc642b04613a9be69c05ef8b5e9627f3bd7d358a937fa47aa20235ee7313a4f30255048533add0ad4918beb918a586e + languageName: node + linkType: hard + "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -2914,7 +3487,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 @@ -2965,6 +3538,15 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.7": + version: 1.0.10 + resolution: "is-generator-function@npm:1.0.10" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -3071,6 +3653,16 @@ __metadata: languageName: node linkType: hard +"jest-changed-files@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-changed-files@npm:29.4.3" + dependencies: + execa: ^5.0.0 + p-limit: ^3.1.0 + checksum: 9a70bd8e92b37e18ad26d8bea97c516f41119fb7046b4255a13c76d557b0e54fa0629726de5a093fadfd6a0a08ce45da65a57086664d505b8db4b3133133e141 + languageName: node + linkType: hard + "jest-circus@npm:^28.1.3": version: 28.1.3 resolution: "jest-circus@npm:28.1.3" @@ -3098,6 +3690,33 @@ __metadata: languageName: node linkType: hard +"jest-circus@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-circus@npm:29.4.3" + dependencies: + "@jest/environment": ^29.4.3 + "@jest/expect": ^29.4.3 + "@jest/test-result": ^29.4.3 + "@jest/types": ^29.4.3 + "@types/node": "*" + chalk: ^4.0.0 + co: ^4.6.0 + dedent: ^0.7.0 + is-generator-fn: ^2.0.0 + jest-each: ^29.4.3 + jest-matcher-utils: ^29.4.3 + jest-message-util: ^29.4.3 + jest-runtime: ^29.4.3 + jest-snapshot: ^29.4.3 + jest-util: ^29.4.3 + p-limit: ^3.1.0 + pretty-format: ^29.4.3 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 2739bef9c888743b49ff3fe303131381618e5d2f250f613a91240d9c86e19e6874fc904cbd8bcb02ec9ec59a84e5dae4ffec929f0c6171e87ddbc05508a137f4 + languageName: node + linkType: hard + "jest-cli@npm:^28.1.3": version: 28.1.3 resolution: "jest-cli@npm:28.1.3" @@ -3125,6 +3744,33 @@ __metadata: languageName: node linkType: hard +"jest-cli@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-cli@npm:29.4.3" + dependencies: + "@jest/core": ^29.4.3 + "@jest/test-result": ^29.4.3 + "@jest/types": ^29.4.3 + chalk: ^4.0.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + import-local: ^3.0.2 + jest-config: ^29.4.3 + jest-util: ^29.4.3 + jest-validate: ^29.4.3 + prompts: ^2.0.1 + yargs: ^17.3.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: f4c9f6d76cde2c60a4169acbebb3f862728be03bcf3fe0077d2e55da7f9f3c3e9483cfa6e936832d35eabf96ee5ebf0300c4b0bd43cffff099801793466bfdd8 + languageName: node + linkType: hard + "jest-config@npm:^28.1.3": version: 28.1.3 resolution: "jest-config@npm:28.1.3" @@ -3163,6 +3809,44 @@ __metadata: languageName: node linkType: hard +"jest-config@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-config@npm:29.4.3" + dependencies: + "@babel/core": ^7.11.6 + "@jest/test-sequencer": ^29.4.3 + "@jest/types": ^29.4.3 + babel-jest: ^29.4.3 + chalk: ^4.0.0 + ci-info: ^3.2.0 + deepmerge: ^4.2.2 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-circus: ^29.4.3 + jest-environment-node: ^29.4.3 + jest-get-type: ^29.4.3 + jest-regex-util: ^29.4.3 + jest-resolve: ^29.4.3 + jest-runner: ^29.4.3 + jest-util: ^29.4.3 + jest-validate: ^29.4.3 + micromatch: ^4.0.4 + parse-json: ^5.2.0 + pretty-format: ^29.4.3 + slash: ^3.0.0 + strip-json-comments: ^3.1.1 + peerDependencies: + "@types/node": "*" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + ts-node: + optional: true + checksum: 92f9a9c6850b18682cb01892774a33967472af23a5844438d8c68077d5f2a29b15b665e4e4db7de3d74002a6dca158cd5b2cb9f5debfd2cce5e1aee6c74e3873 + languageName: node + linkType: hard + "jest-diff@npm:^28.1.3": version: 28.1.3 resolution: "jest-diff@npm:28.1.3" @@ -3196,6 +3880,15 @@ __metadata: languageName: node linkType: hard +"jest-docblock@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-docblock@npm:29.4.3" + dependencies: + detect-newline: ^3.0.0 + checksum: e0e9df1485bb8926e5b33478cdf84b3387d9caf3658e7dc1eaa6dc34cb93dea0d2d74797f6e940f0233a88f3dadd60957f2288eb8f95506361f85b84bf8661df + languageName: node + linkType: hard + "jest-each@npm:^28.1.3": version: 28.1.3 resolution: "jest-each@npm:28.1.3" @@ -3209,6 +3902,19 @@ __metadata: languageName: node linkType: hard +"jest-each@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-each@npm:29.4.3" + dependencies: + "@jest/types": ^29.4.3 + chalk: ^4.0.0 + jest-get-type: ^29.4.3 + jest-util: ^29.4.3 + pretty-format: ^29.4.3 + checksum: 1f72738338399efab0139eaea18bc198be0c6ed889770c8cbfa70bf9c724e8171fe1d3a29a94f9f39b8493ee6b2529bb350fb7c7c75e0d7eddfd28c253c79f9d + languageName: node + linkType: hard + "jest-environment-node@npm:^28.1.3": version: 28.1.3 resolution: "jest-environment-node@npm:28.1.3" @@ -3223,6 +3929,20 @@ __metadata: languageName: node linkType: hard +"jest-environment-node@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-environment-node@npm:29.4.3" + dependencies: + "@jest/environment": ^29.4.3 + "@jest/fake-timers": ^29.4.3 + "@jest/types": ^29.4.3 + "@types/node": "*" + jest-mock: ^29.4.3 + jest-util: ^29.4.3 + checksum: 3c7362edfdbd516e83af7367c95dde35761a482b174de9735c07633405486ec73e19624e9bea4333fca33c24e8d65eaa1aa6594e0cb6bfeeeb564ccc431ee61d + languageName: node + linkType: hard + "jest-get-type@npm:^28.0.2": version: 28.0.2 resolution: "jest-get-type@npm:28.0.2" @@ -3293,6 +4013,16 @@ __metadata: languageName: node linkType: hard +"jest-leak-detector@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-leak-detector@npm:29.4.3" + dependencies: + jest-get-type: ^29.4.3 + pretty-format: ^29.4.3 + checksum: ec2b45e6f0abce81bd0dd0f6fd06b433c24d1ec865267af7640fae540ec868b93752598e407a9184d9c7419cbf32e8789007cc8c1be1a84f8f7321a0f8ad01f1 + languageName: node + linkType: hard + "jest-matcher-utils@npm:^28.1.3": version: 28.1.3 resolution: "jest-matcher-utils@npm:28.1.3" @@ -3408,6 +4138,16 @@ __metadata: languageName: node linkType: hard +"jest-resolve-dependencies@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-resolve-dependencies@npm:29.4.3" + dependencies: + jest-regex-util: ^29.4.3 + jest-snapshot: ^29.4.3 + checksum: 3ad934cd2170c9658d8800f84a975dafc866ec85b7ce391c640c09c3744ced337787620d8667dc8d1fa5e0b1493f973caa1a1bb980e4e6a50b46a1720baf0bd1 + languageName: node + linkType: hard + "jest-resolve@npm:^28.1.3": version: 28.1.3 resolution: "jest-resolve@npm:28.1.3" @@ -3425,6 +4165,23 @@ __metadata: languageName: node linkType: hard +"jest-resolve@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-resolve@npm:29.4.3" + dependencies: + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.4.3 + jest-pnp-resolver: ^1.2.2 + jest-util: ^29.4.3 + jest-validate: ^29.4.3 + resolve: ^1.20.0 + resolve.exports: ^2.0.0 + slash: ^3.0.0 + checksum: 056a66beccf833f3c7e5a8fc9bfec218886e87b0b103decdbdf11893669539df489d1490cd6d5f0eea35731e8be0d2e955a6710498f970d2eae734da4df029dc + languageName: node + linkType: hard + "jest-runner@npm:^28.1.3": version: 28.1.3 resolution: "jest-runner@npm:28.1.3" @@ -3454,6 +4211,35 @@ __metadata: languageName: node linkType: hard +"jest-runner@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-runner@npm:29.4.3" + dependencies: + "@jest/console": ^29.4.3 + "@jest/environment": ^29.4.3 + "@jest/test-result": ^29.4.3 + "@jest/transform": ^29.4.3 + "@jest/types": ^29.4.3 + "@types/node": "*" + chalk: ^4.0.0 + emittery: ^0.13.1 + graceful-fs: ^4.2.9 + jest-docblock: ^29.4.3 + jest-environment-node: ^29.4.3 + jest-haste-map: ^29.4.3 + jest-leak-detector: ^29.4.3 + jest-message-util: ^29.4.3 + jest-resolve: ^29.4.3 + jest-runtime: ^29.4.3 + jest-util: ^29.4.3 + jest-watcher: ^29.4.3 + jest-worker: ^29.4.3 + p-limit: ^3.1.0 + source-map-support: 0.5.13 + checksum: c41108e5da01e0b8fdc2a06c5042eb49bb1d8db0e0d4651769fd1b9fe84ab45188617c11a3a8e1c83748b29bfe57dd77001ec57e86e3e3c30f3534e0314f8882 + languageName: node + linkType: hard + "jest-runtime@npm:^28.1.3": version: 28.1.3 resolution: "jest-runtime@npm:28.1.3" @@ -3484,6 +4270,36 @@ __metadata: languageName: node linkType: hard +"jest-runtime@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-runtime@npm:29.4.3" + dependencies: + "@jest/environment": ^29.4.3 + "@jest/fake-timers": ^29.4.3 + "@jest/globals": ^29.4.3 + "@jest/source-map": ^29.4.3 + "@jest/test-result": ^29.4.3 + "@jest/transform": ^29.4.3 + "@jest/types": ^29.4.3 + "@types/node": "*" + chalk: ^4.0.0 + cjs-module-lexer: ^1.0.0 + collect-v8-coverage: ^1.0.0 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.4.3 + jest-message-util: ^29.4.3 + jest-mock: ^29.4.3 + jest-regex-util: ^29.4.3 + jest-resolve: ^29.4.3 + jest-snapshot: ^29.4.3 + jest-util: ^29.4.3 + slash: ^3.0.0 + strip-bom: ^4.0.0 + checksum: b99f8a910d1a38e7476058ba04ad44dfd3d93e837bb7c301d691e646a1085412fde87f06fbe271c9145f0e72d89400bfa7f6994bc30d456c7742269f37d0f570 + languageName: node + linkType: hard + "jest-snapshot@npm:^28.1.3": version: 28.1.3 resolution: "jest-snapshot@npm:28.1.3" @@ -3589,6 +4405,20 @@ __metadata: languageName: node linkType: hard +"jest-validate@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-validate@npm:29.4.3" + dependencies: + "@jest/types": ^29.4.3 + camelcase: ^6.2.0 + chalk: ^4.0.0 + jest-get-type: ^29.4.3 + leven: ^3.1.0 + pretty-format: ^29.4.3 + checksum: 983e56430d86bed238448cae031535c1d908f760aa312cd4a4ec0e92f3bc1b6675415ddf57cdeceedb8ad9c698e5bcd10f0a856dfc93a8923bdecc7733f4ba80 + languageName: node + linkType: hard + "jest-watcher@npm:^28.1.3": version: 28.1.3 resolution: "jest-watcher@npm:28.1.3" @@ -3605,6 +4435,22 @@ __metadata: languageName: node linkType: hard +"jest-watcher@npm:^29.4.3": + version: 29.4.3 + resolution: "jest-watcher@npm:29.4.3" + dependencies: + "@jest/test-result": ^29.4.3 + "@jest/types": ^29.4.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + emittery: ^0.13.1 + jest-util: ^29.4.3 + string-length: ^4.0.1 + checksum: 44b64991b3414db853c3756f14690028f4edef7aebfb204a4291cc1901c2239fa27a8687c5c5abbecc74bf613e0bb9b1378bf766430c9febcc71e9c0cb5ad8fc + languageName: node + linkType: hard + "jest-worker@npm:^28.1.3": version: 28.1.3 resolution: "jest-worker@npm:28.1.3" @@ -3647,6 +4493,25 @@ __metadata: languageName: node linkType: hard +"jest@npm:^29.4.3": + version: 29.4.3 + resolution: "jest@npm:29.4.3" + dependencies: + "@jest/core": ^29.4.3 + "@jest/types": ^29.4.3 + import-local: ^3.0.2 + jest-cli: ^29.4.3 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 084d10d1ceaade3c40e6d3bbd71b9b71b8919ba6fbd6f1f6699bdc259a6ba2f7350c7ccbfa10c11f7e3e01662853650a6244210179542fe4ba87e77dc3f3109f + languageName: node + linkType: hard + "js-sdsl@npm:^4.1.4": version: 4.3.0 resolution: "js-sdsl@npm:4.3.0" @@ -3723,6 +4588,15 @@ __metadata: languageName: node linkType: hard +"keygrip@npm:~1.1.0": + version: 1.1.0 + resolution: "keygrip@npm:1.1.0" + dependencies: + tsscmp: 1.0.6 + checksum: 078cd16a463d187121f0a27c1c9c95c52ad392b620f823431689f345a0501132cee60f6e96914b07d570105af470b96960402accd6c48a0b1f3cd8fac4fa2cae + languageName: node + linkType: hard + "kleur@npm:^3.0.3": version: 3.0.3 resolution: "kleur@npm:3.0.3" @@ -3730,6 +4604,76 @@ __metadata: languageName: node linkType: hard +"koa-bodyparser@npm:^4.3.0": + version: 4.3.0 + resolution: "koa-bodyparser@npm:4.3.0" + dependencies: + co-body: ^6.0.0 + copy-to: ^2.0.1 + checksum: c227fe0fb5a55b98fc91d865e80229b60178d216d53b732b07833eb38f48a7ed6aa768a083bc06e359db33298547e9a65842fbe9d3f0fdaf5149fe0becafc88f + languageName: node + linkType: hard + +"koa-compose@npm:^4.1.0": + version: 4.1.0 + resolution: "koa-compose@npm:4.1.0" + checksum: 46cb16792d96425e977c2ae4e5cb04930280740e907242ec9c25e3fb8b4a1d7b54451d7432bc24f40ec62255edea71894d2ceeb8238501842b4e48014f2e83db + languageName: node + linkType: hard + +"koa-convert@npm:^2.0.0": + version: 2.0.0 + resolution: "koa-convert@npm:2.0.0" + dependencies: + co: ^4.6.0 + koa-compose: ^4.1.0 + checksum: 7385b3391995f59c1312142e110d5dff677f9850dbfbcf387cd36a7b0af03b5d26e82b811eb9bb008b4f3e661cdab1f8817596e46b1929da2cf6e97a2f7456ed + languageName: node + linkType: hard + +"koa-router@npm:^12.0.0": + version: 12.0.0 + resolution: "koa-router@npm:12.0.0" + dependencies: + http-errors: ^2.0.0 + koa-compose: ^4.1.0 + methods: ^1.1.2 + path-to-regexp: ^6.2.1 + checksum: 29b02fd96972c037e805f6ce2626c971f4fd9cba04005bfedc080ab425d31b4b1cfe2ebc000b26e4a45e68215a3a3ed557f836ba486ea0d2f1e7e78fc95f8dca + languageName: node + linkType: hard + +"koa@npm:^2.14.1": + version: 2.14.1 + resolution: "koa@npm:2.14.1" + dependencies: + accepts: ^1.3.5 + cache-content-type: ^1.0.0 + content-disposition: ~0.5.2 + content-type: ^1.0.4 + cookies: ~0.8.0 + debug: ^4.3.2 + delegates: ^1.0.0 + depd: ^2.0.0 + destroy: ^1.0.4 + encodeurl: ^1.0.2 + escape-html: ^1.0.3 + fresh: ~0.5.2 + http-assert: ^1.3.0 + http-errors: ^1.6.3 + is-generator-function: ^1.0.7 + koa-compose: ^4.1.0 + koa-convert: ^2.0.0 + on-finished: ^2.3.0 + only: ~0.0.2 + parseurl: ^1.3.2 + statuses: ^1.5.0 + type-is: ^1.6.16 + vary: ^1.1.2 + checksum: 84cfce48d72cf434831bd9f4f06beb3815da030325a7e89b13ee684f5afd158221e16c2d450ca637b221aa0c4a0ab235edd129e4efea656dc5d8384801d3e90f + languageName: node + linkType: hard + "leven@npm:^3.1.0": version: 3.1.0 resolution: "leven@npm:3.1.0" @@ -3860,6 +4804,13 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: af1b38516c28ec95d6b0826f6c8f276c58aec391f76be42aa07646b4e39d317723e869700933ca6995b056db4b09a78c92d5440dc23657e6764be5d28874bba1 + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -3874,6 +4825,13 @@ __metadata: languageName: node linkType: hard +"methods@npm:^1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 0917ff4041fa8e2f2fda5425a955fe16ca411591fbd123c0d722fcf02b73971ed6f764d85f0a6f547ce49ee0221ce2c19a5fa692157931cecb422984f1dcd13a + languageName: node + linkType: hard + "micromatch@npm:^4.0.4": version: 4.0.5 resolution: "micromatch@npm:4.0.5" @@ -3884,6 +4842,22 @@ __metadata: languageName: node linkType: hard +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + +"mime-types@npm:^2.1.18, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: 1.52.0 + checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836 + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -4023,7 +4997,7 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 @@ -4103,6 +5077,22 @@ __metadata: languageName: node linkType: hard +"object-inspect@npm:^1.9.0": + version: 1.12.3 + resolution: "object-inspect@npm:1.12.3" + checksum: dabfd824d97a5f407e6d5d24810d888859f6be394d8b733a77442b277e0808860555176719c5905e765e3743a7cada6b8b0a3b85e5331c530fd418cc8ae991db + languageName: node + linkType: hard + +"on-finished@npm:^2.3.0": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: 1.1.1 + checksum: d20929a25e7f0bb62f937a425b5edeb4e4cde0540d77ba146ec9357f00b0d497cdb3b9b05b9c8e46222407d1548d08166bff69cc56dfa55ba0e4469228920ff0 + languageName: node + linkType: hard + "once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -4121,6 +5111,13 @@ __metadata: languageName: node linkType: hard +"only@npm:~0.0.2": + version: 0.0.2 + resolution: "only@npm:0.0.2" + checksum: d399710db867a1ef436dd3ce74499c87ece794aa81ab0370b5d153968766ee4aed2f98d3f92fc87c963e45b7a74d400d6f463ef651a5e7cfb861b15e88e9efe6 + languageName: node + linkType: hard + "optionator@npm:^0.9.1": version: 0.9.1 resolution: "optionator@npm:0.9.1" @@ -4208,6 +5205,13 @@ __metadata: languageName: node linkType: hard +"parseurl@npm:^1.3.2": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + languageName: node + linkType: hard + "path-exists@npm:^4.0.0": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -4236,6 +5240,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^6.2.1": + version: 6.2.1 + resolution: "path-to-regexp@npm:6.2.1" + checksum: f0227af8284ea13300f4293ba111e3635142f976d4197f14d5ad1f124aebd9118783dd2e5f1fe16f7273743cc3dbeddfb7493f237bb27c10fdae07020cc9b698 + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -4346,6 +5357,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.5.2": + version: 6.11.0 + resolution: "qs@npm:6.11.0" + dependencies: + side-channel: ^1.0.4 + checksum: 6e1f29dd5385f7488ec74ac7b6c92f4d09a90408882d0c208414a34dd33badc1a621019d4c799a3df15ab9b1d0292f97c1dd71dc7c045e69f81a8064e5af7297 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -4353,6 +5373,18 @@ __metadata: languageName: node linkType: hard +"raw-body@npm:^2.3.3": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 + languageName: node + linkType: hard + "react-is@npm:^18.0.0": version: 18.2.0 resolution: "react-is@npm:18.2.0" @@ -4415,6 +5447,13 @@ __metadata: languageName: node linkType: hard +"resolve.exports@npm:^2.0.0": + version: 2.0.0 + resolution: "resolve.exports@npm:2.0.0" + checksum: d8bee3b0cc0a0ae6c8323710983505bc6a3a2574f718e96f01e048a0f0af035941434b386cc9efc7eededc5e1199726185c306ec6f6a1aa55d5fbad926fd0634 + languageName: node + linkType: hard + "resolve@npm:^1.20.0": version: 1.22.1 resolution: "resolve@npm:1.22.1" @@ -4475,14 +5514,14 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 languageName: node linkType: hard -"safer-buffer@npm:>= 2.1.2 < 3.0.0": +"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 @@ -4516,6 +5555,13 @@ __metadata: languageName: node linkType: hard +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: be18cbbf70e7d8097c97f713a2e76edf84e87299b40d085c6bf8b65314e994cc15e2e317727342fa6996e38e1f52c59720b53fe621e2eb593a6847bf0356db89 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -4532,6 +5578,17 @@ __metadata: languageName: node linkType: hard +"side-channel@npm:^1.0.4": + version: 1.0.4 + resolution: "side-channel@npm:1.0.4" + dependencies: + call-bind: ^1.0.0 + get-intrinsic: ^1.0.2 + object-inspect: ^1.9.0 + checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 + languageName: node + linkType: hard + "signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -4623,6 +5680,20 @@ __metadata: languageName: node linkType: hard +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + +"statuses@npm:>= 1.5.0 < 2, statuses@npm:^1.5.0": + version: 1.5.0 + resolution: "statuses@npm:1.5.0" + checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c + languageName: node + linkType: hard + "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" @@ -4792,6 +5863,13 @@ __metadata: languageName: node linkType: hard +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 + languageName: node + linkType: hard + "ts-jest@npm:^28.0.7": version: 28.0.8 resolution: "ts-jest@npm:28.0.8" @@ -4877,6 +5955,13 @@ __metadata: languageName: node linkType: hard +"tsscmp@npm:1.0.6": + version: 1.0.6 + resolution: "tsscmp@npm:1.0.6" + checksum: 1512384def36bccc9125cabbd4c3b0e68608d7ee08127ceaa0b84a71797263f1a01c7f82fa69be8a3bd3c1396e2965d2f7b52d581d3a5eeaf3967fbc52e3b3bf + languageName: node + linkType: hard + "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" @@ -4918,6 +6003,16 @@ __metadata: languageName: node linkType: hard +"type-is@npm:^1.6.16": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: 0.3.0 + mime-types: ~2.1.24 + checksum: 2c8e47675d55f8b4e404bcf529abdf5036c537a04c2b20177bcf78c9e3c1da69da3942b1346e6edb09e823228c0ee656ef0e033765ec39a70d496ef601a0c657 + languageName: node + linkType: hard + "typescript@npm:^4.9.5": version: 4.9.5 resolution: "typescript@npm:4.9.5" @@ -4956,6 +6051,13 @@ __metadata: languageName: node linkType: hard +"unpipe@npm:1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 + languageName: node + linkType: hard + "update-browserslist-db@npm:^1.0.10": version: 1.0.10 resolution: "update-browserslist-db@npm:1.0.10" @@ -5004,6 +6106,13 @@ __metadata: languageName: node linkType: hard +"vary@npm:^1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b + languageName: node + linkType: hard + "walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" @@ -5111,6 +6220,13 @@ __metadata: languageName: node linkType: hard +"ylru@npm:^1.2.0": + version: 1.3.2 + resolution: "ylru@npm:1.3.2" + checksum: b6bb3931144424114f2350c072cfeb180f205add93509c605ae025cbed8059846f8a5767655feeeab890d288b5b4c4b36f5d5d867ee4e6946c16bcc7ec3ddaee + languageName: node + linkType: hard + "yn@npm:3.1.1": version: 3.1.1 resolution: "yn@npm:3.1.1" From d9cbe7996abc0e00724af0238c93741b44663c6d Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Wed, 1 Mar 2023 16:11:20 -0500 Subject: [PATCH 02/14] feat(json-rpc): working minimal test --- .vscode/launch.json | 5 +- .vscode/settings.json | 2 +- yarn-project/.pnp.cjs | 265 ++++++++++++++++- yarn-project/json-rpc/package.json | 13 +- yarn-project/json-rpc/src/ClassConverter.ts | 31 +- yarn-project/json-rpc/src/logUtils.ts | 3 + yarn-project/json-rpc/src/server/JsonProxy.ts | 20 +- .../json-rpc/src/server/JsonRpcServer.test.ts | 16 +- .../json-rpc/src/server/JsonRpcServer.ts | 64 ++-- yarn-project/json-rpc/src/server/index.ts | 2 +- yarn-project/yarn.lock | 276 +++++++++++++++++- 11 files changed, 629 insertions(+), 68 deletions(-) create mode 100644 yarn-project/json-rpc/src/logUtils.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 9ce9e4e0f3f..7da67484f24 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,8 +5,7 @@ "version": "0.2.0", "configurations": [ { - "address": "${config:mainframeAddress}", - "port": 9221, + "port": 9229, "type": "node", "request": "attach", "name": "Attach to Remote", @@ -15,4 +14,4 @@ "sourceMaps": true } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 64b124c8ddb..c2b05d2eea5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -127,5 +127,5 @@ "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "cmake.sourceDirectory": "${workspaceFolder}/circuits" + "mainframeAddress": "localhost" } diff --git a/yarn-project/.pnp.cjs b/yarn-project/.pnp.cjs index bb7d7c3079f..e86a2aea712 100755 --- a/yarn-project/.pnp.cjs +++ b/yarn-project/.pnp.cjs @@ -274,17 +274,23 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@aztec/json-rpc", "workspace:json-rpc"],\ ["@aztec/eslint-config", "workspace:eslint-config"],\ ["@jest/globals", "npm:29.4.3"],\ + ["@koa/cors", "npm:4.0.0"],\ ["@rushstack/eslint-patch", "npm:1.2.0"],\ ["@types/jest", "npm:29.4.0"],\ ["@types/koa", "npm:2.13.5"],\ ["@types/koa-bodyparser", "npm:4.3.10"],\ + ["@types/koa-compress", "npm:4.0.3"],\ ["@types/koa-router", "npm:7.4.4"],\ + ["@types/koa__cors", "npm:3.3.1"],\ ["@types/node", "npm:18.14.2"],\ + ["@types/supertest", "npm:2.0.12"],\ ["jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.4.3"],\ ["koa", "npm:2.14.1"],\ ["koa-bodyparser", "npm:4.3.0"],\ + ["koa-compress", "npm:5.1.0"],\ ["koa-router", "npm:12.0.0"],\ - ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:28.0.8"],\ + ["supertest", "npm:6.3.3"],\ + ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.0.5"],\ ["ts-node", "virtual:97973ff51783dc29efdf1c1cff3bd542763fb1d8ea565946db4f6425a5a443923944d5f46e5672160073e5b792b61ec2b3a0e9df4f007033f07c728780e0e4e7#npm:10.9.1"],\ ["tslib", "npm:2.5.0"],\ ["typescript", "patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76"]\ @@ -1867,6 +1873,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@koa/cors", [\ + ["npm:4.0.0", {\ + "packageLocation": "./.yarn/cache/@koa-cors-npm-4.0.0-e1649c9262-e076054482.zip/node_modules/@koa/cors/",\ + "packageDependencies": [\ + ["@koa/cors", "npm:4.0.0"],\ + ["vary", "npm:1.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@nodelib/fs.scandir", [\ ["npm:2.1.5", {\ "packageLocation": "./.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-a970d595bd.zip/node_modules/@nodelib/fs.scandir/",\ @@ -2111,6 +2127,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/cookiejar", [\ + ["npm:2.1.2", {\ + "packageLocation": "./.yarn/cache/@types-cookiejar-npm-2.1.2-2588120a7c-f6e1903454.zip/node_modules/@types/cookiejar/",\ + "packageDependencies": [\ + ["@types/cookiejar", "npm:2.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/cookies", [\ ["npm:0.7.7", {\ "packageLocation": "./.yarn/cache/@types-cookies-npm-0.7.7-0fbdd53be5-d3759efc11.zip/node_modules/@types/cookies/",\ @@ -2272,6 +2297,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/koa-compress", [\ + ["npm:4.0.3", {\ + "packageLocation": "./.yarn/cache/@types-koa-compress-npm-4.0.3-d7a9809a1d-6f09e4ad81.zip/node_modules/@types/koa-compress/",\ + "packageDependencies": [\ + ["@types/koa-compress", "npm:4.0.3"],\ + ["@types/koa", "npm:2.13.5"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/koa-router", [\ ["npm:7.4.4", {\ "packageLocation": "./.yarn/cache/@types-koa-router-npm-7.4.4-ea72843f67-23ff5b725d.zip/node_modules/@types/koa-router/",\ @@ -2282,6 +2318,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/koa__cors", [\ + ["npm:3.3.1", {\ + "packageLocation": "./.yarn/cache/@types-koa__cors-npm-3.3.1-173cac4235-816303d34c.zip/node_modules/@types/koa__cors/",\ + "packageDependencies": [\ + ["@types/koa__cors", "npm:3.3.1"],\ + ["@types/koa", "npm:2.13.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/mime", [\ ["npm:3.0.1", {\ "packageLocation": "./.yarn/cache/@types-mime-npm-3.0.1-dec03536dc-4040fac73f.zip/node_modules/@types/mime/",\ @@ -2356,6 +2402,27 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/superagent", [\ + ["npm:4.1.16", {\ + "packageLocation": "./.yarn/cache/@types-superagent-npm-4.1.16-2fb61656c0-187d1d32fd.zip/node_modules/@types/superagent/",\ + "packageDependencies": [\ + ["@types/superagent", "npm:4.1.16"],\ + ["@types/cookiejar", "npm:2.1.2"],\ + ["@types/node", "npm:18.14.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/supertest", [\ + ["npm:2.0.12", {\ + "packageLocation": "./.yarn/cache/@types-supertest-npm-2.0.12-deccb2551b-f0e2b44f86.zip/node_modules/@types/supertest/",\ + "packageDependencies": [\ + ["@types/supertest", "npm:2.0.12"],\ + ["@types/superagent", "npm:4.1.16"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/yargs", [\ ["npm:17.0.22", {\ "packageLocation": "./.yarn/cache/@types-yargs-npm-17.0.22-35cdb1bdeb-0773523fda.zip/node_modules/@types/yargs/",\ @@ -2781,6 +2848,24 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["asap", [\ + ["npm:2.0.6", {\ + "packageLocation": "./.yarn/cache/asap-npm-2.0.6-36714d439d-b296c92c4b.zip/node_modules/asap/",\ + "packageDependencies": [\ + ["asap", "npm:2.0.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["asynckit", [\ + ["npm:0.4.0", {\ + "packageLocation": "./.yarn/cache/asynckit-npm-0.4.0-c718858525-7b78c451df.zip/node_modules/asynckit/",\ + "packageDependencies": [\ + ["asynckit", "npm:0.4.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["babel-jest", [\ ["npm:28.1.3", {\ "packageLocation": "./.yarn/cache/babel-jest-npm-28.1.3-3bb56d0efd-57ccd2296e.zip/node_modules/babel-jest/",\ @@ -3300,6 +3385,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["combined-stream", [\ + ["npm:1.0.8", {\ + "packageLocation": "./.yarn/cache/combined-stream-npm-1.0.8-dc14d4a63a-49fa4aeb49.zip/node_modules/combined-stream/",\ + "packageDependencies": [\ + ["combined-stream", "npm:1.0.8"],\ + ["delayed-stream", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["commander", [\ ["npm:9.5.0", {\ "packageLocation": "./.yarn/cache/commander-npm-9.5.0-993b3f2434-c7a3e27aa5.zip/node_modules/commander/",\ @@ -3309,6 +3404,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["component-emitter", [\ + ["npm:1.3.0", {\ + "packageLocation": "./.yarn/cache/component-emitter-npm-1.3.0-4b848565b9-b3c46de38f.zip/node_modules/component-emitter/",\ + "packageDependencies": [\ + ["component-emitter", "npm:1.3.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["compressible", [\ + ["npm:2.0.18", {\ + "packageLocation": "./.yarn/cache/compressible-npm-2.0.18-ee5ab04d88-58321a85b3.zip/node_modules/compressible/",\ + "packageDependencies": [\ + ["compressible", "npm:2.0.18"],\ + ["mime-db", "npm:1.52.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["concat-map", [\ ["npm:0.0.1", {\ "packageLocation": "./.yarn/cache/concat-map-npm-0.0.1-85a921b7ee-902a9f5d89.zip/node_modules/concat-map/",\ @@ -3362,6 +3476,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["cookiejar", [\ + ["npm:2.1.4", {\ + "packageLocation": "./.yarn/cache/cookiejar-npm-2.1.4-e418c49b9e-c444211196.zip/node_modules/cookiejar/",\ + "packageDependencies": [\ + ["cookiejar", "npm:2.1.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["cookies", [\ ["npm:0.8.0", {\ "packageLocation": "./.yarn/cache/cookies-npm-0.8.0-d7388cbd94-806055a44f.zip/node_modules/cookies/",\ @@ -3462,6 +3585,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["delayed-stream", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/delayed-stream-npm-1.0.0-c5a4c4cc02-46fe6e83e2.zip/node_modules/delayed-stream/",\ + "packageDependencies": [\ + ["delayed-stream", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["delegates", [\ ["npm:1.0.0", {\ "packageLocation": "./.yarn/cache/delegates-npm-1.0.0-9b1942d75f-a51744d9b5.zip/node_modules/delegates/",\ @@ -3505,6 +3637,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["dezalgo", [\ + ["npm:1.0.4", {\ + "packageLocation": "./.yarn/cache/dezalgo-npm-1.0.4-ae3b673c98-895389c6ae.zip/node_modules/dezalgo/",\ + "packageDependencies": [\ + ["dezalgo", "npm:1.0.4"],\ + ["asap", "npm:2.0.6"],\ + ["wrappy", "npm:1.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["diff", [\ ["npm:4.0.2", {\ "packageLocation": "./.yarn/cache/diff-npm-4.0.2-73133c7102-f2c09b0ce4.zip/node_modules/diff/",\ @@ -3971,6 +4114,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["fast-safe-stringify", [\ + ["npm:2.1.1", {\ + "packageLocation": "./.yarn/cache/fast-safe-stringify-npm-2.1.1-7ce89033ca-a851cbddc4.zip/node_modules/fast-safe-stringify/",\ + "packageDependencies": [\ + ["fast-safe-stringify", "npm:2.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["fastq", [\ ["npm:1.15.0", {\ "packageLocation": "./.yarn/cache/fastq-npm-1.15.0-1013f6514e-0170e6bfcd.zip/node_modules/fastq/",\ @@ -4051,6 +4203,31 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["form-data", [\ + ["npm:4.0.0", {\ + "packageLocation": "./.yarn/cache/form-data-npm-4.0.0-916facec2d-01135bf867.zip/node_modules/form-data/",\ + "packageDependencies": [\ + ["form-data", "npm:4.0.0"],\ + ["asynckit", "npm:0.4.0"],\ + ["combined-stream", "npm:1.0.8"],\ + ["mime-types", "npm:2.1.35"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["formidable", [\ + ["npm:2.1.2", {\ + "packageLocation": "./.yarn/cache/formidable-npm-2.1.2-40ba18d67f-81c8e5d89f.zip/node_modules/formidable/",\ + "packageDependencies": [\ + ["formidable", "npm:2.1.2"],\ + ["dezalgo", "npm:1.0.4"],\ + ["hexoid", "npm:1.0.0"],\ + ["once", "npm:1.4.0"],\ + ["qs", "npm:6.11.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["fresh", [\ ["npm:0.5.2", {\ "packageLocation": "./.yarn/cache/fresh-npm-0.5.2-ad2bb4c0a2-13ea8b08f9.zip/node_modules/fresh/",\ @@ -4312,6 +4489,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["hexoid", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/hexoid-npm-1.0.0-2274609209-27a148ca76.zip/node_modules/hexoid/",\ + "packageDependencies": [\ + ["hexoid", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["html-escaper", [\ ["npm:2.0.2", {\ "packageLocation": "./.yarn/cache/html-escaper-npm-2.0.2-38e51ef294-d2df2da3ad.zip/node_modules/html-escaper/",\ @@ -5847,6 +6033,20 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["koa-compress", [\ + ["npm:5.1.0", {\ + "packageLocation": "./.yarn/cache/koa-compress-npm-5.1.0-6e1afafa29-3d1c72fe1e.zip/node_modules/koa-compress/",\ + "packageDependencies": [\ + ["koa-compress", "npm:5.1.0"],\ + ["bytes", "npm:3.1.2"],\ + ["compressible", "npm:2.0.18"],\ + ["http-errors", "npm:1.8.1"],\ + ["koa-is-json", "npm:1.0.0"],\ + ["statuses", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["koa-convert", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/koa-convert-npm-2.0.0-d709eca55c-7385b33919.zip/node_modules/koa-convert/",\ @@ -5858,6 +6058,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["koa-is-json", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/koa-is-json-npm-1.0.0-0fd77526f2-0f14a7780d.zip/node_modules/koa-is-json/",\ + "packageDependencies": [\ + ["koa-is-json", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["koa-router", [\ ["npm:12.0.0", {\ "packageLocation": "./.yarn/cache/koa-router-npm-12.0.0-ac2780adae-29b02fd969.zip/node_modules/koa-router/",\ @@ -6062,6 +6271,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["mime", [\ + ["npm:2.6.0", {\ + "packageLocation": "./.yarn/cache/mime-npm-2.6.0-88b89d8de0-1497ba7b9f.zip/node_modules/mime/",\ + "packageDependencies": [\ + ["mime", "npm:2.6.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["mime-db", [\ ["npm:1.52.0", {\ "packageLocation": "./.yarn/cache/mime-db-npm-1.52.0-b5371d6fd2-0d99a03585.zip/node_modules/mime-db/",\ @@ -7096,6 +7314,36 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["superagent", [\ + ["npm:8.0.9", {\ + "packageLocation": "./.yarn/cache/superagent-npm-8.0.9-da05128b97-5d00cdc7ce.zip/node_modules/superagent/",\ + "packageDependencies": [\ + ["superagent", "npm:8.0.9"],\ + ["component-emitter", "npm:1.3.0"],\ + ["cookiejar", "npm:2.1.4"],\ + ["debug", "virtual:0c9322b41fab7d59285768a0e9d661e38864eba0258adfe39a8253e14f176a6b908423ed1fe2a13cb929c471127e6c8d9e2ce76373907f467366a10dca15a138#npm:4.3.4"],\ + ["fast-safe-stringify", "npm:2.1.1"],\ + ["form-data", "npm:4.0.0"],\ + ["formidable", "npm:2.1.2"],\ + ["methods", "npm:1.1.2"],\ + ["mime", "npm:2.6.0"],\ + ["qs", "npm:6.11.0"],\ + ["semver", "npm:7.3.8"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["supertest", [\ + ["npm:6.3.3", {\ + "packageLocation": "./.yarn/cache/supertest-npm-6.3.3-2e2b5bc83a-38239e517f.zip/node_modules/supertest/",\ + "packageDependencies": [\ + ["supertest", "npm:6.3.3"],\ + ["methods", "npm:1.1.2"],\ + ["superagent", "npm:8.0.9"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["supports-color", [\ ["npm:5.5.0", {\ "packageLocation": "./.yarn/cache/supports-color-npm-5.5.0-183ac537bc-95f6f4ba5a.zip/node_modules/supports-color/",\ @@ -7234,10 +7482,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ],\ "linkType": "SOFT"\ }],\ - ["virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:28.0.8", {\ - "packageLocation": "./.yarn/__virtual__/ts-jest-virtual-8e2c80f3cb/0/cache/ts-jest-npm-28.0.8-eeca582fd6-c72e929270.zip/node_modules/ts-jest/",\ + ["npm:29.0.5", {\ + "packageLocation": "./.yarn/cache/ts-jest-npm-29.0.5-30e5da5c24-f60f129c22.zip/node_modules/ts-jest/",\ "packageDependencies": [\ - ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:28.0.8"],\ + ["ts-jest", "npm:29.0.5"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.0.5", {\ + "packageLocation": "./.yarn/__virtual__/ts-jest-virtual-35944e0653/0/cache/ts-jest-npm-29.0.5-30e5da5c24-f60f129c22.zip/node_modules/ts-jest/",\ + "packageDependencies": [\ + ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.0.5"],\ ["@babel/core", null],\ ["@jest/types", null],\ ["@types/babel-jest", null],\ @@ -7251,7 +7506,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["esbuild", null],\ ["fast-json-stable-stringify", "npm:2.1.0"],\ ["jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.4.3"],\ - ["jest-util", "npm:28.1.3"],\ + ["jest-util", "npm:29.4.3"],\ ["json5", "npm:2.2.3"],\ ["lodash.memoize", "npm:4.1.2"],\ ["make-error", "npm:1.3.6"],\ diff --git a/yarn-project/json-rpc/package.json b/yarn-project/json-rpc/package.json index c54fa4eb89c..b12fd1dc025 100644 --- a/yarn-project/json-rpc/package.json +++ b/yarn-project/json-rpc/package.json @@ -8,7 +8,8 @@ "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", - "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --passWithNoTests" + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache", + "test-debug": "NODE_NO_WARNINGS=1 node --inspect-brk --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand" }, "jest": { "preset": "ts-jest/presets/default-esm", @@ -24,8 +25,10 @@ "rootDir": "./src" }, "dependencies": { + "@koa/cors": "^4.0.0", "koa": "^2.14.1", "koa-bodyparser": "^4.3.0", + "koa-compress": "^5.1.0", "koa-router": "^12.0.0", "tslib": "^2.4.0" }, @@ -34,12 +37,16 @@ "@jest/globals": "^29.4.3", "@rushstack/eslint-patch": "^1.1.4", "@types/jest": "^29.4.0", + "@types/koa": "^2.13.5", "@types/koa-bodyparser": "^4.3.10", - "@types/koa": "^2.0.49", + "@types/koa-compress": "^4.0.3", "@types/koa-router": "^7.0.42", + "@types/koa__cors": "^3.3.0", "@types/node": "^18.7.23", + "@types/supertest": "^2.0.12", "jest": "^29.4.3", - "ts-jest": "^28.0.7", + "supertest": "^6.3.3", + "ts-jest": "^29.0.5", "ts-node": "^10.9.1", "typescript": "^4.9.5" } diff --git a/yarn-project/json-rpc/src/ClassConverter.ts b/yarn-project/json-rpc/src/ClassConverter.ts index aef7c43bfee..ac6e3dbf664 100644 --- a/yarn-project/json-rpc/src/ClassConverter.ts +++ b/yarn-project/json-rpc/src/ClassConverter.ts @@ -1,20 +1,41 @@ import { assert, hasOwnProperty } from './jsUtils.js'; -type AnyClass = { new (): any; fromString: (str: string) => any }; +/** + * IOClass: + * Represents a class compatible with our class conversion system + * e.g. PublicKey here satisfies 'IOClass' + * class PublicKey { + * toString() { + * return '...'; + * } + * static fromString(str) { + * return new PublicKey(...); + * } + * } + */ +interface IOClass { + new (): any; + fromString: (str: string) => any; +} + export interface ClassConverterInput { - [className: string]: AnyClass; + [className: string]: IOClass; } +/** + * Handles mapping of classes to names, and calling toString and fromString + * to convert to and from JSON-friendly formats + */ export class ClassConverter { - private toClass = new Map(); - private toName = new Map(); + private toClass = new Map(); + private toName = new Map(); constructor(input: ClassConverterInput) { for (const key of Object.keys(input)) { this.register(key, input[key]); } } - register(type: string, class_: AnyClass) { + register(type: string, class_: IOClass) { assert(hasOwnProperty(class_.prototype, 'toString'), `Class ${type} must define a toString() method.`); assert(class_['fromString'], `Class ${type} must define a fromString() static method.`); this.toName.set(class_, type); diff --git a/yarn-project/json-rpc/src/logUtils.ts b/yarn-project/json-rpc/src/logUtils.ts new file mode 100644 index 00000000000..b5b6d5697b3 --- /dev/null +++ b/yarn-project/json-rpc/src/logUtils.ts @@ -0,0 +1,3 @@ +export function logTrace(...objs: any) { + console.log(...objs); +} diff --git a/yarn-project/json-rpc/src/server/JsonProxy.ts b/yarn-project/json-rpc/src/server/JsonProxy.ts index 21fce7da44b..8d12ac220b4 100644 --- a/yarn-project/json-rpc/src/server/JsonProxy.ts +++ b/yarn-project/json-rpc/src/server/JsonProxy.ts @@ -1,23 +1,29 @@ import { ClassConverter, ClassConverterInput } from '../ClassConverter.js'; import { assert, hasOwnProperty } from '../jsUtils.js'; +import { logTrace } from '../logUtils.js'; export class JsonProxy { classMap: ClassConverter; - constructor(private handler: any, input: ClassConverterInput) { + constructor(private handler: object, input: ClassConverterInput) { this.classMap = new ClassConverter(input); } - public call(method: string, jsonParams: any[] = []) { + public call(methodName: string, jsonParams: any[] = []) { + // Get access to our class members + const proto = Object.getPrototypeOf(this.handler); const convert = (obj: any) => { - // Is this a convertable type? - if (obj?.constructor?.fromString) { - return this.classMap.toClassObj(obj); + // Is this a convertible type? + if (obj.constructor.fromString) { + return this.classMap.toJsonObj(obj); } // Leave alone, assume JSON-friendly return obj; }; - assert(hasOwnProperty(this.handler, method), 'JsonProxy: Method not found!'); + assert(hasOwnProperty(proto, methodName), 'JsonProxy: Method not found!'); // convert the params from json representation to classes const convertedParams = jsonParams.map(convert); - return convert(this.handler[method](...convertedParams)); + logTrace('JsonProxy:call', this.handler, methodName, '<-', convertedParams); + const ret = convert((this.handler as any)[methodName](...convertedParams)); + logTrace('JsonProxy:call', this.handler, methodName, '->', ret); + return ret; } } diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts index b0d9f37e58d..12e352297a0 100644 --- a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts +++ b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts @@ -1,8 +1,15 @@ -import { jest } from '@jest/globals'; +import request from 'supertest'; +import { JsonRpcServer } from './JsonRpcServer.js'; // Contrived example class Tree { constructor() {} + toString(): string { + return ''; + } + static fromString(): Tree { + return new Tree(); + } } class State { @@ -15,4 +22,9 @@ class State { } } -describe('block_context', () => {}); +test('simple example', async () => { + const server = new JsonRpcServer(new State(new Tree(), new Tree()), { Tree }); + const response = await request(server.getApp().callback()).post('/getPrivateTree'); + expect(response.status).toBe(200); + expect(response.text).toBe('{"result":{"type":"Tree","data":""}}'); +}); diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.ts b/yarn-project/json-rpc/src/server/JsonRpcServer.ts index fa7aef6d422..7a36538194c 100644 --- a/yarn-project/json-rpc/src/server/JsonRpcServer.ts +++ b/yarn-project/json-rpc/src/server/JsonRpcServer.ts @@ -1,34 +1,25 @@ import http from 'http'; import Router from 'koa-router'; +import cors from '@koa/cors'; +import compress from 'koa-compress'; import { ClassConverterInput } from '../ClassConverter.js'; -import { JsonRpcProxy } from './index.js'; -import Koa, { Context, DefaultState } from 'koa'; +import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; +import { JsonProxy } from './JsonProxy.js'; +import { logTrace } from '../logUtils.js'; /** * JsonRpcServer: - * minimal, dev-friendly mechanism to + * minimal, dev-friendly mechanism to create a server from an object */ -export class JsonRpcServer { - proxy: JsonRpcProxy; - constructor(private handler: T, input: ClassConverterInput) { - this.proxy = new JsonRpcProxy(handler, input); +export class JsonRpcServer { + proxy: JsonProxy; + constructor(private handler: object, input: ClassConverterInput) { + this.proxy = new JsonProxy(handler, input); } - private getApp(prefix: string) { - const router = new Router({ prefix }); - for (const method of Object.keys(this.handler)) { - // Make sure this is a function - if (typeof (this.handler as any)[method] !== 'function') { - continue; - } - router.post(`/${method}`, async (ctx: Koa.Context) => { - const { params = [], jsonrpc, id } = ctx.request.body as any; - const result = await this.proxy.call(method, params); - ctx.body = { jsonrpc, id, result }; - ctx.status = 200; - }); - } + public getApp(prefix = '') { + const router = this.getRouter(prefix); const exceptionHandler = async (ctx: Koa.Context, next: () => Promise) => { try { await next(); @@ -42,13 +33,9 @@ export class JsonRpcServer { app.on('error', error => { console.log(`KOA app-level error. ${JSON.stringify({ error })}`); }); - app.proxy = true; - - // TODO use? - // app.use(compress({ br: false } as any)); + app.use(compress({ br: false } as any)); app.use(bodyParser()); - // TODO use? - // app.use(cors()); + app.use(cors()); app.use(exceptionHandler); app.use(router.routes()); app.use(router.allowedMethods()); @@ -56,7 +43,28 @@ export class JsonRpcServer { return app; } - start(port: number, prefix = '') { + private getRouter(prefix: string) { + const router = new Router({ prefix }); + const proto = Object.getPrototypeOf(this.handler); + // Find all our endpoints from the handler methods + for (const method of Object.getOwnPropertyNames(proto)) { + // Ignore if not a function + if (method === 'constructor' || typeof proto[method] !== 'function') { + continue; + } + // console.log(method, (this.handler as any)[method]); + router.post(`/${method}`, async (ctx: Koa.Context) => { + const { params = [], jsonrpc, id } = ctx.request.body as any; + logTrace('JsonRpcServer:getRouter', method, '<-', params); + const result = await this.proxy.call(method, params); + ctx.body = { jsonrpc, id, result }; + ctx.status = 200; + }); + } + return router; + } + + public start(port: number, prefix = '') { const httpServer = http.createServer(this.getApp(prefix).callback()); httpServer.listen(port); } diff --git a/yarn-project/json-rpc/src/server/index.ts b/yarn-project/json-rpc/src/server/index.ts index 3b62ef7aba5..7dad71a929f 100644 --- a/yarn-project/json-rpc/src/server/index.ts +++ b/yarn-project/json-rpc/src/server/index.ts @@ -1,2 +1,2 @@ export { JsonRpcServer } from './JsonRpcServer.js'; -export { JsonRpcProxy } from './JsonProxy.js'; +export { JsonProxy } from './JsonProxy.js'; diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 0127dd98642..0a9ca5ecf88 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -148,17 +148,23 @@ __metadata: dependencies: "@aztec/eslint-config": "workspace:^" "@jest/globals": ^29.4.3 + "@koa/cors": ^4.0.0 "@rushstack/eslint-patch": ^1.1.4 "@types/jest": ^29.4.0 - "@types/koa": ^2.0.49 + "@types/koa": ^2.13.5 "@types/koa-bodyparser": ^4.3.10 + "@types/koa-compress": ^4.0.3 "@types/koa-router": ^7.0.42 + "@types/koa__cors": ^3.3.0 "@types/node": ^18.7.23 + "@types/supertest": ^2.0.12 jest: ^29.4.3 koa: ^2.14.1 koa-bodyparser: ^4.3.0 + koa-compress: ^5.1.0 koa-router: ^12.0.0 - ts-jest: ^28.0.7 + supertest: ^6.3.3 + ts-jest: ^29.0.5 ts-node: ^10.9.1 tslib: ^2.4.0 typescript: ^4.9.5 @@ -1295,6 +1301,15 @@ __metadata: languageName: node linkType: hard +"@koa/cors@npm:^4.0.0": + version: 4.0.0 + resolution: "@koa/cors@npm:4.0.0" + dependencies: + vary: ^1.1.2 + checksum: e0760544823532f2d71d792e3076858e38bab9b1c090abea175f1319fd91ea58a1da384a2fe7f5108f1c681e3830b01f62a1cafe271d6406751976af443187aa + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -1510,6 +1525,13 @@ __metadata: languageName: node linkType: hard +"@types/cookiejar@npm:*": + version: 2.1.2 + resolution: "@types/cookiejar@npm:2.1.2" + checksum: f6e1903454007f86edd6c3520cbb4d553e1d4e17eaf1f77f6f75e3270f48cc828d74397a113a36942f5fe52f9fa71067bcfa738f53ad468fcca0bc52cb1cbd28 + languageName: node + linkType: hard + "@types/cookies@npm:*": version: 0.7.7 resolution: "@types/cookies@npm:0.7.7" @@ -1635,6 +1657,16 @@ __metadata: languageName: node linkType: hard +"@types/koa-compress@npm:^4.0.3": + version: 4.0.3 + resolution: "@types/koa-compress@npm:4.0.3" + dependencies: + "@types/koa": "*" + "@types/node": "*" + checksum: 6f09e4ad8160204fbee9d0a452b83ba62fec503a2eec60cf41fc67a032971027b6858e0b90c6e05bf1ad3b006f7c7a2d02922db4d159d223ab8d33eeeb108757 + languageName: node + linkType: hard + "@types/koa-router@npm:^7.0.42": version: 7.4.4 resolution: "@types/koa-router@npm:7.4.4" @@ -1644,7 +1676,7 @@ __metadata: languageName: node linkType: hard -"@types/koa@npm:*, @types/koa@npm:^2.0.49": +"@types/koa@npm:*, @types/koa@npm:^2.13.5": version: 2.13.5 resolution: "@types/koa@npm:2.13.5" dependencies: @@ -1660,6 +1692,15 @@ __metadata: languageName: node linkType: hard +"@types/koa__cors@npm:^3.3.0": + version: 3.3.1 + resolution: "@types/koa__cors@npm:3.3.1" + dependencies: + "@types/koa": "*" + checksum: 816303d34c1b92627cfaea5327d25cff86d8eb969e5866af4c3769ec158c4575ab5b6fa01145eec0eeb61019648bc165981becf3a13001ec67a83ef9994e0e29 + languageName: node + linkType: hard + "@types/mime@npm:*": version: 3.0.1 resolution: "@types/mime@npm:3.0.1" @@ -1719,6 +1760,25 @@ __metadata: languageName: node linkType: hard +"@types/superagent@npm:*": + version: 4.1.16 + resolution: "@types/superagent@npm:4.1.16" + dependencies: + "@types/cookiejar": "*" + "@types/node": "*" + checksum: 187d1d32fdafd20b27e81728c46283160d3296ad904d56e0780769cf524105c94cc64bf5bafa170400cf5f1063d30826427de42ff0894d15b54df6d0fa31be4e + languageName: node + linkType: hard + +"@types/supertest@npm:^2.0.12": + version: 2.0.12 + resolution: "@types/supertest@npm:2.0.12" + dependencies: + "@types/superagent": "*" + checksum: f0e2b44f86bec2f708d6a3d0cb209055b487922040773049b0f8c6b557af52d4b5fa904e17dfaa4ce6e610172206bbec7b62420d158fa57b6ffc2de37b1730d3 + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 21.0.0 resolution: "@types/yargs-parser@npm:21.0.0" @@ -2038,6 +2098,20 @@ __metadata: languageName: node linkType: hard +"asap@npm:^2.0.0": + version: 2.0.6 + resolution: "asap@npm:2.0.6" + checksum: b296c92c4b969e973260e47523207cd5769abd27c245a68c26dc7a0fe8053c55bb04360237cb51cab1df52be939da77150ace99ad331fb7fb13b3423ed73ff3d + languageName: node + linkType: hard + +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 7b78c451df768adba04e2d02e63e2d0bf3b07adcd6e42b4cf665cb7ce899bedd344c69a1dcbce355b5f972d597b25aaa1c1742b52cffd9caccb22f348114f6be + languageName: node + linkType: hard + "babel-jest@npm:^28.1.3": version: 28.1.3 resolution: "babel-jest@npm:28.1.3" @@ -2229,7 +2303,7 @@ __metadata: languageName: node linkType: hard -"bytes@npm:3.1.2": +"bytes@npm:3.1.2, bytes@npm:^3.0.0": version: 3.1.2 resolution: "bytes@npm:3.1.2" checksum: e4bcd3948d289c5127591fbedf10c0b639ccbf00243504e4e127374a15c3bc8eed0d28d4aaab08ff6f1cf2abc0cce6ba3085ed32f4f90e82a5683ce0014e1b6e @@ -2444,6 +2518,15 @@ __metadata: languageName: node linkType: hard +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: ~1.0.0 + checksum: 49fa4aeb4916567e33ea81d088f6584749fc90c7abec76fd516bf1c5aa5c79f3584b5ba3de6b86d26ddd64bae5329c4c7479343250cfe71c75bb366eae53bb7c + languageName: node + linkType: hard + "commander@npm:^9.0.0": version: 9.5.0 resolution: "commander@npm:9.5.0" @@ -2451,6 +2534,22 @@ __metadata: languageName: node linkType: hard +"component-emitter@npm:^1.3.0": + version: 1.3.0 + resolution: "component-emitter@npm:1.3.0" + checksum: b3c46de38ffd35c57d1c02488355be9f218e582aec72d72d1b8bbec95a3ac1b38c96cd6e03ff015577e68f550fbb361a3bfdbd9bb248be9390b7b3745691be6b + languageName: node + linkType: hard + +"compressible@npm:^2.0.0": + version: 2.0.18 + resolution: "compressible@npm:2.0.18" + dependencies: + mime-db: ">= 1.43.0 < 2" + checksum: 58321a85b375d39230405654721353f709d0c1442129e9a17081771b816302a012471a9b8f4864c7dbe02eef7f2aaac3c614795197092262e94b409c9be108f0 + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -2495,6 +2594,13 @@ __metadata: languageName: node linkType: hard +"cookiejar@npm:^2.1.4": + version: 2.1.4 + resolution: "cookiejar@npm:2.1.4" + checksum: c4442111963077dc0e5672359956d6556a195d31cbb35b528356ce5f184922b99ac48245ac05ed86cf993f7df157c56da10ab3efdadfed79778a0d9b1b092d5b + languageName: node + linkType: hard + "cookies@npm:~0.8.0": version: 0.8.0 resolution: "cookies@npm:0.8.0" @@ -2570,6 +2676,13 @@ __metadata: languageName: node linkType: hard +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020 + languageName: node + linkType: hard + "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -2605,6 +2718,16 @@ __metadata: languageName: node linkType: hard +"dezalgo@npm:^1.0.4": + version: 1.0.4 + resolution: "dezalgo@npm:1.0.4" + dependencies: + asap: ^2.0.0 + wrappy: 1 + checksum: 895389c6aead740d2ab5da4d3466d20fa30f738010a4d3f4dcccc9fc645ca31c9d10b7e1804ae489b1eb02c7986f9f1f34ba132d409b043082a86d9a4e745624 + languageName: node + linkType: hard + "diff-sequences@npm:^28.1.1": version: 28.1.1 resolution: "diff-sequences@npm:28.1.1" @@ -3003,6 +3126,13 @@ __metadata: languageName: node linkType: hard +"fast-safe-stringify@npm:^2.1.1": + version: 2.1.1 + resolution: "fast-safe-stringify@npm:2.1.1" + checksum: a851cbddc451745662f8f00ddb622d6766f9bd97642dabfd9a405fb0d646d69fc0b9a1243cbf67f5f18a39f40f6fa821737651ff1bceeba06c9992ca2dc5bd3d + languageName: node + linkType: hard + "fastq@npm:^1.6.0": version: 1.15.0 resolution: "fastq@npm:1.15.0" @@ -3076,6 +3206,29 @@ __metadata: languageName: node linkType: hard +"form-data@npm:^4.0.0": + version: 4.0.0 + resolution: "form-data@npm:4.0.0" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.8 + mime-types: ^2.1.12 + checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c + languageName: node + linkType: hard + +"formidable@npm:^2.1.2": + version: 2.1.2 + resolution: "formidable@npm:2.1.2" + dependencies: + dezalgo: ^1.0.4 + hexoid: ^1.0.0 + once: ^1.4.0 + qs: ^6.11.0 + checksum: 81c8e5d89f5eb873e992893468f0de22c01678ca3d315db62be0560f9de1c77d4faefc9b1f4575098eb2263b3c81ba1024833a9fc3206297ddbac88a4f69b7a8 + languageName: node + linkType: hard + "fresh@npm:~0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" @@ -3315,6 +3468,13 @@ __metadata: languageName: node linkType: hard +"hexoid@npm:^1.0.0": + version: 1.0.0 + resolution: "hexoid@npm:1.0.0" + checksum: 27a148ca76a2358287f40445870116baaff4a0ed0acc99900bf167f0f708ffd82e044ff55e9949c71963852b580fc024146d3ac6d5d76b508b78d927fa48ae2d + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -3352,7 +3512,7 @@ __metadata: languageName: node linkType: hard -"http-errors@npm:^1.6.3, http-errors@npm:~1.8.0": +"http-errors@npm:^1.6.3, http-errors@npm:^1.8.0, http-errors@npm:~1.8.0": version: 1.8.1 resolution: "http-errors@npm:1.8.1" dependencies: @@ -4377,7 +4537,7 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.4.3": +"jest-util@npm:^29.0.0, jest-util@npm:^29.4.3": version: 29.4.3 resolution: "jest-util@npm:29.4.3" dependencies: @@ -4579,7 +4739,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.2.1, json5@npm:^2.2.2": +"json5@npm:^2.2.1, json5@npm:^2.2.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -4621,6 +4781,19 @@ __metadata: languageName: node linkType: hard +"koa-compress@npm:^5.1.0": + version: 5.1.0 + resolution: "koa-compress@npm:5.1.0" + dependencies: + bytes: ^3.0.0 + compressible: ^2.0.0 + http-errors: ^1.8.0 + koa-is-json: ^1.0.0 + statuses: ^2.0.1 + checksum: 3d1c72fe1e59d17e84a5109632b1cfe9ab76be3811517f604c6f637e09756c7c255f8aca8b09ba0fc553f02a821d0eeb6decdfb40202d427243e6ab702fe14bd + languageName: node + linkType: hard + "koa-convert@npm:^2.0.0": version: 2.0.0 resolution: "koa-convert@npm:2.0.0" @@ -4631,6 +4804,13 @@ __metadata: languageName: node linkType: hard +"koa-is-json@npm:^1.0.0": + version: 1.0.0 + resolution: "koa-is-json@npm:1.0.0" + checksum: 0f14a7780d7ca0caeda5981ab425b66dd9711fd1bc7a25c091b38331ade8861a2eea41ac9fec7f96537302690de68fe1213b576f2c765ff3b5be3c23e995fbe2 + languageName: node + linkType: hard + "koa-router@npm:^12.0.0": version: 12.0.0 resolution: "koa-router@npm:12.0.0" @@ -4842,14 +5022,14 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:1.52.0": +"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": version: 1.52.0 resolution: "mime-db@npm:1.52.0" checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f languageName: node linkType: hard -"mime-types@npm:^2.1.18, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.18, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -4858,6 +5038,15 @@ __metadata: languageName: node linkType: hard +"mime@npm:2.6.0": + version: 2.6.0 + resolution: "mime@npm:2.6.0" + bin: + mime: cli.js + checksum: 1497ba7b9f6960694268a557eae24b743fd2923da46ec392b042469f4b901721ba0adcf8b0d3c2677839d0e243b209d76e5edcbd09cfdeffa2dfb6bb4df4b862 + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -5093,7 +5282,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0": +"once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -5357,7 +5546,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.5.2": +"qs@npm:^6.11.0, qs@npm:^6.5.2": version: 6.11.0 resolution: "qs@npm:6.11.0" dependencies: @@ -5528,7 +5717,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.x, semver@npm:^7.3.5, semver@npm:^7.3.7": +"semver@npm:7.x, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8": version: 7.3.8 resolution: "semver@npm:7.3.8" dependencies: @@ -5680,7 +5869,7 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1": +"statuses@npm:2.0.1, statuses@npm:^2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb @@ -5754,6 +5943,34 @@ __metadata: languageName: node linkType: hard +"superagent@npm:^8.0.5": + version: 8.0.9 + resolution: "superagent@npm:8.0.9" + dependencies: + component-emitter: ^1.3.0 + cookiejar: ^2.1.4 + debug: ^4.3.4 + fast-safe-stringify: ^2.1.1 + form-data: ^4.0.0 + formidable: ^2.1.2 + methods: ^1.1.2 + mime: 2.6.0 + qs: ^6.11.0 + semver: ^7.3.8 + checksum: 5d00cdc7ceb5570663da80604965750e6b1b8d7d7442b7791e285c62bcd8d578a8ead0242a2426432b59a255fb42eb3a196d636157538a1392e7b6c5f1624810 + languageName: node + linkType: hard + +"supertest@npm:^6.3.3": + version: 6.3.3 + resolution: "supertest@npm:6.3.3" + dependencies: + methods: ^1.1.2 + superagent: ^8.0.5 + checksum: 38239e517f7ba62b7a139a79c5c48d55f8d67b5ff4b6e51d5b07732ca8bbc4a28ffa1b10916fbb403dd013a054dbf028edc5850057d9a43aecbff439d494673e + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -5903,6 +6120,39 @@ __metadata: languageName: node linkType: hard +"ts-jest@npm:^29.0.5": + version: 29.0.5 + resolution: "ts-jest@npm:29.0.5" + dependencies: + bs-logger: 0.x + fast-json-stable-stringify: 2.x + jest-util: ^29.0.0 + json5: ^2.2.3 + lodash.memoize: 4.x + make-error: 1.x + semver: 7.x + yargs-parser: ^21.0.1 + peerDependencies: + "@babel/core": ">=7.0.0-beta.0 <8" + "@jest/types": ^29.0.0 + babel-jest: ^29.0.0 + jest: ^29.0.0 + typescript: ">=4.3" + peerDependenciesMeta: + "@babel/core": + optional: true + "@jest/types": + optional: true + babel-jest: + optional: true + esbuild: + optional: true + bin: + ts-jest: cli.js + checksum: f60f129c2287f4c963d9ee2677132496c5c5a5d39c27ad234199a1140c26318a7d5bda34890ab0e30636ec42a8de28f84487c09e9dcec639c9c67812b3a38373 + languageName: node + linkType: hard + "ts-node@npm:^10.9.1": version: 10.9.1 resolution: "ts-node@npm:10.9.1" From b1485620cb07dcaa834acea3038f01f1293a4831 Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Wed, 1 Mar 2023 16:30:40 -0500 Subject: [PATCH 03/14] feat(json-rpc): cleaner test --- yarn-project/json-rpc/src/ClassConverter.ts | 2 +- yarn-project/json-rpc/src/server/JsonProxy.ts | 17 ++++++++++-- .../json-rpc/src/server/JsonRpcServer.test.ts | 27 +++++++++---------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/yarn-project/json-rpc/src/ClassConverter.ts b/yarn-project/json-rpc/src/ClassConverter.ts index ac6e3dbf664..1a63a69535c 100644 --- a/yarn-project/json-rpc/src/ClassConverter.ts +++ b/yarn-project/json-rpc/src/ClassConverter.ts @@ -14,7 +14,7 @@ import { assert, hasOwnProperty } from './jsUtils.js'; * } */ interface IOClass { - new (): any; + new (...args: any): any; fromString: (str: string) => any; } diff --git a/yarn-project/json-rpc/src/server/JsonProxy.ts b/yarn-project/json-rpc/src/server/JsonProxy.ts index 8d12ac220b4..9015aa84dc4 100644 --- a/yarn-project/json-rpc/src/server/JsonProxy.ts +++ b/yarn-project/json-rpc/src/server/JsonProxy.ts @@ -10,12 +10,25 @@ export class JsonProxy { public call(methodName: string, jsonParams: any[] = []) { // Get access to our class members const proto = Object.getPrototypeOf(this.handler); - const convert = (obj: any) => { + const convert = (obj: any): any => { // Is this a convertible type? if (obj.constructor.fromString) { return this.classMap.toJsonObj(obj); } - // Leave alone, assume JSON-friendly + // Is this an array? + if (Array.isArray(obj)) { + return obj.map((x: any) => convert(x)); + } + // Is this a dictionary? + if (obj.constructor === Object) { + const newObj: any = {}; + for (const key of Object.keys(obj)) { + newObj[key] = convert(obj[key]); + } + return newObj; + } + + // Leave alone, assume JSON primitive return obj; }; assert(hasOwnProperty(proto, methodName), 'JsonProxy: Method not found!'); diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts index 12e352297a0..f97f7644fe8 100644 --- a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts +++ b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts @@ -2,29 +2,26 @@ import request from 'supertest'; import { JsonRpcServer } from './JsonRpcServer.js'; // Contrived example -class Tree { - constructor() {} +class Note { + constructor(private data: string) {} toString(): string { - return ''; + return this.data; } - static fromString(): Tree { - return new Tree(); + static fromString(data: string): Note { + return new Note(data); } } class State { - constructor(private publicTree: Tree, private privateTree: Tree) {} - getPrivateTree(): Tree { - return this.publicTree; - } - getPublicTree(): Tree { - return this.privateTree; + constructor(private notes: Note[]) {} + getNotes(): Note[] { + return this.notes; } } -test('simple example', async () => { - const server = new JsonRpcServer(new State(new Tree(), new Tree()), { Tree }); - const response = await request(server.getApp().callback()).post('/getPrivateTree'); +test('test simple serialization', async () => { + const server = new JsonRpcServer(new State([new Note('a'), new Note('b')]), { Note }); + const response = await request(server.getApp().callback()).post('/getNotes'); expect(response.status).toBe(200); - expect(response.text).toBe('{"result":{"type":"Tree","data":""}}'); + expect(response.text).toBe('{"result":[{"type":"Note","data":"a"},{"type":"Note","data":"b"}]}'); }); From b851fd93aba0e816284448900c82aebcfffccd27 Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Wed, 1 Mar 2023 18:07:12 -0500 Subject: [PATCH 04/14] feat(json-rpc): add, and appease, client tests --- yarn-project/.pnp.cjs | 10 +++ yarn-project/json-rpc/package.json | 3 +- .../json-rpc/src/client/JsonRpcClient.test.ts | 21 +++++ .../json-rpc/src/client/JsonRpcClient.ts | 83 ++++++++++++++++++- yarn-project/json-rpc/src/convert.ts | 51 ++++++++++++ yarn-project/json-rpc/src/jsUtils.ts | 30 +++++++ yarn-project/json-rpc/src/server/JsonProxy.ts | 34 ++------ .../json-rpc/src/server/JsonRpcServer.test.ts | 44 +++++----- yarn-project/json-rpc/src/test/TestState.ts | 26 ++++++ yarn-project/yarn.lock | 8 ++ 10 files changed, 260 insertions(+), 50 deletions(-) create mode 100644 yarn-project/json-rpc/src/client/JsonRpcClient.test.ts create mode 100644 yarn-project/json-rpc/src/convert.ts create mode 100644 yarn-project/json-rpc/src/test/TestState.ts diff --git a/yarn-project/.pnp.cjs b/yarn-project/.pnp.cjs index e86a2aea712..3a076b7bc80 100755 --- a/yarn-project/.pnp.cjs +++ b/yarn-project/.pnp.cjs @@ -284,6 +284,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@types/koa__cors", "npm:3.3.1"],\ ["@types/node", "npm:18.14.2"],\ ["@types/supertest", "npm:2.0.12"],\ + ["comlink", "npm:4.4.1"],\ ["jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.4.3"],\ ["koa", "npm:2.14.1"],\ ["koa-bodyparser", "npm:4.3.0"],\ @@ -3395,6 +3396,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["comlink", [\ + ["npm:4.4.1", {\ + "packageLocation": "./.yarn/cache/comlink-npm-4.4.1-b05bb2527d-16d58a8f59.zip/node_modules/comlink/",\ + "packageDependencies": [\ + ["comlink", "npm:4.4.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["commander", [\ ["npm:9.5.0", {\ "packageLocation": "./.yarn/cache/commander-npm-9.5.0-993b3f2434-c7a3e27aa5.zip/node_modules/commander/",\ diff --git a/yarn-project/json-rpc/package.json b/yarn-project/json-rpc/package.json index b12fd1dc025..3f1926c6be2 100644 --- a/yarn-project/json-rpc/package.json +++ b/yarn-project/json-rpc/package.json @@ -9,7 +9,7 @@ "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache", - "test-debug": "NODE_NO_WARNINGS=1 node --inspect-brk --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand" + "test-debug": "NODE_NO_WARNINGS=1 node --inspect-brk --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --testTimeout 1000000" }, "jest": { "preset": "ts-jest/presets/default-esm", @@ -44,6 +44,7 @@ "@types/koa__cors": "^3.3.0", "@types/node": "^18.7.23", "@types/supertest": "^2.0.12", + "comlink": "^4.4.1", "jest": "^29.4.3", "supertest": "^6.3.3", "ts-jest": "^29.0.5", diff --git a/yarn-project/json-rpc/src/client/JsonRpcClient.test.ts b/yarn-project/json-rpc/src/client/JsonRpcClient.test.ts new file mode 100644 index 00000000000..5f27171c381 --- /dev/null +++ b/yarn-project/json-rpc/src/client/JsonRpcClient.test.ts @@ -0,0 +1,21 @@ +import request from 'supertest'; +import { JsonRpcServer } from '../server/JsonRpcServer.js'; +import { TestState, TestNote } from '../test/TestState.js'; +import { JsonRpcClient } from './JsonRpcClient.js'; + +test('test an RPC function over client', async () => { + const client = new JsonRpcClient('', { TestNote }); + // Mock the method + (client as any).fetch = async (method: string, body: any) => { + const server = new JsonRpcServer(new TestState([new TestNote('a'), new TestNote('b')]), { TestNote }); + const result = await request(server.getApp().callback()).post(`/${method}`).send(body); + return JSON.parse(result.text); + }; + const result = await client.rpc.addNotes([new TestNote('c')]); + expect(result[0]).toBeInstanceOf(TestNote); + expect(result[1]).toBeInstanceOf(TestNote); + expect(result[2]).toBeInstanceOf(TestNote); + expect(result[0].toString()).toBe('a'); + expect(result[1].toString()).toBe('b'); + expect(result[2].toString()).toBe('c'); +}); diff --git a/yarn-project/json-rpc/src/client/JsonRpcClient.ts b/yarn-project/json-rpc/src/client/JsonRpcClient.ts index f4bd53a9532..f34ece97211 100644 --- a/yarn-project/json-rpc/src/client/JsonRpcClient.ts +++ b/yarn-project/json-rpc/src/client/JsonRpcClient.ts @@ -1,3 +1,82 @@ -export class JsonRpcClient { - constructor() {} +import { retry } from '../jsUtils'; +import { logTrace } from '../logUtils'; +// comlink: +// Dev dependency just for the somewhat complex RemoteObject type +// This takes a {foo(): T} and makes {foo(): Promise} +// while avoiding Promise of Promise. +import { RemoteObject } from 'comlink'; +import { ClassConverter, ClassConverterInput } from '../ClassConverter'; +import { convertFromJsonObj, convertToJsonObj } from '../convert'; + +export class JsonRpcClient { + private classConverter: ClassConverter; + public readonly rpc: RemoteObject; + private id = 0; + + constructor(private host: string, classMap: ClassConverterInput, private netMustSucceed = false) { + // the rpc object has syntax sugar over 'request' + // for accessing the remote methods + this.rpc = this.createRpcProxy(); + this.classConverter = new ClassConverter(classMap); + } + /** + * Creates a Proxy object that delegates over RPC + * and satisfies RemoteObject + */ + private createRpcProxy(): RemoteObject { + return new Proxy( + {}, + { + get: + (_, method: string) => + (...params: any[]) => { + logTrace(`JsonRpcClient.constructor`, 'proxy', method, '<-', params); + return this.request(method, params); + }, + }, + ) as RemoteObject; + } + public async request(method: string, params: any[]): Promise { + const body = { + jsonrpc: '2.0', + id: this.id++, + method, + params: params.map(param => convertToJsonObj(this.classConverter, param)), + }; + logTrace(`JsonRpcClient.request`, method, '<-', params); + const res = await this.fetch(method, body); + logTrace(`JsonRpcClient.request`, method, '->', res); + if (res.error) { + throw res.error; + } + return convertFromJsonObj(this.classConverter, res.result); + } + + private async fetch(method: string, body: any) { + const tryOnce = async () => { + logTrace(`JsonRpcClient.fetch`, this.host, method, '<-', body); + const resp = await fetch(`${this.host}/${method}`, { + method: 'POST', + body: JSON.stringify(body), + headers: { 'content-type': 'application/json' }, + }); + + if (!resp.ok) { + throw new Error(resp.statusText); + } + + const text = await resp.text(); + try { + return JSON.parse(text); + } catch (err) { + throw new Error(`Failed to parse body as JSON: ${text}`); + } + }; + + if (this.netMustSucceed) { + return await retry(tryOnce, 'JsonRpcClient request'); + } + + return await tryOnce(); + } } diff --git a/yarn-project/json-rpc/src/convert.ts b/yarn-project/json-rpc/src/convert.ts new file mode 100644 index 00000000000..22c5127d776 --- /dev/null +++ b/yarn-project/json-rpc/src/convert.ts @@ -0,0 +1,51 @@ +import { ClassConverter } from './ClassConverter.js'; + +export function convertFromJsonObj(cc: ClassConverter, obj: any): any { + if (!obj) { + return obj; // Primitive type + } + // Is this a convertible type? + if (typeof obj.type === 'string' && typeof obj.data === 'string') { + return cc.toClassObj(obj); + } + // Is this an array? + if (Array.isArray(obj)) { + return obj.map((x: any) => convertFromJsonObj(cc, x)); + } + // Is this a dictionary? + if (obj.constructor === Object) { + const newObj: any = {}; + for (const key of Object.keys(obj)) { + newObj[key] = convertFromJsonObj(cc, obj[key]); + } + return newObj; + } + + // Leave alone, assume JSON primitive + return obj; +} + +export function convertToJsonObj(cc: ClassConverter, obj: any): any { + if (!obj) { + return obj; // Primitive type + } + // Is this a convertible type? + if (obj.constructor.fromString) { + return cc.toJsonObj(obj); + } + // Is this an array? + if (Array.isArray(obj)) { + return obj.map((x: any) => convertToJsonObj(cc, x)); + } + // Is this a dictionary? + if (obj.constructor === Object) { + const newObj: any = {}; + for (const key of Object.keys(obj)) { + newObj[key] = convertToJsonObj(cc, obj[key]); + } + return newObj; + } + + // Leave alone, assume JSON primitive + return obj; +} diff --git a/yarn-project/json-rpc/src/jsUtils.ts b/yarn-project/json-rpc/src/jsUtils.ts index 362e7989230..260c33e151a 100644 --- a/yarn-project/json-rpc/src/jsUtils.ts +++ b/yarn-project/json-rpc/src/jsUtils.ts @@ -5,3 +5,33 @@ export const assert = (x: any, err: string) => { throw new Error(err); } }; + +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export function* backoffGenerator() { + const v = [1, 1, 1, 2, 4, 8, 16, 32, 64]; + let i = 0; + while (true) { + yield v[Math.min(i++, v.length - 1)]; + } +} + +// Retries according to an exponential backoff +export async function retry(fn: () => Promise, name = 'Operation', backoff = backoffGenerator()) { + while (true) { + try { + return await fn(); + } catch (err: any) { + const s = backoff.next().value; + if (s === undefined) { + throw err; + } + console.log(`${name} failed. Will retry in ${s}s...`); + console.log(err); + await sleep(s * 1000); + continue; + } + } +} diff --git a/yarn-project/json-rpc/src/server/JsonProxy.ts b/yarn-project/json-rpc/src/server/JsonProxy.ts index 9015aa84dc4..a7064b3856f 100644 --- a/yarn-project/json-rpc/src/server/JsonProxy.ts +++ b/yarn-project/json-rpc/src/server/JsonProxy.ts @@ -1,41 +1,23 @@ import { ClassConverter, ClassConverterInput } from '../ClassConverter.js'; +import { convertFromJsonObj, convertToJsonObj } from '../convert.js'; import { assert, hasOwnProperty } from '../jsUtils.js'; import { logTrace } from '../logUtils.js'; export class JsonProxy { - classMap: ClassConverter; + classConverter: ClassConverter; constructor(private handler: object, input: ClassConverterInput) { - this.classMap = new ClassConverter(input); + this.classConverter = new ClassConverter(input); } - public call(methodName: string, jsonParams: any[] = []) { + public async call(methodName: string, jsonParams: any[] = []) { // Get access to our class members const proto = Object.getPrototypeOf(this.handler); - const convert = (obj: any): any => { - // Is this a convertible type? - if (obj.constructor.fromString) { - return this.classMap.toJsonObj(obj); - } - // Is this an array? - if (Array.isArray(obj)) { - return obj.map((x: any) => convert(x)); - } - // Is this a dictionary? - if (obj.constructor === Object) { - const newObj: any = {}; - for (const key of Object.keys(obj)) { - newObj[key] = convert(obj[key]); - } - return newObj; - } - - // Leave alone, assume JSON primitive - return obj; - }; assert(hasOwnProperty(proto, methodName), 'JsonProxy: Method not found!'); + assert(Array.isArray(jsonParams), 'JsonProxy: Params not an array!'); // convert the params from json representation to classes - const convertedParams = jsonParams.map(convert); + const convertedParams = jsonParams.map(param => convertFromJsonObj(this.classConverter, param)); logTrace('JsonProxy:call', this.handler, methodName, '<-', convertedParams); - const ret = convert((this.handler as any)[methodName](...convertedParams)); + const rawRet = await (this.handler as any)[methodName](...convertedParams); + const ret = convertToJsonObj(this.classConverter, rawRet); logTrace('JsonProxy:call', this.handler, methodName, '->', ret); return ret; } diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts index f97f7644fe8..6d3f8c8ddb2 100644 --- a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts +++ b/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts @@ -1,27 +1,29 @@ import request from 'supertest'; +import { TestState, TestNote } from '../test/TestState.js'; import { JsonRpcServer } from './JsonRpcServer.js'; -// Contrived example -class Note { - constructor(private data: string) {} - toString(): string { - return this.data; - } - static fromString(data: string): Note { - return new Note(data); - } -} - -class State { - constructor(private notes: Note[]) {} - getNotes(): Note[] { - return this.notes; - } -} +test('test an RPC function with a primitive parameter', async () => { + const server = new JsonRpcServer(new TestState([new TestNote('a'), new TestNote('b')]), { TestNote }); + const response = await request(server.getApp().callback()) + .post('/getNote') + .send({ params: [0] }); + expect(response.status).toBe(200); + expect(response.text).toBe('{"result":{"type":"TestNote","data":"a"}}'); +}); -test('test simple serialization', async () => { - const server = new JsonRpcServer(new State([new Note('a'), new Note('b')]), { Note }); - const response = await request(server.getApp().callback()).post('/getNotes'); +test('test an RPC function with an array of classes', async () => { + const server = new JsonRpcServer(new TestState([]), { TN: TestNote }); + const response = await request(server.getApp().callback()) + .post('/addNotes') + .send({ + params: [ + [ + { type: 'TN', data: 'a' }, + { type: 'TN', data: 'b' }, + { type: 'TN', data: 'c' }, + ], + ], + }); expect(response.status).toBe(200); - expect(response.text).toBe('{"result":[{"type":"Note","data":"a"},{"type":"Note","data":"b"}]}'); + expect(response.text).toBe('{"result":[{"type":"TN","data":"a"},{"type":"TN","data":"b"},{"type":"TN","data":"c"}]}'); }); diff --git a/yarn-project/json-rpc/src/test/TestState.ts b/yarn-project/json-rpc/src/test/TestState.ts new file mode 100644 index 00000000000..7788157b42c --- /dev/null +++ b/yarn-project/json-rpc/src/test/TestState.ts @@ -0,0 +1,26 @@ +import { sleep } from '../jsUtils'; + +// Contrived example for JSON RPC tests +export class TestNote { + constructor(private data: string) {} + toString(): string { + return this.data; + } + static fromString(data: string): TestNote { + return new TestNote(data); + } +} + +export class TestState { + constructor(private notes: TestNote[]) {} + getNote(index: number): TestNote { + return this.notes[index]; + } + async addNotes(notes: TestNote[]): Promise { + for (const note of notes) { + this.notes.push(note); + } + await sleep(notes.length); + return this.notes; + } +} diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 0a9ca5ecf88..f46b14c5535 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -158,6 +158,7 @@ __metadata: "@types/koa__cors": ^3.3.0 "@types/node": ^18.7.23 "@types/supertest": ^2.0.12 + comlink: ^4.4.1 jest: ^29.4.3 koa: ^2.14.1 koa-bodyparser: ^4.3.0 @@ -2527,6 +2528,13 @@ __metadata: languageName: node linkType: hard +"comlink@npm:^4.4.1": + version: 4.4.1 + resolution: "comlink@npm:4.4.1" + checksum: 16d58a8f590087fc45432e31d6c138308dfd4b75b89aec0b7f7bb97ad33d810381bd2b1e608a1fb2cf05979af9cbfcdcaf1715996d5fcf77aeb013b6da3260af + languageName: node + linkType: hard + "commander@npm:^9.0.0": version: 9.5.0 resolution: "commander@npm:9.5.0" From cd1ba7335a617e47b0eb70e63b3f79498ec5bfe5 Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Thu, 2 Mar 2023 08:21:04 -0500 Subject: [PATCH 05/14] feat(json-rpc): add Buffer support --- yarn-project/.pnp.cjs | 12 +++++- yarn-project/json-rpc/README.md | 42 +++++++++++++++++---- yarn-project/json-rpc/src/ClassConverter.ts | 1 + yarn-project/json-rpc/src/convert.ts | 9 +++++ 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/yarn-project/.pnp.cjs b/yarn-project/.pnp.cjs index 3a076b7bc80..1c3238e77b1 100755 --- a/yarn-project/.pnp.cjs +++ b/yarn-project/.pnp.cjs @@ -294,7 +294,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.0.5"],\ ["ts-node", "virtual:97973ff51783dc29efdf1c1cff3bd542763fb1d8ea565946db4f6425a5a443923944d5f46e5672160073e5b792b61ec2b3a0e9df4f007033f07c728780e0e4e7#npm:10.9.1"],\ ["tslib", "npm:2.5.0"],\ - ["typescript", "patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76"]\ + ["typescript", "patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76"],\ + ["uint8-to-base64", "npm:0.2.0"]\ ],\ "linkType": "SOFT"\ }]\ @@ -7730,6 +7731,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["uint8-to-base64", [\ + ["npm:0.2.0", {\ + "packageLocation": "./.yarn/cache/uint8-to-base64-npm-0.2.0-6c89b6b8aa-0005558e30.zip/node_modules/uint8-to-base64/",\ + "packageDependencies": [\ + ["uint8-to-base64", "npm:0.2.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["unique-filename", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/unique-filename-npm-2.0.1-183c6c7c2b-807acf3381.zip/node_modules/unique-filename/",\ diff --git a/yarn-project/json-rpc/README.md b/yarn-project/json-rpc/README.md index 361d4fcfee0..6438e568fb7 100644 --- a/yarn-project/json-rpc/README.md +++ b/yarn-project/json-rpc/README.md @@ -1,29 +1,55 @@ # json-rpc json-rpc + +``` -- src --- client + -- client + Code to use by a client wishing to use a json-rpc server + Includes syntax sugar for making requests with normal method syntax + -- server + Code for easily turning a class into an exposed RPC with one endpoint per method +``` + +Each JsonRpcClient and JsonRpcServer class needs a map of classes that will be translated in input and output values. +By default, Buffer is handled, but other usermade classes need to define toString() and static fromString() like so: + +``` + class PublicKey { + toString() { + return '...'; + } + static fromString(str) { + return new PublicKey(...); + } + } +``` + +## Usage + In Dapp: ``` -const wallet = new JsonRpcClient('wallet-server.com'); -wallet.signTxRequest(accountPubKey, txRequest); -The client will send [{ name: 'PublicKey', value: accountPubKey.toString() }, { name: 'TxRequest', txRequest.toString() }] to the server. +const wallet = new JsonRpcClient('wallet-server.com', /*register classes*/ {PublicKey, TxRequest}); +const response = await wallet.rpc.signTxRequest(accountPubKey, txRequest); ``` +The client will send `[{ name: 'PublicKey', value: accountPubKey.toString() }, { name: 'TxRequest', txRequest.toString() }]` to the server. + In wallet: ``` -const publicClient = new JsonRpcClient('public-client.com'); -const keyStore = new JsonRpcClient('key-store.com'); -Different clients for different services. +const publicClient = new JsonRpcClient('public-client.com', /*register classes*/ ...); +const keyStore = new JsonRpcClient('key-store.com', /*register classes*/ ...); ``` +Different clients for different services. + -- server Running a wallet server: ``` const wallet = new WalletImplementation(); -const server = new JsonRpcServer(wallet); +const server = new JsonRpcServer(wallet, /*register classes*/ ...); server.start(8080); ``` diff --git a/yarn-project/json-rpc/src/ClassConverter.ts b/yarn-project/json-rpc/src/ClassConverter.ts index 1a63a69535c..849818f400d 100644 --- a/yarn-project/json-rpc/src/ClassConverter.ts +++ b/yarn-project/json-rpc/src/ClassConverter.ts @@ -36,6 +36,7 @@ export class ClassConverter { } } register(type: string, class_: IOClass) { + assert(type !== 'Buffer', "'Buffer' handling is hardcoded. Cannot use as name."); assert(hasOwnProperty(class_.prototype, 'toString'), `Class ${type} must define a toString() method.`); assert(class_['fromString'], `Class ${type} must define a fromString() static method.`); this.toName.set(class_, type); diff --git a/yarn-project/json-rpc/src/convert.ts b/yarn-project/json-rpc/src/convert.ts index 22c5127d776..c9b5b8b68f8 100644 --- a/yarn-project/json-rpc/src/convert.ts +++ b/yarn-project/json-rpc/src/convert.ts @@ -4,10 +4,15 @@ export function convertFromJsonObj(cc: ClassConverter, obj: any): any { if (!obj) { return obj; // Primitive type } + // Is this a serialized Node buffer? + if (obj.type === 'Buffer' && typeof obj.data === 'string') { + return Buffer.from(obj.data, 'base64'); + } // Is this a convertible type? if (typeof obj.type === 'string' && typeof obj.data === 'string') { return cc.toClassObj(obj); } + // Is this an array? if (Array.isArray(obj)) { return obj.map((x: any) => convertFromJsonObj(cc, x)); @@ -29,6 +34,10 @@ export function convertToJsonObj(cc: ClassConverter, obj: any): any { if (!obj) { return obj; // Primitive type } + // Is this a Node buffer? + if (obj instanceof Buffer) { + return { type: 'Buffer', data: obj.toString('base64') }; + } // Is this a convertible type? if (obj.constructor.fromString) { return cc.toJsonObj(obj); From ce711b92741a71aa30935b6678787ad15ffdf5c9 Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Thu, 2 Mar 2023 08:21:51 -0500 Subject: [PATCH 06/14] chore: revert .vscode --- .vscode/launch.json | 5 +++-- .vscode/settings.json | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 7da67484f24..9ce9e4e0f3f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,8 @@ "version": "0.2.0", "configurations": [ { - "port": 9229, + "address": "${config:mainframeAddress}", + "port": 9221, "type": "node", "request": "attach", "name": "Attach to Remote", @@ -14,4 +15,4 @@ "sourceMaps": true } ] -} +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index c2b05d2eea5..12af39373c4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -126,6 +126,5 @@ }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "mainframeAddress": "localhost" + } } From 69103ef683d7339bd8d1a24d82efb319ee6a5764 Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Thu, 2 Mar 2023 08:22:52 -0500 Subject: [PATCH 07/14] chore: update Dockerfile --- yarn-project/json-rpc/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/json-rpc/Dockerfile b/yarn-project/json-rpc/Dockerfile index fae8b679966..4c91bce3358 100644 --- a/yarn-project/json-rpc/Dockerfile +++ b/yarn-project/json-rpc/Dockerfile @@ -1,7 +1,7 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base AS builder -COPY aztec.js aztec.js -WORKDIR /usr/src/yarn-project/aztec.js +COPY json-rpc json-rpc +WORKDIR /usr/src/yarn-project/json-rpc RUN yarn build && yarn formatting && yarn test FROM alpine:latest -COPY --from=builder /usr/src/yarn-project/aztec.js /usr/src/yarn-project/aztec.js \ No newline at end of file +COPY --from=builder /usr/src/yarn-project/json-rpc /usr/src/yarn-project/json-rpc \ No newline at end of file From 4d63973b5fe74bfa01588de11b91be9d7d21006a Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Thu, 2 Mar 2023 08:30:00 -0500 Subject: [PATCH 08/14] feat(json-rpc): test buffer support --- yarn-project/json-rpc/src/convert.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 yarn-project/json-rpc/src/convert.test.ts diff --git a/yarn-project/json-rpc/src/convert.test.ts b/yarn-project/json-rpc/src/convert.test.ts new file mode 100644 index 00000000000..2e272490e88 --- /dev/null +++ b/yarn-project/json-rpc/src/convert.test.ts @@ -0,0 +1,13 @@ +import { ClassConverter } from './ClassConverter.js'; +import { convertFromJsonObj, convertToJsonObj } from './convert.js'; +import { TestNote } from './test/TestState.js'; + +const TEST_BASE64 = 'YmFzZTY0IGRlY29kZXI='; +test('test an RPC function over client', () => { + const cc = new ClassConverter({ TestNote }); + const buffer = Buffer.from(TEST_BASE64, 'base64'); + expect(convertFromJsonObj(cc, convertToJsonObj(cc, buffer)).toString('base64')).toBe(TEST_BASE64); + const note = new TestNote('1'); + expect(convertFromJsonObj(cc, convertToJsonObj(cc, note))).toBeInstanceOf(TestNote); + expect(convertFromJsonObj(cc, convertToJsonObj(cc, note)).toString()).toBe('1'); +}); From 4ecaa69193352f6e81f6b6299c94f665589f12ea Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Mon, 6 Mar 2023 14:15:58 -0500 Subject: [PATCH 09/14] feat(json-rpc): move to snake-case --- .../src/{ClassConverter.ts => class_converter.ts} | 2 +- yarn-project/json-rpc/src/client/index.ts | 2 +- .../{JsonRpcClient.test.ts => json_rpc_client.test.ts} | 6 +++--- .../src/client/{JsonRpcClient.ts => json_rpc_client.ts} | 8 ++++---- yarn-project/json-rpc/src/convert.test.ts | 4 ++-- yarn-project/json-rpc/src/convert.ts | 2 +- yarn-project/json-rpc/src/{jsUtils.ts => js_utils.ts} | 0 yarn-project/json-rpc/src/{logUtils.ts => log_utils.ts} | 0 yarn-project/json-rpc/src/server/index.ts | 4 ++-- .../json-rpc/src/server/{JsonProxy.ts => json_proxy.ts} | 6 +++--- .../{JsonRpcServer.test.ts => json_rpc_server.test.ts} | 4 ++-- .../src/server/{JsonRpcServer.ts => json_rpc_server.ts} | 6 +++--- .../json-rpc/src/test/{TestState.ts => test_state.ts} | 2 +- 13 files changed, 23 insertions(+), 23 deletions(-) rename yarn-project/json-rpc/src/{ClassConverter.ts => class_converter.ts} (96%) rename yarn-project/json-rpc/src/client/{JsonRpcClient.test.ts => json_rpc_client.test.ts} (82%) rename yarn-project/json-rpc/src/client/{JsonRpcClient.ts => json_rpc_client.ts} (93%) rename yarn-project/json-rpc/src/{jsUtils.ts => js_utils.ts} (100%) rename yarn-project/json-rpc/src/{logUtils.ts => log_utils.ts} (100%) rename yarn-project/json-rpc/src/server/{JsonProxy.ts => json_proxy.ts} (85%) rename yarn-project/json-rpc/src/server/{JsonRpcServer.test.ts => json_rpc_server.test.ts} (89%) rename yarn-project/json-rpc/src/server/{JsonRpcServer.ts => json_rpc_server.ts} (93%) rename yarn-project/json-rpc/src/test/{TestState.ts => test_state.ts} (93%) diff --git a/yarn-project/json-rpc/src/ClassConverter.ts b/yarn-project/json-rpc/src/class_converter.ts similarity index 96% rename from yarn-project/json-rpc/src/ClassConverter.ts rename to yarn-project/json-rpc/src/class_converter.ts index 849818f400d..e1d50e89ca2 100644 --- a/yarn-project/json-rpc/src/ClassConverter.ts +++ b/yarn-project/json-rpc/src/class_converter.ts @@ -1,4 +1,4 @@ -import { assert, hasOwnProperty } from './jsUtils.js'; +import { assert, hasOwnProperty } from './js_utils.js'; /** * IOClass: diff --git a/yarn-project/json-rpc/src/client/index.ts b/yarn-project/json-rpc/src/client/index.ts index 21c164ac322..54992d47525 100644 --- a/yarn-project/json-rpc/src/client/index.ts +++ b/yarn-project/json-rpc/src/client/index.ts @@ -1 +1 @@ -export { JsonRpcClient } from './JsonRpcClient.js'; +export { JsonRpcClient } from './json_rpc_client.js'; diff --git a/yarn-project/json-rpc/src/client/JsonRpcClient.test.ts b/yarn-project/json-rpc/src/client/json_rpc_client.test.ts similarity index 82% rename from yarn-project/json-rpc/src/client/JsonRpcClient.test.ts rename to yarn-project/json-rpc/src/client/json_rpc_client.test.ts index 5f27171c381..7f4191d182b 100644 --- a/yarn-project/json-rpc/src/client/JsonRpcClient.test.ts +++ b/yarn-project/json-rpc/src/client/json_rpc_client.test.ts @@ -1,7 +1,7 @@ import request from 'supertest'; -import { JsonRpcServer } from '../server/JsonRpcServer.js'; -import { TestState, TestNote } from '../test/TestState.js'; -import { JsonRpcClient } from './JsonRpcClient.js'; +import { JsonRpcServer } from '../server/json_rpc_server.js'; +import { TestState, TestNote } from '../test/test_state.js'; +import { JsonRpcClient } from './json_rpc_client.js'; test('test an RPC function over client', async () => { const client = new JsonRpcClient('', { TestNote }); diff --git a/yarn-project/json-rpc/src/client/JsonRpcClient.ts b/yarn-project/json-rpc/src/client/json_rpc_client.ts similarity index 93% rename from yarn-project/json-rpc/src/client/JsonRpcClient.ts rename to yarn-project/json-rpc/src/client/json_rpc_client.ts index f34ece97211..a2e40ef1c2f 100644 --- a/yarn-project/json-rpc/src/client/JsonRpcClient.ts +++ b/yarn-project/json-rpc/src/client/json_rpc_client.ts @@ -1,12 +1,12 @@ -import { retry } from '../jsUtils'; -import { logTrace } from '../logUtils'; +import { retry } from '../js_utils.js'; +import { logTrace } from '../log_utils.js'; // comlink: // Dev dependency just for the somewhat complex RemoteObject type // This takes a {foo(): T} and makes {foo(): Promise} // while avoiding Promise of Promise. import { RemoteObject } from 'comlink'; -import { ClassConverter, ClassConverterInput } from '../ClassConverter'; -import { convertFromJsonObj, convertToJsonObj } from '../convert'; +import { ClassConverter, ClassConverterInput } from '../class_converter.js'; +import { convertFromJsonObj, convertToJsonObj } from '../convert.js'; export class JsonRpcClient { private classConverter: ClassConverter; diff --git a/yarn-project/json-rpc/src/convert.test.ts b/yarn-project/json-rpc/src/convert.test.ts index 2e272490e88..68e04fb039b 100644 --- a/yarn-project/json-rpc/src/convert.test.ts +++ b/yarn-project/json-rpc/src/convert.test.ts @@ -1,6 +1,6 @@ -import { ClassConverter } from './ClassConverter.js'; +import { ClassConverter } from './class_converter.js'; import { convertFromJsonObj, convertToJsonObj } from './convert.js'; -import { TestNote } from './test/TestState.js'; +import { TestNote } from './test/test_state.js'; const TEST_BASE64 = 'YmFzZTY0IGRlY29kZXI='; test('test an RPC function over client', () => { diff --git a/yarn-project/json-rpc/src/convert.ts b/yarn-project/json-rpc/src/convert.ts index c9b5b8b68f8..078574fc7b4 100644 --- a/yarn-project/json-rpc/src/convert.ts +++ b/yarn-project/json-rpc/src/convert.ts @@ -1,4 +1,4 @@ -import { ClassConverter } from './ClassConverter.js'; +import { ClassConverter } from './class_converter.js'; export function convertFromJsonObj(cc: ClassConverter, obj: any): any { if (!obj) { diff --git a/yarn-project/json-rpc/src/jsUtils.ts b/yarn-project/json-rpc/src/js_utils.ts similarity index 100% rename from yarn-project/json-rpc/src/jsUtils.ts rename to yarn-project/json-rpc/src/js_utils.ts diff --git a/yarn-project/json-rpc/src/logUtils.ts b/yarn-project/json-rpc/src/log_utils.ts similarity index 100% rename from yarn-project/json-rpc/src/logUtils.ts rename to yarn-project/json-rpc/src/log_utils.ts diff --git a/yarn-project/json-rpc/src/server/index.ts b/yarn-project/json-rpc/src/server/index.ts index 7dad71a929f..8495233b59d 100644 --- a/yarn-project/json-rpc/src/server/index.ts +++ b/yarn-project/json-rpc/src/server/index.ts @@ -1,2 +1,2 @@ -export { JsonRpcServer } from './JsonRpcServer.js'; -export { JsonProxy } from './JsonProxy.js'; +export { JsonRpcServer } from './json_rpc_server.js'; +export { JsonProxy } from './json_proxy.js'; diff --git a/yarn-project/json-rpc/src/server/JsonProxy.ts b/yarn-project/json-rpc/src/server/json_proxy.ts similarity index 85% rename from yarn-project/json-rpc/src/server/JsonProxy.ts rename to yarn-project/json-rpc/src/server/json_proxy.ts index a7064b3856f..6eb77697d51 100644 --- a/yarn-project/json-rpc/src/server/JsonProxy.ts +++ b/yarn-project/json-rpc/src/server/json_proxy.ts @@ -1,7 +1,7 @@ -import { ClassConverter, ClassConverterInput } from '../ClassConverter.js'; +import { ClassConverter, ClassConverterInput } from '../class_converter.js'; import { convertFromJsonObj, convertToJsonObj } from '../convert.js'; -import { assert, hasOwnProperty } from '../jsUtils.js'; -import { logTrace } from '../logUtils.js'; +import { assert, hasOwnProperty } from '../js_utils.js'; +import { logTrace } from '../log_utils.js'; export class JsonProxy { classConverter: ClassConverter; diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts b/yarn-project/json-rpc/src/server/json_rpc_server.test.ts similarity index 89% rename from yarn-project/json-rpc/src/server/JsonRpcServer.test.ts rename to yarn-project/json-rpc/src/server/json_rpc_server.test.ts index 6d3f8c8ddb2..2142325e802 100644 --- a/yarn-project/json-rpc/src/server/JsonRpcServer.test.ts +++ b/yarn-project/json-rpc/src/server/json_rpc_server.test.ts @@ -1,6 +1,6 @@ import request from 'supertest'; -import { TestState, TestNote } from '../test/TestState.js'; -import { JsonRpcServer } from './JsonRpcServer.js'; +import { TestState, TestNote } from '../test/test_state.js'; +import { JsonRpcServer } from './json_rpc_server.js'; test('test an RPC function with a primitive parameter', async () => { const server = new JsonRpcServer(new TestState([new TestNote('a'), new TestNote('b')]), { TestNote }); diff --git a/yarn-project/json-rpc/src/server/JsonRpcServer.ts b/yarn-project/json-rpc/src/server/json_rpc_server.ts similarity index 93% rename from yarn-project/json-rpc/src/server/JsonRpcServer.ts rename to yarn-project/json-rpc/src/server/json_rpc_server.ts index 7a36538194c..0b5836aabd7 100644 --- a/yarn-project/json-rpc/src/server/JsonRpcServer.ts +++ b/yarn-project/json-rpc/src/server/json_rpc_server.ts @@ -2,11 +2,11 @@ import http from 'http'; import Router from 'koa-router'; import cors from '@koa/cors'; import compress from 'koa-compress'; -import { ClassConverterInput } from '../ClassConverter.js'; +import { ClassConverterInput } from '../class_converter.js'; import Koa from 'koa'; import bodyParser from 'koa-bodyparser'; -import { JsonProxy } from './JsonProxy.js'; -import { logTrace } from '../logUtils.js'; +import { JsonProxy } from './json_proxy.js'; +import { logTrace } from '../log_utils.js'; /** * JsonRpcServer: diff --git a/yarn-project/json-rpc/src/test/TestState.ts b/yarn-project/json-rpc/src/test/test_state.ts similarity index 93% rename from yarn-project/json-rpc/src/test/TestState.ts rename to yarn-project/json-rpc/src/test/test_state.ts index 7788157b42c..3db91e675cc 100644 --- a/yarn-project/json-rpc/src/test/TestState.ts +++ b/yarn-project/json-rpc/src/test/test_state.ts @@ -1,4 +1,4 @@ -import { sleep } from '../jsUtils'; +import { sleep } from '../js_utils.js'; // Contrived example for JSON RPC tests export class TestNote { From d893c72408ee364a715bcf95faf7d5fc8ef3403e Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Tue, 7 Mar 2023 09:57:12 -0500 Subject: [PATCH 10/14] feat(json-rpc): make client a proxy object --- yarn-project/json-rpc/package.json | 5 - yarn-project/json-rpc/src/client/index.ts | 2 +- .../src/client/json_rpc_client.test.ts | 9 +- .../json-rpc/src/client/json_rpc_client.ts | 109 ++++++++---------- 4 files changed, 56 insertions(+), 69 deletions(-) diff --git a/yarn-project/json-rpc/package.json b/yarn-project/json-rpc/package.json index 3f1926c6be2..6c059a5f1dc 100644 --- a/yarn-project/json-rpc/package.json +++ b/yarn-project/json-rpc/package.json @@ -13,11 +13,6 @@ }, "jest": { "preset": "ts-jest/presets/default-esm", - "globals": { - "ts-jest": { - "useESM": true - } - }, "moduleNameMapper": { "^(\\.{1,2}/.*)\\.js$": "$1" }, diff --git a/yarn-project/json-rpc/src/client/index.ts b/yarn-project/json-rpc/src/client/index.ts index 54992d47525..134c3c43a83 100644 --- a/yarn-project/json-rpc/src/client/index.ts +++ b/yarn-project/json-rpc/src/client/index.ts @@ -1 +1 @@ -export { JsonRpcClient } from './json_rpc_client.js'; +export { createJsonRpcClient } from './json_rpc_client.js'; diff --git a/yarn-project/json-rpc/src/client/json_rpc_client.test.ts b/yarn-project/json-rpc/src/client/json_rpc_client.test.ts index 7f4191d182b..0d20b2d0222 100644 --- a/yarn-project/json-rpc/src/client/json_rpc_client.test.ts +++ b/yarn-project/json-rpc/src/client/json_rpc_client.test.ts @@ -1,17 +1,16 @@ import request from 'supertest'; import { JsonRpcServer } from '../server/json_rpc_server.js'; import { TestState, TestNote } from '../test/test_state.js'; -import { JsonRpcClient } from './json_rpc_client.js'; +import { createJsonRpcClient } from './json_rpc_client.js'; test('test an RPC function over client', async () => { - const client = new JsonRpcClient('', { TestNote }); - // Mock the method - (client as any).fetch = async (method: string, body: any) => { + const mockFetch = async (host: string, method: string, body: any) => { const server = new JsonRpcServer(new TestState([new TestNote('a'), new TestNote('b')]), { TestNote }); const result = await request(server.getApp().callback()).post(`/${method}`).send(body); return JSON.parse(result.text); }; - const result = await client.rpc.addNotes([new TestNote('c')]); + const client = createJsonRpcClient('', { TestNote }, mockFetch); + const result = await client.addNotes([new TestNote('c')]); expect(result[0]).toBeInstanceOf(TestNote); expect(result[1]).toBeInstanceOf(TestNote); expect(result[2]).toBeInstanceOf(TestNote); diff --git a/yarn-project/json-rpc/src/client/json_rpc_client.ts b/yarn-project/json-rpc/src/client/json_rpc_client.ts index a2e40ef1c2f..9869099f051 100644 --- a/yarn-project/json-rpc/src/client/json_rpc_client.ts +++ b/yarn-project/json-rpc/src/client/json_rpc_client.ts @@ -8,75 +8,68 @@ import { RemoteObject } from 'comlink'; import { ClassConverter, ClassConverterInput } from '../class_converter.js'; import { convertFromJsonObj, convertToJsonObj } from '../convert.js'; -export class JsonRpcClient { - private classConverter: ClassConverter; - public readonly rpc: RemoteObject; - private id = 0; +export async function defaultFetch(host: string, method: string, body: any) { + logTrace(`JsonRpcClient.fetch`, host, method, '<-', body); + const resp = await fetch(`${host}/${method}`, { + method: 'POST', + body: JSON.stringify(body), + headers: { 'content-type': 'application/json' }, + }); - constructor(private host: string, classMap: ClassConverterInput, private netMustSucceed = false) { - // the rpc object has syntax sugar over 'request' - // for accessing the remote methods - this.rpc = this.createRpcProxy(); - this.classConverter = new ClassConverter(classMap); + if (!resp.ok) { + throw new Error(resp.statusText); } - /** - * Creates a Proxy object that delegates over RPC - * and satisfies RemoteObject - */ - private createRpcProxy(): RemoteObject { - return new Proxy( - {}, - { - get: - (_, method: string) => - (...params: any[]) => { - logTrace(`JsonRpcClient.constructor`, 'proxy', method, '<-', params); - return this.request(method, params); - }, - }, - ) as RemoteObject; + + const text = await resp.text(); + try { + return JSON.parse(text); + } catch (err) { + throw new Error(`Failed to parse body as JSON: ${text}`); } - public async request(method: string, params: any[]): Promise { +} + +export async function mustSucceedFetch(host: string, method: string, body: any) { + return await retry(() => defaultFetch(host, method, body), 'JsonRpcClient request'); +} +/** + * Creates a Proxy object that delegates over RPC + * and satisfies RemoteObject + * The server should have ran new JsonRpcServer() + */ +export function createJsonRpcClient( + host: string, + classMap: ClassConverterInput, + fetch = defaultFetch, +) { + const classConverter = new ClassConverter(classMap); + let id = 0; + const request = async (method: string, params: any[]): Promise => { const body = { jsonrpc: '2.0', - id: this.id++, + id: id++, method, - params: params.map(param => convertToJsonObj(this.classConverter, param)), + params: params.map(param => convertToJsonObj(classConverter, param)), }; logTrace(`JsonRpcClient.request`, method, '<-', params); - const res = await this.fetch(method, body); + const res = await fetch(host, method, body); logTrace(`JsonRpcClient.request`, method, '->', res); if (res.error) { throw res.error; } - return convertFromJsonObj(this.classConverter, res.result); - } - - private async fetch(method: string, body: any) { - const tryOnce = async () => { - logTrace(`JsonRpcClient.fetch`, this.host, method, '<-', body); - const resp = await fetch(`${this.host}/${method}`, { - method: 'POST', - body: JSON.stringify(body), - headers: { 'content-type': 'application/json' }, - }); - - if (!resp.ok) { - throw new Error(resp.statusText); - } - - const text = await resp.text(); - try { - return JSON.parse(text); - } catch (err) { - throw new Error(`Failed to parse body as JSON: ${text}`); - } - }; - - if (this.netMustSucceed) { - return await retry(tryOnce, 'JsonRpcClient request'); - } + return convertFromJsonObj(classConverter, res.result); + }; - return await tryOnce(); - } + // Intercept any RPC methods with a proxy + // This wraps 'request' with a method-call syntax wrapper + return new Proxy( + {}, + { + get: + (_, method: string) => + (...params: any[]) => { + logTrace(`JsonRpcClient.constructor`, 'proxy', method, '<-', params); + return request(method, params); + }, + }, + ) as RemoteObject; } From 8993260626cee34b829e1f315f810712572156f1 Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Tue, 7 Mar 2023 09:57:21 -0500 Subject: [PATCH 11/14] feat(json-rpc): make client a proxy object --- .vscode/settings.json | 3 +- yarn-project/.pnp.cjs | 12 +- yarn-project/json-rpc/README.md | 10 +- yarn-project/json-rpc/package.json | 5 - yarn-project/json-rpc/src/client/index.ts | 2 +- .../src/client/json_rpc_client.test.ts | 9 +- .../json-rpc/src/client/json_rpc_client.ts | 109 ++++++++---------- 7 files changed, 64 insertions(+), 86 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 12af39373c4..64b124c8ddb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -126,5 +126,6 @@ }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "cmake.sourceDirectory": "${workspaceFolder}/circuits" } diff --git a/yarn-project/.pnp.cjs b/yarn-project/.pnp.cjs index 1c3238e77b1..3a076b7bc80 100755 --- a/yarn-project/.pnp.cjs +++ b/yarn-project/.pnp.cjs @@ -294,8 +294,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["ts-jest", "virtual:2c105e38078e4e3ed5a1479704e6e87fbcad156e4c266801f7bd5827dcc2c5bd1747e2d76a5bf9223d262c1d9b0e98e99574ceb2225b2ace4827ef03e9feb4b4#npm:29.0.5"],\ ["ts-node", "virtual:97973ff51783dc29efdf1c1cff3bd542763fb1d8ea565946db4f6425a5a443923944d5f46e5672160073e5b792b61ec2b3a0e9df4f007033f07c728780e0e4e7#npm:10.9.1"],\ ["tslib", "npm:2.5.0"],\ - ["typescript", "patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76"],\ - ["uint8-to-base64", "npm:0.2.0"]\ + ["typescript", "patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76"]\ ],\ "linkType": "SOFT"\ }]\ @@ -7731,15 +7730,6 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ - ["uint8-to-base64", [\ - ["npm:0.2.0", {\ - "packageLocation": "./.yarn/cache/uint8-to-base64-npm-0.2.0-6c89b6b8aa-0005558e30.zip/node_modules/uint8-to-base64/",\ - "packageDependencies": [\ - ["uint8-to-base64", "npm:0.2.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["unique-filename", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/unique-filename-npm-2.0.1-183c6c7c2b-807acf3381.zip/node_modules/unique-filename/",\ diff --git a/yarn-project/json-rpc/README.md b/yarn-project/json-rpc/README.md index 6438e568fb7..8abcc99adda 100644 --- a/yarn-project/json-rpc/README.md +++ b/yarn-project/json-rpc/README.md @@ -11,7 +11,7 @@ json-rpc Code for easily turning a class into an exposed RPC with one endpoint per method ``` -Each JsonRpcClient and JsonRpcServer class needs a map of classes that will be translated in input and output values. +Each createJsonRpcClient and JsonRpcServer call needs a map of classes that will be translated in input and output values. By default, Buffer is handled, but other usermade classes need to define toString() and static fromString() like so: ``` @@ -30,8 +30,8 @@ By default, Buffer is handled, but other usermade classes need to define toStrin In Dapp: ``` -const wallet = new JsonRpcClient('wallet-server.com', /*register classes*/ {PublicKey, TxRequest}); -const response = await wallet.rpc.signTxRequest(accountPubKey, txRequest); +const wallet = createJsonRpcClient('wallet-server.com', /*register classes*/ {PublicKey, TxRequest}); +const response = await wallet.signTxRequest(accountPubKey, txRequest); ``` The client will send `[{ name: 'PublicKey', value: accountPubKey.toString() }, { name: 'TxRequest', txRequest.toString() }]` to the server. @@ -39,8 +39,8 @@ The client will send `[{ name: 'PublicKey', value: accountPubKey.toString() }, { In wallet: ``` -const publicClient = new JsonRpcClient('public-client.com', /*register classes*/ ...); -const keyStore = new JsonRpcClient('key-store.com', /*register classes*/ ...); +const publicClient = createJsonRpcClient('public-client.com', /*register classes*/ ...); +const keyStore = createJsonRpcClient('key-store.com', /*register classes*/ ...); ``` Different clients for different services. diff --git a/yarn-project/json-rpc/package.json b/yarn-project/json-rpc/package.json index 3f1926c6be2..6c059a5f1dc 100644 --- a/yarn-project/json-rpc/package.json +++ b/yarn-project/json-rpc/package.json @@ -13,11 +13,6 @@ }, "jest": { "preset": "ts-jest/presets/default-esm", - "globals": { - "ts-jest": { - "useESM": true - } - }, "moduleNameMapper": { "^(\\.{1,2}/.*)\\.js$": "$1" }, diff --git a/yarn-project/json-rpc/src/client/index.ts b/yarn-project/json-rpc/src/client/index.ts index 54992d47525..134c3c43a83 100644 --- a/yarn-project/json-rpc/src/client/index.ts +++ b/yarn-project/json-rpc/src/client/index.ts @@ -1 +1 @@ -export { JsonRpcClient } from './json_rpc_client.js'; +export { createJsonRpcClient } from './json_rpc_client.js'; diff --git a/yarn-project/json-rpc/src/client/json_rpc_client.test.ts b/yarn-project/json-rpc/src/client/json_rpc_client.test.ts index 7f4191d182b..0d20b2d0222 100644 --- a/yarn-project/json-rpc/src/client/json_rpc_client.test.ts +++ b/yarn-project/json-rpc/src/client/json_rpc_client.test.ts @@ -1,17 +1,16 @@ import request from 'supertest'; import { JsonRpcServer } from '../server/json_rpc_server.js'; import { TestState, TestNote } from '../test/test_state.js'; -import { JsonRpcClient } from './json_rpc_client.js'; +import { createJsonRpcClient } from './json_rpc_client.js'; test('test an RPC function over client', async () => { - const client = new JsonRpcClient('', { TestNote }); - // Mock the method - (client as any).fetch = async (method: string, body: any) => { + const mockFetch = async (host: string, method: string, body: any) => { const server = new JsonRpcServer(new TestState([new TestNote('a'), new TestNote('b')]), { TestNote }); const result = await request(server.getApp().callback()).post(`/${method}`).send(body); return JSON.parse(result.text); }; - const result = await client.rpc.addNotes([new TestNote('c')]); + const client = createJsonRpcClient('', { TestNote }, mockFetch); + const result = await client.addNotes([new TestNote('c')]); expect(result[0]).toBeInstanceOf(TestNote); expect(result[1]).toBeInstanceOf(TestNote); expect(result[2]).toBeInstanceOf(TestNote); diff --git a/yarn-project/json-rpc/src/client/json_rpc_client.ts b/yarn-project/json-rpc/src/client/json_rpc_client.ts index a2e40ef1c2f..9869099f051 100644 --- a/yarn-project/json-rpc/src/client/json_rpc_client.ts +++ b/yarn-project/json-rpc/src/client/json_rpc_client.ts @@ -8,75 +8,68 @@ import { RemoteObject } from 'comlink'; import { ClassConverter, ClassConverterInput } from '../class_converter.js'; import { convertFromJsonObj, convertToJsonObj } from '../convert.js'; -export class JsonRpcClient { - private classConverter: ClassConverter; - public readonly rpc: RemoteObject; - private id = 0; +export async function defaultFetch(host: string, method: string, body: any) { + logTrace(`JsonRpcClient.fetch`, host, method, '<-', body); + const resp = await fetch(`${host}/${method}`, { + method: 'POST', + body: JSON.stringify(body), + headers: { 'content-type': 'application/json' }, + }); - constructor(private host: string, classMap: ClassConverterInput, private netMustSucceed = false) { - // the rpc object has syntax sugar over 'request' - // for accessing the remote methods - this.rpc = this.createRpcProxy(); - this.classConverter = new ClassConverter(classMap); + if (!resp.ok) { + throw new Error(resp.statusText); } - /** - * Creates a Proxy object that delegates over RPC - * and satisfies RemoteObject - */ - private createRpcProxy(): RemoteObject { - return new Proxy( - {}, - { - get: - (_, method: string) => - (...params: any[]) => { - logTrace(`JsonRpcClient.constructor`, 'proxy', method, '<-', params); - return this.request(method, params); - }, - }, - ) as RemoteObject; + + const text = await resp.text(); + try { + return JSON.parse(text); + } catch (err) { + throw new Error(`Failed to parse body as JSON: ${text}`); } - public async request(method: string, params: any[]): Promise { +} + +export async function mustSucceedFetch(host: string, method: string, body: any) { + return await retry(() => defaultFetch(host, method, body), 'JsonRpcClient request'); +} +/** + * Creates a Proxy object that delegates over RPC + * and satisfies RemoteObject + * The server should have ran new JsonRpcServer() + */ +export function createJsonRpcClient( + host: string, + classMap: ClassConverterInput, + fetch = defaultFetch, +) { + const classConverter = new ClassConverter(classMap); + let id = 0; + const request = async (method: string, params: any[]): Promise => { const body = { jsonrpc: '2.0', - id: this.id++, + id: id++, method, - params: params.map(param => convertToJsonObj(this.classConverter, param)), + params: params.map(param => convertToJsonObj(classConverter, param)), }; logTrace(`JsonRpcClient.request`, method, '<-', params); - const res = await this.fetch(method, body); + const res = await fetch(host, method, body); logTrace(`JsonRpcClient.request`, method, '->', res); if (res.error) { throw res.error; } - return convertFromJsonObj(this.classConverter, res.result); - } - - private async fetch(method: string, body: any) { - const tryOnce = async () => { - logTrace(`JsonRpcClient.fetch`, this.host, method, '<-', body); - const resp = await fetch(`${this.host}/${method}`, { - method: 'POST', - body: JSON.stringify(body), - headers: { 'content-type': 'application/json' }, - }); - - if (!resp.ok) { - throw new Error(resp.statusText); - } - - const text = await resp.text(); - try { - return JSON.parse(text); - } catch (err) { - throw new Error(`Failed to parse body as JSON: ${text}`); - } - }; - - if (this.netMustSucceed) { - return await retry(tryOnce, 'JsonRpcClient request'); - } + return convertFromJsonObj(classConverter, res.result); + }; - return await tryOnce(); - } + // Intercept any RPC methods with a proxy + // This wraps 'request' with a method-call syntax wrapper + return new Proxy( + {}, + { + get: + (_, method: string) => + (...params: any[]) => { + logTrace(`JsonRpcClient.constructor`, 'proxy', method, '<-', params); + return request(method, params); + }, + }, + ) as RemoteObject; } From 0acff434571c9aa09663987f3557932e1d31037a Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Tue, 7 Mar 2023 09:59:40 -0500 Subject: [PATCH 12/14] Revert .vscode --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 64b124c8ddb..12af39373c4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -126,6 +126,5 @@ }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "cmake.sourceDirectory": "${workspaceFolder}/circuits" + } } From 353cea6734a7d5abda30808685296efc2e4636cc Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Tue, 7 Mar 2023 10:17:21 -0500 Subject: [PATCH 13/14] chore: remove comment --- yarn-project/json-rpc/src/server/json_rpc_server.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/json-rpc/src/server/json_rpc_server.ts b/yarn-project/json-rpc/src/server/json_rpc_server.ts index 0b5836aabd7..ac261eb1ca1 100644 --- a/yarn-project/json-rpc/src/server/json_rpc_server.ts +++ b/yarn-project/json-rpc/src/server/json_rpc_server.ts @@ -52,7 +52,6 @@ export class JsonRpcServer { if (method === 'constructor' || typeof proto[method] !== 'function') { continue; } - // console.log(method, (this.handler as any)[method]); router.post(`/${method}`, async (ctx: Koa.Context) => { const { params = [], jsonrpc, id } = ctx.request.body as any; logTrace('JsonRpcServer:getRouter', method, '<-', params); From 6be3fef663b94e93d6e54124d8fa835cc7934a9e Mon Sep 17 00:00:00 2001 From: Adam Domurad Date: Tue, 14 Mar 2023 14:45:16 -0400 Subject: [PATCH 14/14] docs: Documentation pass --- yarn-project/eslint-config/index.js | 3 + yarn-project/eslint-config/package.json | 1 + yarn-project/json-rpc/package.json | 2 +- yarn-project/json-rpc/src/class_converter.ts | 55 ++++++++++++++++--- .../json-rpc/src/client/json_rpc_client.ts | 33 +++++++---- yarn-project/json-rpc/src/convert.test.ts | 2 + yarn-project/json-rpc/src/convert.ts | 13 +++++ yarn-project/json-rpc/src/js_utils.ts | 10 +++- 8 files changed, 99 insertions(+), 20 deletions(-) diff --git a/yarn-project/eslint-config/index.js b/yarn-project/eslint-config/index.js index 33833650a8c..6e721a45772 100644 --- a/yarn-project/eslint-config/index.js +++ b/yarn-project/eslint-config/index.js @@ -3,10 +3,13 @@ const contexts = [ 'MethodDefinition', 'TSPropertySignature', 'PropertySignature', + 'TSInterfaceDeclaration > TSPropertyDefinition', + 'InterfaceDeclaration > PropertyDefinition', 'TSInterfaceDeclaration', 'InterfaceDeclaration', 'TSTypeAliasDeclaration', 'TypeAliasDeclaration', + // TODO how to ensure non-function exports are documented? 'TSTypeDeclaration', 'TypeDeclaration', 'TSEnumDeclaration', diff --git a/yarn-project/eslint-config/package.json b/yarn-project/eslint-config/package.json index b059ec8e99c..e3ad97ed48b 100644 --- a/yarn-project/eslint-config/package.json +++ b/yarn-project/eslint-config/package.json @@ -8,6 +8,7 @@ "eslint": "^8.21.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-jsdoc": "^40.0.0", + "eslint-plugin-node": "^11.1.0", "eslint-plugin-tsdoc": "^0.2.17" } } diff --git a/yarn-project/json-rpc/package.json b/yarn-project/json-rpc/package.json index 6c059a5f1dc..373a828bba0 100644 --- a/yarn-project/json-rpc/package.json +++ b/yarn-project/json-rpc/package.json @@ -7,7 +7,7 @@ "build": "yarn clean && yarn formatting && tsc -b tsconfig.dest.json", "build:dev": "tsc -b tsconfig.dest.json --watch", "clean": "rm -rf ./dest .tsbuildinfo", - "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 0 ./src", + "formatting": "run -T prettier --check ./src && run -T eslint --max-warnings 16 ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache", "test-debug": "NODE_NO_WARNINGS=1 node --inspect-brk --experimental-vm-modules $(yarn bin jest) --no-cache --runInBand --testTimeout 1000000" }, diff --git a/yarn-project/json-rpc/src/class_converter.ts b/yarn-project/json-rpc/src/class_converter.ts index e1d50e89ca2..7d0bf382228 100644 --- a/yarn-project/json-rpc/src/class_converter.ts +++ b/yarn-project/json-rpc/src/class_converter.ts @@ -1,9 +1,9 @@ import { assert, hasOwnProperty } from './js_utils.js'; /** - * IOClass: - * Represents a class compatible with our class conversion system - * e.g. PublicKey here satisfies 'IOClass' + * Represents a class compatible with our class conversion system. + * E.g. PublicKey here satisfies 'IOClass'. + * ``` * class PublicKey { * toString() { * return '...'; @@ -12,29 +12,60 @@ import { assert, hasOwnProperty } from './js_utils.js'; * return new PublicKey(...); * } * } + * ``` */ interface IOClass { new (...args: any): any; + /** + * Creates an IOClass from a given string. + */ fromString: (str: string) => any; } +/** + * Registered classes available for conversion. + */ export interface ClassConverterInput { [className: string]: IOClass; } /** - * Handles mapping of classes to names, and calling toString and fromString - * to convert to and from JSON-friendly formats + * Represents a class in a JSON-friendly encoding. + */ +export interface JsonEncodedClass { + /** + * The class type. + */ + type: string; + /** + * The class data string. + */ + data: string; +} + +/** + * Handles mapping of classes to names, and calling toString and fromString to convert to and from JSON-friendly formats. + * Takes a class map as input. */ export class ClassConverter { private toClass = new Map(); private toName = new Map(); + /** + * Create a class converter from a table of classes. + * @param input - The class table. + */ constructor(input: ClassConverterInput) { for (const key of Object.keys(input)) { this.register(key, input[key]); } } + /** + * Register a class with a certain name. + * This name is used for conversion from and to this class. + * @param type - The class name to use for serialization. + * @param class_ - The class object. + */ register(type: string, class_: IOClass) { assert(type !== 'Buffer', "'Buffer' handling is hardcoded. Cannot use as name."); assert(hasOwnProperty(class_.prototype, 'toString'), `Class ${type} must define a toString() method.`); @@ -42,12 +73,22 @@ export class ClassConverter { this.toName.set(class_, type); this.toClass.set(type, class_); } - toClassObj(jsonObj: { type: string; data: string }) { + /** + * Convert a JSON-like object to a class object. + * @param jsonObj - An object encoding a class. + * @returns The class object. + */ + toClassObj(jsonObj: JsonEncodedClass): any { const class_ = this.toClass.get(jsonObj.type); assert(class_, `Could not find type in lookup.`); return class_!.fromString(jsonObj.data); } - toJsonObj(classObj: any) { + /** + * Convert a JSON-like object to a class object. + * @param classObj - A JSON encoding a class. + * @returns The class object. + */ + toJsonObj(classObj: any): JsonEncodedClass { const type = this.toName.get(classObj.constructor); assert(type, `Could not find class in lookup.`); return { type: type!, data: classObj.toString() }; diff --git a/yarn-project/json-rpc/src/client/json_rpc_client.ts b/yarn-project/json-rpc/src/client/json_rpc_client.ts index 9869099f051..e77a1f13957 100644 --- a/yarn-project/json-rpc/src/client/json_rpc_client.ts +++ b/yarn-project/json-rpc/src/client/json_rpc_client.ts @@ -8,9 +8,17 @@ import { RemoteObject } from 'comlink'; import { ClassConverter, ClassConverterInput } from '../class_converter.js'; import { convertFromJsonObj, convertToJsonObj } from '../convert.js'; -export async function defaultFetch(host: string, method: string, body: any) { - logTrace(`JsonRpcClient.fetch`, host, method, '<-', body); - const resp = await fetch(`${host}/${method}`, { +/** + * A normal fetch function that does not retry. + * Alternatives are a fetch function with retries, or a mocked fetch. + * @param host - The host URL. + * @param method - The RPC method name. + * @param body - The RPC payload. + * @returns The parsed JSON response, or throws an error. + */ +export async function defaultFetch(host: string, rpcMethod: string, body: any) { + logTrace(`JsonRpcClient.fetch`, host, rpcMethod, '<-', body); + const resp = await fetch(`${host}/${rpcMethod}`, { method: 'POST', body: JSON.stringify(body), headers: { 'content-type': 'application/json' }, @@ -28,13 +36,16 @@ export async function defaultFetch(host: string, method: string, body: any) { } } -export async function mustSucceedFetch(host: string, method: string, body: any) { - return await retry(() => defaultFetch(host, method, body), 'JsonRpcClient request'); +/** + * A fetch function with retries. + */ +export async function mustSucceedFetch(host: string, rpcMethod: string, body: any) { + return await retry(() => defaultFetch(host, rpcMethod, body), 'JsonRpcClient request'); } + /** - * Creates a Proxy object that delegates over RPC - * and satisfies RemoteObject - * The server should have ran new JsonRpcServer() + * Creates a Proxy object that delegates over RPC and satisfies RemoteObject. + * The server should have ran new JsonRpcServer(). */ export function createJsonRpcClient( host: string, @@ -65,10 +76,10 @@ export function createJsonRpcClient( {}, { get: - (_, method: string) => + (_, rpcMethod: string) => (...params: any[]) => { - logTrace(`JsonRpcClient.constructor`, 'proxy', method, '<-', params); - return request(method, params); + logTrace(`JsonRpcClient.constructor`, 'proxy', rpcMethod, '<-', params); + return request(rpcMethod, params); }, }, ) as RemoteObject; diff --git a/yarn-project/json-rpc/src/convert.test.ts b/yarn-project/json-rpc/src/convert.test.ts index 68e04fb039b..2423598a72e 100644 --- a/yarn-project/json-rpc/src/convert.test.ts +++ b/yarn-project/json-rpc/src/convert.test.ts @@ -2,6 +2,8 @@ import { ClassConverter } from './class_converter.js'; import { convertFromJsonObj, convertToJsonObj } from './convert.js'; import { TestNote } from './test/test_state.js'; +import { Buffer } from 'buffer'; + const TEST_BASE64 = 'YmFzZTY0IGRlY29kZXI='; test('test an RPC function over client', () => { const cc = new ClassConverter({ TestNote }); diff --git a/yarn-project/json-rpc/src/convert.ts b/yarn-project/json-rpc/src/convert.ts index 078574fc7b4..c80af2be960 100644 --- a/yarn-project/json-rpc/src/convert.ts +++ b/yarn-project/json-rpc/src/convert.ts @@ -1,5 +1,12 @@ import { ClassConverter } from './class_converter.js'; +import { Buffer } from 'buffer'; +/** + * Convert a JSON-friendly object, which may encode a class object. + * @param cc - The class converter. + * @param obj - The encoded object. + * @returns The decoded object. + */ export function convertFromJsonObj(cc: ClassConverter, obj: any): any { if (!obj) { return obj; // Primitive type @@ -30,6 +37,12 @@ export function convertFromJsonObj(cc: ClassConverter, obj: any): any { return obj; } +/** + * Convert objects or classes to a JSON-friendly object. + * @param cc - The class converter. + * @param obj - The object. + * @returns The encoded object. + */ export function convertToJsonObj(cc: ClassConverter, obj: any): any { if (!obj) { return obj; // Primitive type diff --git a/yarn-project/json-rpc/src/js_utils.ts b/yarn-project/json-rpc/src/js_utils.ts index 260c33e151a..02a8a53338d 100644 --- a/yarn-project/json-rpc/src/js_utils.ts +++ b/yarn-project/json-rpc/src/js_utils.ts @@ -1,5 +1,13 @@ // Make sure this property was not inherited -export const hasOwnProperty = (class_: any, method: string) => Object.prototype.hasOwnProperty.call(class_, method); + +/** + * Does this own the property? + * @param obj - An object. + * @param method - A property name. + */ +export const hasOwnProperty = (obj: any, propertyName: string) => + Object.prototype.hasOwnProperty.call(obj, propertyName); + export const assert = (x: any, err: string) => { if (!x) { throw new Error(err);