From e6ae7bfcc69d997ee1f6caefce312e386e7e4be3 Mon Sep 17 00:00:00 2001 From: Mateusz Kubaszek Date: Fri, 23 Feb 2024 22:20:19 +0100 Subject: [PATCH 1/6] feat: prepare base fastify template feat: add some defaults plugins feat: start working on tests feat: working with types feat: finished test feat: finished test feat: update package --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 4 +- .idea/workspace.xml | 66 + package-lock.json | 1244 ++++++++++------- package.json | 3 +- packages/emmett-fastify/package.json | 55 + .../emmett-fastify/src/e2e/decider/api.ts | 133 ++ .../applicationLogicWithOC.int.spec.ts | 152 ++ .../src/e2e/decider/businessLogic.ts | 189 +++ .../src/e2e/decider/shoppingCart.ts | 175 +++ packages/emmett-fastify/src/e2e/testing.ts | 42 + packages/emmett-fastify/src/index.ts | 102 ++ packages/emmett-fastify/tsconfig.build.json | 6 + packages/emmett-fastify/tsconfig.json | 17 + packages/emmett-fastify/tsup.config.ts | 20 + tsconfig.json | 6 +- 16 files changed, 1688 insertions(+), 526 deletions(-) create mode 100644 .DS_Store create mode 100644 .idea/workspace.xml create mode 100644 packages/emmett-fastify/package.json create mode 100644 packages/emmett-fastify/src/e2e/decider/api.ts create mode 100644 packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts create mode 100644 packages/emmett-fastify/src/e2e/decider/businessLogic.ts create mode 100644 packages/emmett-fastify/src/e2e/decider/shoppingCart.ts create mode 100644 packages/emmett-fastify/src/e2e/testing.ts create mode 100644 packages/emmett-fastify/src/index.ts create mode 100644 packages/emmett-fastify/tsconfig.build.json create mode 100644 packages/emmett-fastify/tsconfig.json create mode 100644 packages/emmett-fastify/tsup.config.ts diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fb4857b214405c1f3b6d09d6e443962c221a9414 GIT binary patch literal 6148 zcmeHK&2AGh5FRIiY-o#8sg)2C(n?%INDv^TUeYu@aNyD)H~--*~ul`Gkn#49`u!|_B9$l)^ zm{Qbi+!qVCO9KkvzmNP3_V<9|czvqV1?4Dbi;=}0%fq(iVIA&+h4U<&HB#~OZ}#CN zADA!Nw{Vaq`KZzOAqvIPwd-ZC>}`2(y61Az9R;It-VTPZxb|GiH2hNz!WT(A=~efR zWHt(tEFLOA62&li{W8fSIcdvr7Uc@t)g4~NtMsb3udbR88qJ!IY+CcV@~GxNe)wcM zt$6!)?;o7>`srmRKVlXTfp4%9UekH`gvt^V@4Le+mDw5k7+0YaI;KPF&@<>d);C&Q zlLA}L?}mLKVtR)(M9Q$9F|YxRR7-+VinU$k>AU5r47&gk2dj2d@yN2?L4+L9uxk)K z!H!z98;V~o + + + + + + + + + + + + + + + + + + + { + "customColor": "", + "associatedIndex": 2 +} + + + + + + + + + 1709677145533 + + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index bcd3deaa..bf846821 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "packages/emmett", "packages/emmett-esdb", "packages/emmett-expressjs", - "packages/emmett-testcontainers" + "packages/emmett-testcontainers", + "packages/emmett-fastify" ], "devDependencies": { "@faker-js/faker": "8.4.1", @@ -300,70 +301,6 @@ } } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", @@ -380,294 +317,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -758,6 +407,10 @@ "resolved": "packages/emmett-expressjs", "link": true }, + "node_modules/@event-driven-io/emmett-fastify": { + "resolved": "packages/emmett-fastify", + "link": true + }, "node_modules/@event-driven-io/emmett-testcontainers": { "resolved": "packages/emmett-testcontainers", "link": true @@ -811,6 +464,97 @@ "npm": ">=6.14.13" } }, + "node_modules/@fastify/accept-negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz", + "integrity": "sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@fastify/ajv-compiler": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.5.0.tgz", + "integrity": "sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==", + "dependencies": { + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "fast-uri": "^2.0.0" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@fastify/compress": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@fastify/compress/-/compress-7.0.0.tgz", + "integrity": "sha512-jo/NaBVHP1OXIf8Kmr3bZyYQB0gAIgcy5c8rRKTPjhklHO7lRs/6ZFckUVT0NtbKSvrTuIcmSkxYpjyv3FNHXA==", + "dependencies": { + "@fastify/accept-negotiator": "^1.1.0", + "fastify-plugin": "^4.5.0", + "into-stream": "^6.0.0", + "mime-db": "^1.52.0", + "minipass": "^7.0.2", + "peek-stream": "^1.1.3", + "pump": "^3.0.0", + "pumpify": "^2.0.1" + } + }, + "node_modules/@fastify/error": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", + "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==" + }, + "node_modules/@fastify/etag": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@fastify/etag/-/etag-5.1.0.tgz", + "integrity": "sha512-j/huE8baxgF22idzY35a579b6uP+9ykE9Jt02xY4ZApELNr2KGZmQOKTQsZS94TfKMLfPHwkoM8FfZRq8OZDXg==", + "dependencies": { + "fastify-plugin": "^4.0.0" + } + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", + "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==", + "dependencies": { + "fast-json-stringify": "^5.7.0" + } + }, + "node_modules/@fastify/formbody": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-7.4.0.tgz", + "integrity": "sha512-H3C6h1GN56/SMrZS8N2vCT2cZr7mIHzBHzOBa5OPpjfB/D6FzP9mMpE02ZzrFX0ANeh0BAJdoXKOF2e7IbV+Og==", + "dependencies": { + "fast-querystring": "^1.0.0", + "fastify-plugin": "^4.0.0" + } + }, + "node_modules/@fastify/merge-json-schemas": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", + "integrity": "sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, "node_modules/@grpc/grpc-js": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.1.tgz", @@ -1110,32 +854,6 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "dev": true }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", - "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz", - "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", @@ -1149,136 +867,6 @@ "darwin" ] }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz", - "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz", - "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz", - "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz", - "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz", - "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz", - "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz", - "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz", - "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz", - "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz", - "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@shikijs/core": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.1.5.tgz", @@ -2084,6 +1672,22 @@ } } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2142,6 +1746,42 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/algoliasearch": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", @@ -2310,6 +1950,11 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -2366,6 +2011,25 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/avvio": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.3.0.tgz", + "integrity": "sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==", + "dependencies": { + "@fastify/error": "^3.3.0", + "archy": "^1.0.0", + "debug": "^4.0.0", + "fastq": "^1.17.1" + } + }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", @@ -2556,6 +2220,11 @@ "node": "*" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "node_modules/buildcheck": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", @@ -2740,6 +2409,11 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/close-with-grace": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/close-with-grace/-/close-with-grace-1.3.0.tgz", + "integrity": "sha512-lvm0rmLIR5bNz4CRKW6YvCfn9Wg5Wb9A8PJ3Bb+hjyikgC1RO1W3J4z9rBXQYw97mAte7dNSQI8BmUsxdlXQyw==" + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3069,6 +2743,44 @@ "node": ">=6.0.0" } }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3414,7 +3126,23 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { - "node": ">= 0.6" + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" } }, "node_modules/execa": { @@ -3522,11 +3250,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fast-content-type-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz", + "integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==" + }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -3573,23 +3310,115 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-json-stringify": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.12.0.tgz", + "integrity": "sha512-7Nnm9UPa7SfHRbHVA1kJQrGXCRzB7LMlAAqHXQFkEQqueJm1V8owm0FsE/2Do55/4CcdhwiLQERaKomOnKQkyA==", + "dependencies": { + "@fastify/merge-json-schemas": "^0.1.0", + "ajv": "^8.10.0", + "ajv-formats": "^2.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^2.1.0", + "json-schema-ref-resolver": "^1.0.1", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-redact": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", + "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, + "node_modules/fast-uri": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.3.0.tgz", + "integrity": "sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==" + }, + "node_modules/fastify": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.26.1.tgz", + "integrity": "sha512-tznA/G55dsxzM5XChBfcvVSloG2ejeeotfPPJSFaWmHyCDVGMpvf3nRNbsCb/JTBF9RmQFBfuujWt3Nphjesng==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "dependencies": { + "@fastify/ajv-compiler": "^3.5.0", + "@fastify/error": "^3.4.0", + "@fastify/fast-json-stringify-compiler": "^4.3.0", + "abstract-logging": "^2.0.1", + "avvio": "^8.3.0", + "fast-content-type-parse": "^1.1.0", + "fast-json-stringify": "^5.8.0", + "find-my-way": "^8.0.0", + "light-my-request": "^5.11.0", + "pino": "^8.17.0", + "process-warning": "^3.0.0", + "proxy-addr": "^2.0.7", + "rfdc": "^1.3.0", + "secure-json-parse": "^2.7.0", + "semver": "^7.5.4", + "toad-cache": "^3.3.0" + } + }, + "node_modules/fastify-plugin": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", + "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==" + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } @@ -3648,6 +3477,19 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/find-my-way": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.1.0.tgz", + "integrity": "sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3754,6 +3596,42 @@ "node": ">= 0.6" } }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -4120,6 +3998,21 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/into-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", + "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -4265,6 +4158,14 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/json-schema-ref-resolver": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", + "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4349,6 +4250,29 @@ "node": ">= 0.8.0" } }, + "node_modules/light-my-request": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.11.1.tgz", + "integrity": "sha512-KXAh2m6VRlkWCk2KfmHE7tLBXKh30JE0tXUJY4dNxje4oLmPKUqlUfImiEQZLphx+Z9KTQcVv4DjGnJxkVOIbA==", + "dependencies": { + "cookie": "^0.6.0", + "process-warning": "^2.0.0", + "set-cookie-parser": "^2.4.1" + } + }, + "node_modules/light-my-request/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/light-my-request/node_modules/process-warning": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.2.tgz", + "integrity": "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==" + }, "node_modules/lilconfig": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", @@ -4599,7 +4523,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -4807,6 +4730,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -4858,6 +4789,14 @@ "node": ">= 0.8.0" } }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -4964,6 +4903,16 @@ "node": ">=8" } }, + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, "node_modules/perfect-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", @@ -5000,6 +4949,79 @@ "node": ">=0.10" } }, + "node_modules/pino": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.19.0.tgz", + "integrity": "sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", + "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -5118,11 +5140,24 @@ "node": ">=6.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -5198,11 +5233,31 @@ "once": "^1.3.1" } }, + "node_modules/pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "dependencies": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, + "node_modules/pumpify/node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -5247,6 +5302,11 @@ "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -5326,6 +5386,14 @@ "node": ">=8.10.0" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5335,6 +5403,14 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -5353,6 +5429,14 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -5365,7 +5449,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -5374,8 +5457,7 @@ "node_modules/rfdc": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", - "dev": true + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" }, "node_modules/rimraf": { "version": "3.0.2", @@ -5508,6 +5590,22 @@ } ] }, + "node_modules/safe-regex2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", + "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", + "dependencies": { + "ret": "~0.2.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5520,11 +5618,15 @@ "dev": true, "peer": true }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -5539,7 +5641,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -5613,6 +5714,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + }, "node_modules/set-function-length": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", @@ -5711,6 +5817,14 @@ "node": ">=8" } }, + "node_modules/sonic-boom": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", + "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.8.0-beta.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", @@ -5746,6 +5860,14 @@ "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==" }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/ssh-remote-port-forward": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz", @@ -5789,6 +5911,11 @@ "node": ">= 0.8" } }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" + }, "node_modules/streamx": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.16.1.tgz", @@ -6106,6 +6233,50 @@ "node": ">=0.8" } }, + "node_modules/thread-stream": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", + "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -6126,6 +6297,14 @@ "node": ">=8.0" } }, + "node_modules/toad-cache": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", + "engines": { + "node": ">=12" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -6381,7 +6560,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -6670,6 +6848,14 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -6682,8 +6868,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "2.3.4", @@ -6878,6 +7063,19 @@ "uuid": "9.0.1" } }, + "packages/emmett-fastify": { + "name": "@event-driven-io/emmett-fastify", + "version": "0.1.8", + "dependencies": { + "@event-driven-io/emmett": "^0.4.0", + "@fastify/compress": "7.0.0", + "@fastify/etag": "5.1.0", + "@fastify/formbody": "7.4.0", + "close-with-grace": "1.3.0", + "fastify": "4.26.1" + }, + "devDependencies": {} + }, "packages/emmett-testcontainers": { "name": "@event-driven-io/emmett-testcontainers", "version": "0.4.0", diff --git a/package.json b/package.json index 07b1ad60..d26ae487 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "packages/emmett", "packages/emmett-esdb", "packages/emmett-expressjs", - "packages/emmett-testcontainers" + "packages/emmett-testcontainers", + "packages/emmett-fastify" ] } diff --git a/packages/emmett-fastify/package.json b/packages/emmett-fastify/package.json new file mode 100644 index 00000000..d28572ce --- /dev/null +++ b/packages/emmett-fastify/package.json @@ -0,0 +1,55 @@ +{ + "name": "@event-driven-io/emmett-fastify", + "version": "0.1.8", + "description": "Emmett - Event Sourcing development made simple", + "scripts": { + "build": "tsup", + "build:ts": "tsc", + "build:ts:watch": "tsc --watch", + "lint": "npm run lint:eslint && npm run lint:prettier", + "lint:prettier": "prettier --check \"**/**/!(*.d).{ts,json,md}\"", + "lint:eslint": "eslint **/*.ts", + "fix": "run-s fix:eslint fix:prettier", + "fix:prettier": "prettier --write \"**/**/!(*.d).{ts,json,md}\"", + "fix:eslint": "eslint **/*.ts --fix", + "test": "run-s test:unit test:int test:e2e", + "test:unit": "glob -c \"node --import tsx --test\" **/*.unit.spec.ts", + "test:int": "glob -c \"node --import tsx --test\" **/*.int.spec.ts", + "test:e2e": "glob -c \"node --import tsx --test\" **/*.e2e.spec.ts", + "test:watch": "node --import tsx --test --watch", + "test:unit:watch": "glob -c \"node --import tsx --test --watch\" **/*.unit.spec.ts", + "test:int:watch": "glob -c \"node --import tsx --test --watch\" **/*.int.spec.ts", + "test:e2e:watch": "glob -c \"node --import tsx --test --watch\" **/*.e2e.spec.ts" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/event-driven-io/emmett.git" + }, + "keywords": [ + "Event Sourcing", + "Fastify" + ], + "author": "Oskar Dudycz", + "contributors": [ + "Mateusz Kubaszek mkubasz@gmail.com" + ], + "bugs": { + "url": "https://github.com/event-driven-io/emmett/issues" + }, + "homepage": "https://event-driven-io.github.io/emmett/", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "dependencies": { + "@event-driven-io/emmett": "^0.4.0", + "fastify": "4.26.1", + "@fastify/compress": "7.0.0", + "@fastify/etag": "5.1.0", + "@fastify/formbody": "7.4.0", + "close-with-grace": "1.3.0" + }, + "devDependencies": {} +} diff --git a/packages/emmett-fastify/src/e2e/decider/api.ts b/packages/emmett-fastify/src/e2e/decider/api.ts new file mode 100644 index 00000000..f30a4e22 --- /dev/null +++ b/packages/emmett-fastify/src/e2e/decider/api.ts @@ -0,0 +1,133 @@ +import { + assertNotEmptyString, + STREAM_DOES_NOT_EXIST, + DeciderCommandHandler, + type EventStore, + assertPositiveNumber, + assertUnsignedBigInt, +} from '@event-driven-io/emmett'; +import { + type FastifyInstance, + type FastifyReply, + type FastifyRequest, +} from 'fastify'; +import { decider } from './businessLogic'; +import { type PricedProductItem, type ProductItem } from './shoppingCart'; + + +export const handle = DeciderCommandHandler(decider); +const dummyPriceProvider = (_productId: string) => { + return 100; +}; + +interface ShoppingCartItem { + shoppingCartId: string; +} + +export const RegisterRoutes = (eventStore: EventStore) => (app: FastifyInstance) => { + app.post( + '/clients/:clientId/shopping-carts', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { clientId } = request.params as { clientId: string }; + assertNotEmptyString(clientId); + const shoppingCartId = clientId; + await handle( + eventStore, + shoppingCartId, + { + type: 'OpenShoppingCart', + data: { clientId: shoppingCartId, shoppingCartId, now: new Date() }, + }, + ); + reply.code(201).send({ clientId }); + }, + ); + app.post( + '/clients/:clientId/shopping-carts/:shoppingCartId/product-items', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); + const { productId, quantity } = request.body as PricedProductItem; + const productItem: ProductItem = { + productId: assertNotEmptyString(productId), + quantity: assertPositiveNumber(quantity), + }; + + const unitPrice = dummyPriceProvider(productItem.productId); + await handle( + eventStore, + shoppingCartId, + { + type: 'AddProductItemToShoppingCart', + data: { + shoppingCartId, + productItem: { ...productItem, unitPrice }, + }, + }, + + ); + reply.code(204); + }, + ); + app.delete( + '/clients/:clientId/shopping-carts/:shoppingCartId/product-items', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); + const { productId, quantity, unitPrice } = request.query as PricedProductItem; + const productItem: PricedProductItem = { + productId: assertNotEmptyString(productId), + quantity: assertPositiveNumber(Number(quantity)), + unitPrice: assertPositiveNumber(Number(unitPrice)), + }; + + await handle( + eventStore, + shoppingCartId, + { + type: 'RemoveProductItemFromShoppingCart', + data: { shoppingCartId, productItem }, + }, + ); + reply.code(204); + }, + ); + app.post( + '/clients/:clientId/shopping-carts/:shoppingCartId/confirm', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); + + await handle( + eventStore, + shoppingCartId, + { + type: 'ConfirmShoppingCart', + data: { shoppingCartId, now: new Date() }, + }, + + ); + reply.code(204); + }, + ); + app.delete( + '/clients/:clientId/shopping-carts/:shoppingCartId', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); + try { + await handle( + eventStore, + shoppingCartId, + { + type: 'CancelShoppingCart', + data: { shoppingCartId, now: new Date() }, + }, + ); + } catch (error) { + reply.code(403).send({ detail: error.message }); + } + reply.code(204); + }, + ); +}; diff --git a/packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts b/packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts new file mode 100644 index 00000000..8462ce6e --- /dev/null +++ b/packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts @@ -0,0 +1,152 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ +import assert from 'node:assert/strict'; +import { beforeEach, describe, it } from 'node:test'; +import { v4 as uuid } from 'uuid'; +import { type FastifyInstance } from 'fastify'; +import { getInMemoryEventStore, type EventStore, assertMatches } from '@event-driven-io/emmett'; +import { getApplication } from '../..'; +import { RegisterRoutes } from './api'; +import { ShoppingCartErrors } from './businessLogic'; +import type { ShoppingCartEvent } from './shoppingCart'; + +describe('Application logic with optimistic concurrency using Fastify', () => { + let app: FastifyInstance; + let eventStore: EventStore; + beforeEach(async () => { + + eventStore = getInMemoryEventStore(); + const registerRoutes = RegisterRoutes(eventStore); + app = await getApplication({ registerRoutes }); + }); + + it('Should handle requests correctly', async () => { + const clientId = uuid(); + /////////////////////////////////////////////////// + // 1. Open Shopping Cart + /////////////////////////////////////////////////// + + const createResponse = await app.inject({ + method: 'POST', + url: `/clients/${clientId}/shopping-carts`, + }); + + const current = createResponse.json(); + if (!current?.clientId) { + assert.fail(); + } + assert.ok(current.clientId); + + const shoppingCartId = current.clientId; + /////////////////////////////////////////////////// + // 2. Add Two Pair of Shoes + /////////////////////////////////////////////////// + const twoPairsOfShoes = { + quantity: 2, + productId: '123', + }; + let response = await app.inject({ + method: 'POST', + url: `/clients/${clientId}/shopping-carts/${shoppingCartId}/product-items`, + body: twoPairsOfShoes, + }); + assert.equal(response.statusCode, 204); + + /////////////////////////////////////////////////// + // 3. Add T-Shirt + /////////////////////////////////////////////////// + const tShirt = { + productId: '456', + quantity: 1, + }; + + response = await app.inject({ + method: 'POST', + url: `/clients/${clientId}/shopping-carts/${shoppingCartId}/product-items`, + body: tShirt, + }); + + + assert.equal(response.statusCode, 204); + + /////////////////////////////////////////////////// + // 4. Remove pair of shoes + /////////////////////////////////////////////////// + const pairOfShoes = { + productId: '123', + quantity: 1, + unitPrice: 100, + }; + + response = await app.inject({ + method: 'DELETE', + url: `/clients/${clientId}/shopping-carts/${shoppingCartId}/product-items?productId=${pairOfShoes.productId}&quantity=${pairOfShoes.quantity}&unitPrice=${pairOfShoes.unitPrice}`, + }); + assert.equal(response.statusCode, 204); + + /////////////////////////////////////////////////// + // 5. Confirm cart + /////////////////////////////////////////////////// + + response = await app.inject({ + method: 'POST', + url: `/clients/${clientId}/shopping-carts/${shoppingCartId}/confirm`, + }); + + assert.equal(response.statusCode, 204); + + + /////////////////////////////////////////////////// + // 6. Try Cancel Cart + /////////////////////////////////////////////////// + response = await app.inject({ + method: 'DELETE', + url: `/clients/${clientId}/shopping-carts/${shoppingCartId}`, + }); + + assert.equal(response.statusCode, 403); + assertMatches(response.json(), { + detail: ShoppingCartErrors.CART_IS_ALREADY_CLOSED, + }); + const result = + await eventStore.readStream(shoppingCartId); + + assert.ok(result); + assert.equal(result.events.length, Number(5)); + + assertMatches(result?.events, [ + { + type: 'ShoppingCartOpened', + data: { + shoppingCartId, + clientId, + //openedAt, + }, + }, + { + type: 'ProductItemAddedToShoppingCart', + data: { + shoppingCartId, + productItem: twoPairsOfShoes, + }, + }, + { + type: 'ProductItemAddedToShoppingCart', + data: { + shoppingCartId, + productItem: tShirt, + }, + }, + { + type: 'ProductItemRemovedFromShoppingCart', + data: { shoppingCartId, productItem: pairOfShoes }, + }, + { + type: 'ShoppingCartConfirmed', + data: { + shoppingCartId, + //confirmedAt, + }, + }, + ]); + }); +}); diff --git a/packages/emmett-fastify/src/e2e/decider/businessLogic.ts b/packages/emmett-fastify/src/e2e/decider/businessLogic.ts new file mode 100644 index 00000000..4ffa8603 --- /dev/null +++ b/packages/emmett-fastify/src/e2e/decider/businessLogic.ts @@ -0,0 +1,189 @@ +import { + EmmettError, + IllegalStateError, + type Decider, +} from '@event-driven-io/emmett'; + +import { + ShoppingCartStatus, + emptyShoppingCart, + evolve, + type PricedProductItem, + type ShoppingCart, + type ShoppingCartEvent, +} from './shoppingCart'; + +////////////////////////////////////// +/// Commands +////////////////////////////////////// + +export type OpenShoppingCart = { + type: 'OpenShoppingCart'; + data: { + shoppingCartId: string; + clientId: string; + now: Date; + }; +}; + +export type AddProductItemToShoppingCart = { + type: 'AddProductItemToShoppingCart'; + data: { + shoppingCartId: string; + productItem: PricedProductItem; + }; +}; + +export type RemoveProductItemFromShoppingCart = { + type: 'RemoveProductItemFromShoppingCart'; + data: { + shoppingCartId: string; + productItem: PricedProductItem; + }; +}; + +export type ConfirmShoppingCart = { + type: 'ConfirmShoppingCart'; + data: { + shoppingCartId: string; + now: Date; + }; +}; + +export type CancelShoppingCart = { + type: 'CancelShoppingCart'; + data: { + shoppingCartId: string; + now: Date; + }; +}; + +export type ShoppingCartCommand = + | OpenShoppingCart + | AddProductItemToShoppingCart + | RemoveProductItemFromShoppingCart + | ConfirmShoppingCart + | CancelShoppingCart; + +////////////////////////////////////// +/// Decide +////////////////////////////////////// + +export const enum ShoppingCartErrors { + CART_ALREADY_EXISTS = 'CART_ALREADY_EXISTS', + CART_IS_ALREADY_CLOSED = 'CART_IS_ALREADY_CLOSED', + PRODUCT_ITEM_NOT_FOUND = 'PRODUCT_ITEM_NOT_FOUND', + CART_IS_EMPTY = 'CART_IS_EMPTY', + UNKNOWN_EVENT_TYPE = 'UNKNOWN_EVENT_TYPE', + UNKNOWN_COMMAND_TYPE = 'UNKNOWN_COMMAND_TYPE', +} + +export const assertProductItemExists = ( + productItems: PricedProductItem[], + { productId, quantity, unitPrice }: PricedProductItem, +): void => { + const currentQuantity = + productItems.find( + (p) => p.productId === productId && p.unitPrice == unitPrice, + )?.quantity ?? 0; + + if (currentQuantity < quantity) { + throw new IllegalStateError(ShoppingCartErrors.PRODUCT_ITEM_NOT_FOUND); + } +}; + +export const decide = ( + { type, data: command }: ShoppingCartCommand, + shoppingCart: ShoppingCart, +): ShoppingCartEvent => { + switch (type) { + case 'OpenShoppingCart': { + if (shoppingCart.status !== ShoppingCartStatus.Empty) { + throw new IllegalStateError(ShoppingCartErrors.CART_ALREADY_EXISTS); + } + return { + type: 'ShoppingCartOpened', + data: { + shoppingCartId: command.shoppingCartId, + clientId: command.clientId, + openedAt: command.now, + }, + }; + } + + case 'AddProductItemToShoppingCart': { + if (shoppingCart.status !== ShoppingCartStatus.Pending) { + throw new IllegalStateError(ShoppingCartErrors.CART_IS_ALREADY_CLOSED); + } + return { + type: 'ProductItemAddedToShoppingCart', + data: { + shoppingCartId: command.shoppingCartId, + productItem: command.productItem, + }, + }; + } + + case 'RemoveProductItemFromShoppingCart': { + if (shoppingCart.status !== ShoppingCartStatus.Pending) { + throw new IllegalStateError(ShoppingCartErrors.CART_IS_ALREADY_CLOSED); + } + + assertProductItemExists(shoppingCart.productItems, command.productItem); + + return { + type: 'ProductItemRemovedFromShoppingCart', + data: { + shoppingCartId: command.shoppingCartId, + productItem: command.productItem, + }, + }; + } + + case 'ConfirmShoppingCart': { + if (shoppingCart.status !== ShoppingCartStatus.Pending) { + throw new IllegalStateError(ShoppingCartErrors.CART_IS_ALREADY_CLOSED); + } + + if (shoppingCart.productItems.length === 0) { + throw new IllegalStateError(ShoppingCartErrors.CART_IS_EMPTY); + } + + return { + type: 'ShoppingCartConfirmed', + data: { + shoppingCartId: command.shoppingCartId, + confirmedAt: command.now, + }, + }; + } + + case 'CancelShoppingCart': { + if (shoppingCart.status !== ShoppingCartStatus.Pending) { + throw new IllegalStateError(ShoppingCartErrors.CART_IS_ALREADY_CLOSED); + } + + return { + type: 'ShoppingCartCanceled', + data: { + shoppingCartId: command.shoppingCartId, + canceledAt: command.now, + }, + }; + } + default: { + const _: never = command; + throw new EmmettError(ShoppingCartErrors.UNKNOWN_COMMAND_TYPE); + } + } +}; + +export const decider: Decider< + ShoppingCart, + ShoppingCartCommand, + ShoppingCartEvent +> = { + decide, + evolve, + getInitialState: () => emptyShoppingCart, +}; diff --git a/packages/emmett-fastify/src/e2e/decider/shoppingCart.ts b/packages/emmett-fastify/src/e2e/decider/shoppingCart.ts new file mode 100644 index 00000000..4bf1be71 --- /dev/null +++ b/packages/emmett-fastify/src/e2e/decider/shoppingCart.ts @@ -0,0 +1,175 @@ +import { merge } from '@event-driven-io/emmett'; + +export interface ProductItem { + productId: string; + quantity: number; +} + +export type PricedProductItem = ProductItem & { + unitPrice: number; +}; + +export type ShoppingCartEvent = + | { + type: 'ShoppingCartOpened'; + data: { + shoppingCartId: string; + clientId: string; + openedAt: Date; + }; + } + | { + type: 'ProductItemAddedToShoppingCart'; + data: { + shoppingCartId: string; + productItem: PricedProductItem; + }; + } + | { + type: 'ProductItemRemovedFromShoppingCart'; + data: { + shoppingCartId: string; + productItem: PricedProductItem; + }; + } + | { + type: 'ShoppingCartConfirmed'; + data: { + shoppingCartId: string; + confirmedAt: Date; + }; + } + | { + type: 'ShoppingCartCanceled'; + data: { + shoppingCartId: string; + canceledAt: Date; + }; + }; + +export enum ShoppingCartStatus { + Empty = 'Empty', + Pending = 'Pending', + Confirmed = 'Confirmed', + Canceled = 'Canceled', +} + +export type Empty = { status: ShoppingCartStatus.Empty }; + +export type Pending = { + status: ShoppingCartStatus.Pending; + id: string; + clientId: string; + productItems: PricedProductItem[]; + openedAt: Date; +}; + +export type Confirmed = { + status: ShoppingCartStatus.Confirmed; + id: string; + clientId: string; + productItems: PricedProductItem[]; + confirmedAt: Date; +}; + +export type Canceled = { + status: ShoppingCartStatus.Canceled; + id: string; + clientId: string; + productItems: PricedProductItem[]; + canceledAt: Date; +}; + +export type ShoppingCart = Empty | Pending | Confirmed | Canceled; + +export const emptyShoppingCart: Empty = { status: ShoppingCartStatus.Empty }; + +export const evolve = ( + state: ShoppingCart, + { type, data: event }: ShoppingCartEvent, +): ShoppingCart => { + switch (type) { + case 'ShoppingCartOpened': + return { + id: event.shoppingCartId, + clientId: event.clientId, + openedAt: event.openedAt, + productItems: [], + status: ShoppingCartStatus.Pending, + }; + case 'ProductItemAddedToShoppingCart': { + if (state.status !== ShoppingCartStatus.Pending) return state; + + const { productItems } = state; + const { productItem } = event; + + return { + ...state, + productItems: merge( + productItems, + productItem, + (p) => + p.productId === productItem.productId && + p.unitPrice === productItem.unitPrice, + (p) => { + return { + ...p, + quantity: p.quantity + productItem.quantity, + }; + }, + () => productItem, + ), + }; + } + case 'ProductItemRemovedFromShoppingCart': { + if (state.status !== ShoppingCartStatus.Pending) return state; + + const { productItems } = state; + const { productItem } = event; + return { + ...state, + productItems: merge( + productItems, + productItem, + (p) => + p.productId === productItem.productId && + p.unitPrice === productItem.unitPrice, + (p) => { + return { + ...p, + quantity: p.quantity - productItem.quantity, + }; + }, + ), + }; + } + case 'ShoppingCartConfirmed': + if (state.status !== ShoppingCartStatus.Pending) return state; + + return { + ...state, + status: ShoppingCartStatus.Confirmed, + confirmedAt: event.confirmedAt, + }; + case 'ShoppingCartCanceled': + if (state.status !== ShoppingCartStatus.Pending) return state; + + return { + ...state, + status: ShoppingCartStatus.Canceled, + canceledAt: event.canceledAt, + }; + } +}; + +export const getShoppingCart = (events: ShoppingCartEvent[]): ShoppingCart => { + return events.reduce(evolve, emptyShoppingCart); +}; + +export const enum ShoppingCartErrors { + CART_IS_ALREADY_CLOSED = 'CART_IS_ALREADY_CLOSED', + PRODUCT_ITEM_NOT_FOUND = 'PRODUCT_ITEM_NOT_FOUND', + CART_IS_EMPTY = 'CART_IS_EMPTY', + UNKNOWN_EVENT_TYPE = 'UNKNOWN_EVENT_TYPE', + UNKNOWN_COMMAND_TYPE = 'UNKNOWN_COMMAND_TYPE', +} diff --git a/packages/emmett-fastify/src/e2e/testing.ts b/packages/emmett-fastify/src/e2e/testing.ts new file mode 100644 index 00000000..aee8279b --- /dev/null +++ b/packages/emmett-fastify/src/e2e/testing.ts @@ -0,0 +1,42 @@ +import type { Response } from 'light-my-request'; +import assert from 'node:assert/strict'; +import type { Test } from 'supertest'; + +export type TestResponse = Omit< + Omit, + 'headers' +> & { + body: Partial; + headers: Record; +}; + +export const expectNextRevisionInResponseEtag = ( + response: TestResponse, +) => { + const eTagValue = response.headers['etag']; + assert.ok(eTagValue); + assert.match(eTagValue, /W\/"\d+.*"/); +}; + +export const runTwice = (test: () => Promise) => { + const expect = async (assert: { + first: (test: Response) => Promise; + second: (test: Response) => Promise; + }): Promise => { + const { first: firstExpect, second: secondExpect } = assert; + + const result = await firstExpect(await test()); + await secondExpect(await test()); + + return result; + }; + + return { expect }; +}; + +export const statuses = (first: number, second: number) => { + return { + first: (test: Test) => test.expect(first), + second: (test: Test) => test.expect(second), + }; +}; diff --git a/packages/emmett-fastify/src/index.ts b/packages/emmett-fastify/src/index.ts new file mode 100644 index 00000000..6790b1f4 --- /dev/null +++ b/packages/emmett-fastify/src/index.ts @@ -0,0 +1,102 @@ +import Compress from '@fastify/compress'; +import Etag from '@fastify/etag'; +import Form from '@fastify/formbody'; +import closeWithGrace from 'close-with-grace'; +import Fastify, { type FastifyInstance, type FastifyRequest, type FastifyReply } from 'fastify'; + +const defaultPlugins = [ + { plugin: Etag, options: {} }, + { plugin: Compress, options: { global: false } }, + { plugin: Form, options: {} }, +]; + + +const defaultPostMiddlewares = (app: FastifyInstance) => { + app.all('*', async (request: FastifyRequest, reply: FastifyReply) => { + return reply.status(404).send(); + }); +}; + +export interface ApplicationOptions { + serverOptions?: { logger: boolean }; + registerRoutes?: (app: FastifyInstance) => void; + registerPreMiddlewares?: (app: FastifyInstance) => void; + registerPostMiddlewares?: (app: FastifyInstance) => void; + extendApp?: (app: FastifyInstance) => FastifyInstance; + activeDefaultPlugins?: Array<{ + plugin: unknown; + options: Record; + }>; +} + +export const getApplication = async (options: ApplicationOptions) => { + const { + registerPreMiddlewares, + registerRoutes, + registerPostMiddlewares = defaultPostMiddlewares, + extendApp = (app) => app, + activeDefaultPlugins = defaultPlugins, + serverOptions = { + logger: true, + }, + } = options; + + const app: FastifyInstance = extendApp( + Fastify({ + logger: serverOptions.logger, + }), + ); + + await Promise.all( + activeDefaultPlugins.map(async ({ plugin, options }) => { + await app.register(plugin, options); + }), + ); + + if (registerPreMiddlewares) { + registerPreMiddlewares(app); + } + + if (registerRoutes) { + registerRoutes(app); + } + + if (registerPostMiddlewares) { + registerPostMiddlewares(app); + } + + const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => { + if (opts.err) { + app.log.error(opts.err); + } + + await app.close(); + }); + + app.addHook('onClose', (instance, done) => { + closeListeners.uninstall(); + done(); + }); + + return app; +}; + +export type StartApiOptions = { + port?: number; +}; + +export const startAPI = async ( + app: FastifyInstance, + options: StartApiOptions = { port: 5000 }, +) => { + const { port } = options; + try { + await app.listen({ port }); + const address = app.server.address() as { address: string; port: number }; + + console.log(`Server listening on ${address?.address}:${address?.port}`); + } catch (err) { + app.log.error(err); + process.exit(1); + } +}; diff --git a/packages/emmett-fastify/tsconfig.build.json b/packages/emmett-fastify/tsconfig.build.json new file mode 100644 index 00000000..80b6a0a8 --- /dev/null +++ b/packages/emmett-fastify/tsconfig.build.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": false + } +} diff --git a/packages/emmett-fastify/tsconfig.json b/packages/emmett-fastify/tsconfig.json new file mode 100644 index 00000000..cbdf98bb --- /dev/null +++ b/packages/emmett-fastify/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.shared.json", + "include": ["./src/**/*"], + "compilerOptions": { + "composite": true, + "outDir": "./dist" /* Redirect output structure to the directory. */, + "rootDir": "./src", + "paths": { + "@event-driven-io/emmett": ["../packages/emmett"] + } + }, + "references": [ + { + "path": "../emmett/" + } + ] +} diff --git a/packages/emmett-fastify/tsup.config.ts b/packages/emmett-fastify/tsup.config.ts new file mode 100644 index 00000000..a21eaef5 --- /dev/null +++ b/packages/emmett-fastify/tsup.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'tsup'; + +const env = process.env.NODE_ENV; + +export default defineConfig({ + splitting: true, + clean: true, // clean up the dist folder + dts: true, // generate dts files + format: ['cjs', 'esm'], // generate cjs and esm files + minify: env === 'production', + bundle: env === 'production', + skipNodeModulesBundle: true, + entryPoints: ['src/index.ts'], + watch: env === 'development', + target: 'esnext', + outDir: 'dist', //env === 'production' ? 'dist' : 'lib', + entry: ['src/**/*.ts'], //include all files under src + sourcemap: true, + tsconfig: 'tsconfig.build.json', // workaround for https://github.com/egoist/tsup/issues/571#issuecomment-1760052931 +}); diff --git a/tsconfig.json b/tsconfig.json index e2f3515d..5c079d81 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,8 @@ "@event-driven-io/emmett-expressjs": ["./packages/emmett-expressjs/src"], "@event-driven-io/emmett-eventstoredb": [ "./packages/emmett-eventstoredb/src" - ] + ], + "@event-driven-io/emmett-fastify": ["./packages/emmett-fastify/src"], } }, "references": [ @@ -25,6 +26,9 @@ }, { "path": "./packages/emmett-testcontainers/" + }, + { + "path": "./packages/emmett-fastify/" } ] } From dd6bdbf5820f8ebdd5cc0bc2c4e47c0dea7896d5 Mon Sep 17 00:00:00 2001 From: Mateusz Kubaszek Date: Mon, 4 Mar 2024 11:38:13 +0100 Subject: [PATCH 2/6] feat: general server options --- packages/emmett-fastify/src/index.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/emmett-fastify/src/index.ts b/packages/emmett-fastify/src/index.ts index 6790b1f4..3ec47f07 100644 --- a/packages/emmett-fastify/src/index.ts +++ b/packages/emmett-fastify/src/index.ts @@ -2,7 +2,11 @@ import Compress from '@fastify/compress'; import Etag from '@fastify/etag'; import Form from '@fastify/formbody'; import closeWithGrace from 'close-with-grace'; -import Fastify, { type FastifyInstance, type FastifyRequest, type FastifyReply } from 'fastify'; +import Fastify, { + type FastifyInstance, + type FastifyReply, + type FastifyRequest, +} from 'fastify'; const defaultPlugins = [ { plugin: Etag, options: {} }, @@ -10,7 +14,6 @@ const defaultPlugins = [ { plugin: Form, options: {} }, ]; - const defaultPostMiddlewares = (app: FastifyInstance) => { app.all('*', async (request: FastifyRequest, reply: FastifyReply) => { return reply.status(404).send(); @@ -41,11 +44,7 @@ export const getApplication = async (options: ApplicationOptions) => { }, } = options; - const app: FastifyInstance = extendApp( - Fastify({ - logger: serverOptions.logger, - }), - ); + const app: FastifyInstance = extendApp(Fastify(serverOptions)); await Promise.all( activeDefaultPlugins.map(async ({ plugin, options }) => { From 4dea3130b6de5e720147137bfae27398fbbeeb52 Mon Sep 17 00:00:00 2001 From: futpib Date: Sat, 2 Mar 2024 15:17:53 +0000 Subject: [PATCH 3/6] Fix martendb.io link in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb6b3a06..f2379931 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Nowadays, storage is cheap, but the information is priceless. Event Sourcing, contrary to the standard approach, keeps all the facts that happened in our system. To do that, it needs an event store: a database designed for its needs. -This project aims to experiment with an opinionated Event Sourcing framework based on my experience working on [Marten](martendb.io/) and [EventStoreDB](https://developers.eventstore.com/). +This project aims to experiment with an opinionated Event Sourcing framework based on my experience working on [Marten](https://martendb.io/) and [EventStoreDB](https://developers.eventstore.com/). **Take your event-driven applications back to the future!** From 900ec5875a1a85a2447ae9853f4fdde7e467f9f9 Mon Sep 17 00:00:00 2001 From: Thiago Valentim <51245643+thiagomini@users.noreply.github.com> Date: Tue, 5 Mar 2024 09:39:23 -0300 Subject: [PATCH 4/6] feat(docs,emmet-expressjs): add e2e api specification (#29) * feat(docs,emmet-expressjs): add e2e api specification closes #26 * Configured E2E tests for using ESDB - Updated http responses to allow returning problem without options (e.g. NotFound) - Fixed path to ESDB package in tsconfig * refactor(docs,emmett-expressjs): apply review changes - Move ApiE2ESpecification to its own file - Move common test setup functions to utils file - Fixed typos "succeded" -> "succeeded" - Changed api to return not found when shopping cart does not exist * fix(emmett-expressjs): fix import statement --------- Co-authored-by: Oskar Dudycz --- .idea/workspace.xml | 10 +-- .../gettingStarted/webApi/apiBDD.e2e.spec.ts | 89 +++++++++++++++++++ .../gettingStarted/webApi/shoppingCart.ts | 1 + .../gettingStarted/webApi/simpleApi.ts | 47 +++++++++- .../applicationLogicWithOC.int.spec.ts | 1 - packages/emmett-expressjs/src/handler.ts | 11 +-- .../src/testing/apiE2ESpecification.ts | 67 ++++++++++++++ .../src/testing/apiSpecification.ts | 82 ++--------------- .../emmett-expressjs/src/testing/index.ts | 1 + .../emmett-expressjs/src/testing/utils.ts | 74 +++++++++++++++ .../src/eventStore/index.ts | 2 + tsconfig.json | 6 +- 12 files changed, 298 insertions(+), 93 deletions(-) create mode 100644 docs/snippets/gettingStarted/webApi/apiBDD.e2e.spec.ts create mode 100644 packages/emmett-expressjs/src/testing/apiE2ESpecification.ts create mode 100644 packages/emmett-expressjs/src/testing/utils.ts diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 503bf419..38feccd5 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,13 +5,9 @@ - - - - - + - + diff --git a/docs/snippets/gettingStarted/webApi/apiBDD.e2e.spec.ts b/docs/snippets/gettingStarted/webApi/apiBDD.e2e.spec.ts new file mode 100644 index 00000000..995d457d --- /dev/null +++ b/docs/snippets/gettingStarted/webApi/apiBDD.e2e.spec.ts @@ -0,0 +1,89 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ +import { type EventStore } from '@event-driven-io/emmett'; +import { getEventStoreDBEventStore } from '@event-driven-io/emmett-esdb'; +import { + ApiE2ESpecification, + expectResponse, + getApplication, +} from '@event-driven-io/emmett-expressjs'; +import { + EventStoreDBContainer, + StartedEventStoreDBContainer, +} from '@event-driven-io/emmett-testcontainers'; +import { randomUUID } from 'node:crypto'; +import { after, before, beforeEach, describe, it } from 'node:test'; +import type { PricedProductItem } from '../events'; +import { ShoppingCartStatus } from './shoppingCart'; +import { shoppingCartApi } from './simpleApi'; + +const getUnitPrice = () => { + return Promise.resolve(100); +}; + +describe('ShoppingCart E2E', () => { + let clientId: string; + let shoppingCartId: string; + let esdbContainer: StartedEventStoreDBContainer; + let given: ApiE2ESpecification; + + before(async () => { + esdbContainer = await new EventStoreDBContainer().start(); + + given = ApiE2ESpecification.for( + (): EventStore => getEventStoreDBEventStore(esdbContainer.getClient()), + (eventStore: EventStore) => + getApplication({ + apis: [shoppingCartApi(eventStore, getUnitPrice, () => now)], + }), + ); + }); + + beforeEach(() => { + clientId = randomUUID(); + shoppingCartId = `shopping_cart:${clientId}:current`; + }); + + after(() => { + return esdbContainer.stop(); + }); + + describe('When empty', () => { + it('should add product item', () => { + return given((request) => + request + .post(`/clients/${clientId}/shopping-carts/current/product-items`) + .send(productItem), + ) + .when((request) => + request.get(`/clients/${clientId}/shopping-carts/current`).send(), + ) + .then([ + expectResponse(200, { + body: { + clientId, + id: shoppingCartId, + productItems: [ + { + quantity: productItem.quantity, + productId: productItem.productId, + }, + ], + status: ShoppingCartStatus.Opened, + }, + }), + ]); + }); + }); + + const now = new Date(); + + const getRandomProduct = (): PricedProductItem => { + return { + productId: randomUUID(), + unitPrice: 100, + quantity: Math.random() * 10, + }; + }; + + const productItem = getRandomProduct(); +}); diff --git a/docs/snippets/gettingStarted/webApi/shoppingCart.ts b/docs/snippets/gettingStarted/webApi/shoppingCart.ts index 4bf1be71..f3deb74c 100644 --- a/docs/snippets/gettingStarted/webApi/shoppingCart.ts +++ b/docs/snippets/gettingStarted/webApi/shoppingCart.ts @@ -52,6 +52,7 @@ export enum ShoppingCartStatus { Pending = 'Pending', Confirmed = 'Confirmed', Canceled = 'Canceled', + Opened = 'Opened', } export type Empty = { status: ShoppingCartStatus.Empty }; diff --git a/docs/snippets/gettingStarted/webApi/simpleApi.ts b/docs/snippets/gettingStarted/webApi/simpleApi.ts index ad09a86f..296738d3 100644 --- a/docs/snippets/gettingStarted/webApi/simpleApi.ts +++ b/docs/snippets/gettingStarted/webApi/simpleApi.ts @@ -6,6 +6,8 @@ import { } from '@event-driven-io/emmett'; import { NoContent, + NotFound, + OK, on, type WebApiSetup, } from '@event-driven-io/emmett-expressjs'; @@ -22,7 +24,8 @@ import type { ConfirmShoppingCart, RemoveProductItemFromShoppingCart, } from '../commands'; -import { evolve, getInitialState } from '../shoppingCart'; +import type { ProductItem, ShoppingCartEvent } from '../events'; +import { evolve, getInitialState, type ShoppingCart } from '../shoppingCart'; export const handle = CommandHandler(evolve, getInitialState); @@ -140,6 +143,42 @@ export const shoppingCartApi = }), ); // #endregion complete-api + + // Get Shopping Cart + router.get( + '/clients/:clientId/shopping-carts/current', + on(async (request: GetShoppingCartRequest) => { + const shoppingCartId = getShoppingCartId( + assertNotEmptyString(request.params.clientId), + ); + + const result = await eventStore.aggregateStream< + ShoppingCart, + ShoppingCartEvent + >(shoppingCartId, { + evolve, + getInitialState, + }); + + if (result === null) return NotFound(); + + const productItems: ProductItem[] = Array.from( + result.state.productItems, + ).map(([productId, quantity]) => ({ + productId, + quantity, + })); + + return OK({ + body: { + clientId: assertNotEmptyString(request.params.clientId), + id: shoppingCartId, + productItems, + status: result?.state.status, + }, + }); + }), + ); }; // Add Product Item @@ -148,3 +187,9 @@ type AddProductItemRequest = Request< unknown, Partial<{ productId: number; quantity: number }> >; + +type GetShoppingCartRequest = Request< + Partial<{ clientId: string }>, + unknown, + unknown +>; diff --git a/packages/emmett-expressjs/src/e2e/decider/applicationLogicWithOC.int.spec.ts b/packages/emmett-expressjs/src/e2e/decider/applicationLogicWithOC.int.spec.ts index 7dea53cd..95b3eda7 100644 --- a/packages/emmett-expressjs/src/e2e/decider/applicationLogicWithOC.int.spec.ts +++ b/packages/emmett-expressjs/src/e2e/decider/applicationLogicWithOC.int.spec.ts @@ -44,7 +44,6 @@ describe('Application logic with optimistic concurrency', () => { if (!current.id) { assert.fail(); - return; } assert.ok(current.id); diff --git a/packages/emmett-expressjs/src/handler.ts b/packages/emmett-expressjs/src/handler.ts index 7c0b58f7..80568ff7 100644 --- a/packages/emmett-expressjs/src/handler.ts +++ b/packages/emmett-expressjs/src/handler.ts @@ -63,16 +63,17 @@ export const HttpResponse = // ERRORS ///////////////////// -export const BadRequest = (options: HttpProblemResponseOptions): HttpResponse => - HttpProblem(400, options); +export const BadRequest = ( + options?: HttpProblemResponseOptions, +): HttpResponse => HttpProblem(400, options); -export const Forbidden = (options: HttpProblemResponseOptions): HttpResponse => +export const Forbidden = (options?: HttpProblemResponseOptions): HttpResponse => HttpProblem(403, options); -export const NotFound = (options: HttpProblemResponseOptions): HttpResponse => +export const NotFound = (options?: HttpProblemResponseOptions): HttpResponse => HttpProblem(404, options); -export const Conflict = (options: HttpProblemResponseOptions): HttpResponse => +export const Conflict = (options?: HttpProblemResponseOptions): HttpResponse => HttpProblem(409, options); export const PreconditionFailed = ( diff --git a/packages/emmett-expressjs/src/testing/apiE2ESpecification.ts b/packages/emmett-expressjs/src/testing/apiE2ESpecification.ts new file mode 100644 index 00000000..497ae584 --- /dev/null +++ b/packages/emmett-expressjs/src/testing/apiE2ESpecification.ts @@ -0,0 +1,67 @@ +import type { Test } from 'supertest'; +import supertest, { type Response } from 'supertest'; +import type TestAgent from 'supertest/lib/agent'; + +import type { + DefaultStreamVersionType, + EventStore, +} from '@event-driven-io/emmett'; +import assert from 'assert'; +import type { Application } from 'express'; +import { WrapEventStore } from './utils'; + +export type E2EResponseAssert = (response: Response) => boolean | void; + +export type ApiE2ESpecificationAssert = [E2EResponseAssert]; + +export type ApiE2ESpecification = ( + ...givenRequests: ((request: TestAgent) => Test)[] +) => { + when: (setupRequest: (request: TestAgent) => Test) => { + then: (verify: ApiE2ESpecificationAssert) => Promise; + }; +}; + +export const ApiE2ESpecification = { + for: ( + getEventStore: () => EventStore, + getApplication: (eventStore: EventStore) => Application, + ): ApiE2ESpecification => { + { + return ( + ...givenRequests: ((request: TestAgent) => Test)[] + ) => { + const eventStore = WrapEventStore(getEventStore()); + const application = getApplication(eventStore); + + return { + when: ( + setupRequest: (request: TestAgent) => Test, + ) => { + const handle = async () => { + for (const requestFn of givenRequests) { + await requestFn(supertest(application)); + } + + return setupRequest(supertest(application)); + }; + + return { + then: async ( + verify: ApiE2ESpecificationAssert, + ): Promise => { + const response = await handle(); + + verify.forEach((assertion) => { + const succeeded = assertion(response); + + if (succeeded === false) assert.fail(); + }); + }, + }; + }, + }; + }; + } + }, +}; diff --git a/packages/emmett-expressjs/src/testing/apiSpecification.ts b/packages/emmett-expressjs/src/testing/apiSpecification.ts index 5caf7961..72502515 100644 --- a/packages/emmett-expressjs/src/testing/apiSpecification.ts +++ b/packages/emmett-expressjs/src/testing/apiSpecification.ts @@ -1,14 +1,8 @@ import { assertMatches, - type AggregateStreamOptions, - type AggregateStreamResult, - type AppendToStreamOptions, - type AppendToStreamResult, type DefaultStreamVersionType, type Event, type EventStore, - type ReadStreamOptions, - type ReadStreamResult, } from '@event-driven-io/emmett'; import { type Application } from 'express'; import type { ProblemDocument } from 'http-problem-details'; @@ -16,16 +10,12 @@ import assert from 'node:assert/strict'; import type { Response, Test } from 'supertest'; import supertest from 'supertest'; import type TestAgent from 'supertest/lib/agent'; +import { WrapEventStore, type TestEventStream } from './utils'; //////////////////////////////// /////////// Setup //////////////////////////////// -export type TestEventStream = [ - string, - EventType[], -]; - export const existingStream = ( streamId: string, events: EventType[], @@ -59,9 +49,9 @@ export const expectNewEvents = ( }; export const expectResponse = - ( + ( statusCode: number, - options?: { body?: unknown; headers?: { [index: string]: string } }, + options?: { body?: Body; headers?: { [index: string]: string } }, ) => (response: Response): void => { const { body, headers } = options ?? {}; @@ -123,16 +113,16 @@ export const ApiSpecification = { const response = await handle(); if (typeof verify === 'function') { - const succeded = verify(response); + const succeeded = verify(response); - if (succeded === false) assert.fail(); + if (succeeded === false) assert.fail(); } else if (Array.isArray(verify)) { const [first, ...rest] = verify; if (typeof first === 'function') { - const succeded = first(response); + const succeeded = first(response); - if (succeded === false) assert.fail(); + if (succeeded === false) assert.fail(); } const events = typeof first === 'function' ? rest : verify; @@ -150,61 +140,3 @@ export const ApiSpecification = { } }, }; - -const WrapEventStore = ( - eventStore: EventStore, -): EventStore & { - appendedEvents: Map; - setup( - streamName: string, - events: EventType[], - ): Promise>; -} => { - const appendedEvents = new Map(); - - return { - async aggregateStream( - streamName: string, - options: AggregateStreamOptions, - ): Promise | null> { - return eventStore.aggregateStream(streamName, options); - }, - - readStream( - streamName: string, - options?: ReadStreamOptions, - ): Promise> { - return eventStore.readStream(streamName, options); - }, - - appendToStream: async ( - streamName: string, - events: EventType[], - options?: AppendToStreamOptions, - ): Promise> => { - const result = await eventStore.appendToStream( - streamName, - events, - options, - ); - - const currentStream = appendedEvents.get(streamName) ?? [streamName, []]; - - appendedEvents.set(streamName, [ - streamName, - [...currentStream[1], ...events], - ]); - - return result; - }, - - appendedEvents, - - setup: async ( - streamName: string, - events: EventType[], - ): Promise> => { - return eventStore.appendToStream(streamName, events); - }, - }; -}; diff --git a/packages/emmett-expressjs/src/testing/index.ts b/packages/emmett-expressjs/src/testing/index.ts index 03ec44b8..435fde87 100644 --- a/packages/emmett-expressjs/src/testing/index.ts +++ b/packages/emmett-expressjs/src/testing/index.ts @@ -1 +1,2 @@ +export * from './apiE2ESpecification'; export * from './apiSpecification'; diff --git a/packages/emmett-expressjs/src/testing/utils.ts b/packages/emmett-expressjs/src/testing/utils.ts new file mode 100644 index 00000000..aec63ed7 --- /dev/null +++ b/packages/emmett-expressjs/src/testing/utils.ts @@ -0,0 +1,74 @@ +import type { + AggregateStreamOptions, + AggregateStreamResult, + AppendToStreamOptions, + AppendToStreamResult, + DefaultStreamVersionType, + Event, + EventStore, + ReadStreamOptions, + ReadStreamResult, +} from '@event-driven-io/emmett'; + +export type TestEventStream = [ + string, + EventType[], +]; + +export const WrapEventStore = ( + eventStore: EventStore, +): EventStore & { + appendedEvents: Map; + setup( + streamName: string, + events: EventType[], + ): Promise>; +} => { + const appendedEvents = new Map(); + + return { + async aggregateStream( + streamName: string, + options: AggregateStreamOptions, + ): Promise | null> { + return eventStore.aggregateStream(streamName, options); + }, + + readStream( + streamName: string, + options?: ReadStreamOptions, + ): Promise> { + return eventStore.readStream(streamName, options); + }, + + appendToStream: async ( + streamName: string, + events: EventType[], + options?: AppendToStreamOptions, + ): Promise> => { + const result = await eventStore.appendToStream( + streamName, + events, + options, + ); + + const currentStream = appendedEvents.get(streamName) ?? [streamName, []]; + + appendedEvents.set(streamName, [ + streamName, + [...currentStream[1], ...events], + ]); + + return result; + }, + + appendedEvents, + + setup: async ( + streamName: string, + events: EventType[], + ): Promise> => { + return eventStore.appendToStream(streamName, events); + }, + }; +}; diff --git a/packages/emmett-testcontainers/src/eventStore/index.ts b/packages/emmett-testcontainers/src/eventStore/index.ts index f4c3734b..cd3466dc 100644 --- a/packages/emmett-testcontainers/src/eventStore/index.ts +++ b/packages/emmett-testcontainers/src/eventStore/index.ts @@ -4,6 +4,8 @@ import { StartedEventStoreDBContainer, } from './eventStoreDBContainer'; +export * from './eventStoreDBContainer'; + let esdbContainer: StartedEventStoreDBContainer; export const getEventStoreDBTestClient = async ( diff --git a/tsconfig.json b/tsconfig.json index 5c079d81..af26990d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,10 +8,8 @@ "paths": { "@event-driven-io/emmett": ["./packages/emmett/src"], "@event-driven-io/emmett-expressjs": ["./packages/emmett-expressjs/src"], - "@event-driven-io/emmett-eventstoredb": [ - "./packages/emmett-eventstoredb/src" - ], - "@event-driven-io/emmett-fastify": ["./packages/emmett-fastify/src"], + "@event-driven-io/emmett-esdb": ["./packages/emmett-esdb/src"], + "@event-driven-io/emmett-fastify": ["./packages/emmett-fastify/src"] } }, "references": [ From e84d4d7e3185852aeb4bbb9d3af929e5190f768c Mon Sep 17 00:00:00 2001 From: Mateusz Kubaszek Date: Tue, 5 Mar 2024 23:42:07 +0100 Subject: [PATCH 5/6] fix: remove default middlewares to extend developers expirience --- .../emmett-fastify/src/e2e/decider/api.ts | 2 -- packages/emmett-fastify/src/index.ts | 24 +------------------ 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/packages/emmett-fastify/src/e2e/decider/api.ts b/packages/emmett-fastify/src/e2e/decider/api.ts index f30a4e22..bbd039f4 100644 --- a/packages/emmett-fastify/src/e2e/decider/api.ts +++ b/packages/emmett-fastify/src/e2e/decider/api.ts @@ -1,10 +1,8 @@ import { assertNotEmptyString, - STREAM_DOES_NOT_EXIST, DeciderCommandHandler, type EventStore, assertPositiveNumber, - assertUnsignedBigInt, } from '@event-driven-io/emmett'; import { type FastifyInstance, diff --git a/packages/emmett-fastify/src/index.ts b/packages/emmett-fastify/src/index.ts index 3ec47f07..2071dc7d 100644 --- a/packages/emmett-fastify/src/index.ts +++ b/packages/emmett-fastify/src/index.ts @@ -4,8 +4,6 @@ import Form from '@fastify/formbody'; import closeWithGrace from 'close-with-grace'; import Fastify, { type FastifyInstance, - type FastifyReply, - type FastifyRequest, } from 'fastify'; const defaultPlugins = [ @@ -14,18 +12,9 @@ const defaultPlugins = [ { plugin: Form, options: {} }, ]; -const defaultPostMiddlewares = (app: FastifyInstance) => { - app.all('*', async (request: FastifyRequest, reply: FastifyReply) => { - return reply.status(404).send(); - }); -}; - export interface ApplicationOptions { serverOptions?: { logger: boolean }; registerRoutes?: (app: FastifyInstance) => void; - registerPreMiddlewares?: (app: FastifyInstance) => void; - registerPostMiddlewares?: (app: FastifyInstance) => void; - extendApp?: (app: FastifyInstance) => FastifyInstance; activeDefaultPlugins?: Array<{ plugin: unknown; options: Record; @@ -34,17 +23,14 @@ export interface ApplicationOptions { export const getApplication = async (options: ApplicationOptions) => { const { - registerPreMiddlewares, registerRoutes, - registerPostMiddlewares = defaultPostMiddlewares, - extendApp = (app) => app, activeDefaultPlugins = defaultPlugins, serverOptions = { logger: true, }, } = options; - const app: FastifyInstance = extendApp(Fastify(serverOptions)); + const app: FastifyInstance = Fastify(serverOptions); await Promise.all( activeDefaultPlugins.map(async ({ plugin, options }) => { @@ -52,18 +38,10 @@ export const getApplication = async (options: ApplicationOptions) => { }), ); - if (registerPreMiddlewares) { - registerPreMiddlewares(app); - } - if (registerRoutes) { registerRoutes(app); } - if (registerPostMiddlewares) { - registerPostMiddlewares(app); - } - const closeListeners = closeWithGrace({ delay: 500 }, async (opts) => { if (opts.err) { app.log.error(opts.err); From 43a2aae03ad79b851e3b7a5ae275e48a4a383778 Mon Sep 17 00:00:00 2001 From: Oskar Dudycz Date: Wed, 6 Mar 2024 10:06:34 +0100 Subject: [PATCH 6/6] Fixed fastify API tests and typing around plugins Fixed also linter errors --- package-lock.json | 1137 ++++++++++++----- .../emmett-fastify/src/e2e/decider/api.ts | 169 ++- .../applicationLogicWithOC.int.spec.ts | 19 +- packages/emmett-fastify/src/index.ts | 28 +- 4 files changed, 922 insertions(+), 431 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf846821..2d8dc38e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -225,9 +225,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", + "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -301,6 +301,70 @@ } } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/darwin-arm64": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", @@ -317,6 +381,294 @@ "node": ">=12" } }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -686,19 +1038,29 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -709,9 +1071,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" @@ -854,10 +1216,36 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "dev": true }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz", + "integrity": "sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.1.tgz", + "integrity": "sha512-wlzcWiH2Ir7rdMELxFE5vuM7D6TsOcJ2Yw0c3vaBR3VOsJFVTx9xvwnAvhgU5Ii8Gd6+I11qNHwndDscIm0HXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", - "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.1.tgz", + "integrity": "sha512-YRXa1+aZIFN5BaImK+84B3uNK8C6+ynKLPgvn29X9s0LTVCByp54TB7tdSMHDR7GTV39bz1lOmlLDuedgTwwHg==", "cpu": [ "arm64" ], @@ -867,19 +1255,149 @@ "darwin" ] }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.1.tgz", + "integrity": "sha512-opjWJ4MevxeA8FhlngQWPBOvVWYNPFkq6/25rGgG+KOy0r8clYwL1CFd+PGwRqqMFVQ4/Qd3sQu5t7ucP7C/Uw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.1.tgz", + "integrity": "sha512-uBkwaI+gBUlIe+EfbNnY5xNyXuhZbDSx2nzzW8tRMjUmpScd6lCQYKY2V9BATHtv5Ef2OBq6SChEP8h+/cxifQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.1.tgz", + "integrity": "sha512-0bK9aG1kIg0Su7OcFTlexkVeNZ5IzEsnz1ept87a0TUgZ6HplSgkJAnFpEVRW7GRcikT4GlPV0pbtVedOaXHQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.1.tgz", + "integrity": "sha512-qB6AFRXuP8bdkBI4D7UPUbE7OQf7u5OL+R94JE42Z2Qjmyj74FtDdLGeriRyBDhm4rQSvqAGCGC01b8Fu2LthQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.1.tgz", + "integrity": "sha512-sHig3LaGlpNgDj5o8uPEoGs98RII8HpNIqFtAI8/pYABO8i0nb1QzT0JDoXF/pxzqO+FkxvwkHZo9k0NJYDedg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.1.tgz", + "integrity": "sha512-nD3YcUv6jBJbBNFvSbp0IV66+ba/1teuBcu+fBBPZ33sidxitc6ErhON3JNavaH8HlswhWMC3s5rgZpM4MtPqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.1.tgz", + "integrity": "sha512-7/XVZqgBby2qp/cO0TQ8uJK+9xnSdJ9ct6gSDdEr4MfABrjTyrW6Bau7HQ73a2a5tPB7hno49A0y1jhWGDN9OQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.1.tgz", + "integrity": "sha512-CYc64bnICG42UPL7TrhIwsJW4QcKkIt9gGlj21gq3VV0LL6XNb1yAdHVp1pIi9gkts9gGcT3OfUYHjGP7ETAiw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.1.tgz", + "integrity": "sha512-LN+vnlZ9g0qlHGlS920GR4zFCqAwbv2lULrR29yGaWP9u7wF5L7GqWu9Ah6/kFZPXPUkpdZwd//TNR+9XC9hvA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.1.tgz", + "integrity": "sha512-n+vkrSyphvmU0qkQ6QBNXCGr2mKjhP08mPRM/Xp5Ck2FV4NrHU+y6axzDeixUrCBHVUS51TZhjqrKBBsHLKb2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@shikijs/core": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.1.5.tgz", - "integrity": "sha512-cKc5vGQ4p/4sjx48BHIO7CvLaN32vqpz5Wh7v2n+U1EezGdfX4Wms7khBctKz3iCg9yYq4sfGUc2t+JWj6EUsw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.1.7.tgz", + "integrity": "sha512-gTYLUIuD1UbZp/11qozD3fWpUTuMqPSf3svDMMrL0UmlGU7D9dPw/V1FonwAorCUJBltaaESxq90jrSjQyGixg==", "dev": true }, "node_modules/@shikijs/transformers": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.1.5.tgz", - "integrity": "sha512-ot6KWPmLuSN9nA9FAhttOXZIjKIy7cnwpNtI9aWmYN72RUaDz8eojRfMGUXsXXUxW/buvcvdZQAQldk7/pFpdw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.1.7.tgz", + "integrity": "sha512-lXz011ao4+rvweps/9h3CchBfzb1U5OtP5D51Tqc9lQYdLblWMIxQxH6Ybe1GeGINcEVM4goMyPrI0JvlIp4UQ==", "dev": true, "dependencies": { - "shiki": "1.1.5" + "shiki": "1.1.7" } }, "node_modules/@tsconfig/node10": { @@ -1055,9 +1573,9 @@ } }, "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==", + "version": "6.9.12", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.12.tgz", + "integrity": "sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg==", "dev": true }, "node_modules/@types/range-parser": { @@ -1067,9 +1585,9 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/send": { @@ -1118,9 +1636,9 @@ } }, "node_modules/@types/superagent": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.3.tgz", - "integrity": "sha512-R/CfN6w2XsixLb1Ii8INfn+BT9sGPvw74OavfkW4SwY+jeUcAwLZv2+bXLJkndnimxjEBm0RPHgcjW9pLCa8cw==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.4.tgz", + "integrity": "sha512-uzSBYwrpal8y2X2Pul5ZSWpzRiDha2FLcquaN95qUPnOjYgm/zQ5LIdqeJpQJTRWNTN+Rhm0aC8H06Ds2rqCYw==", "dev": true, "dependencies": { "@types/cookiejar": "^2.1.5", @@ -1360,71 +1878,71 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz", - "integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.21.tgz", + "integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==", "dev": true, "dependencies": { "@babel/parser": "^7.23.9", - "@vue/shared": "3.4.19", + "@vue/shared": "3.4.21", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz", - "integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz", + "integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==", "dev": true, "dependencies": { - "@vue/compiler-core": "3.4.19", - "@vue/shared": "3.4.19" + "@vue/compiler-core": "3.4.21", + "@vue/shared": "3.4.21" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz", - "integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz", + "integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==", "dev": true, "dependencies": { "@babel/parser": "^7.23.9", - "@vue/compiler-core": "3.4.19", - "@vue/compiler-dom": "3.4.19", - "@vue/compiler-ssr": "3.4.19", - "@vue/shared": "3.4.19", + "@vue/compiler-core": "3.4.21", + "@vue/compiler-dom": "3.4.21", + "@vue/compiler-ssr": "3.4.21", + "@vue/shared": "3.4.21", "estree-walker": "^2.0.2", - "magic-string": "^0.30.6", - "postcss": "^8.4.33", + "magic-string": "^0.30.7", + "postcss": "^8.4.35", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz", - "integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz", + "integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==", "dev": true, "dependencies": { - "@vue/compiler-dom": "3.4.19", - "@vue/shared": "3.4.19" + "@vue/compiler-dom": "3.4.21", + "@vue/shared": "3.4.21" } }, "node_modules/@vue/devtools-api": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.0.15.tgz", - "integrity": "sha512-kgEYWosDyWpS1vFSuJNNWUnHkP+VkL3Y+9mw+rf7ex41SwbYL/WdC3KXqAtjiSrEs7r/FrHmUTh0BkINJPFkbA==", + "version": "7.0.16", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.0.16.tgz", + "integrity": "sha512-fZG2CG8624qphMf4aj59zNHckMx1G3lxODUuyM9USKuLznXCh66TP+tEbPOCcml16hA0GizJ4D8w6F34hrfbcw==", "dev": true, "dependencies": { - "@vue/devtools-kit": "^7.0.15" + "@vue/devtools-kit": "^7.0.16" } }, "node_modules/@vue/devtools-kit": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.0.15.tgz", - "integrity": "sha512-dT7OeCe1LUCIhHIb/yRR6Hn+XHh73r1o78onqCrxEKHdoZwBItiIeVnmJZPEUDFstIxfs+tJL231mySk3laTow==", + "version": "7.0.16", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.0.16.tgz", + "integrity": "sha512-IA8SSGiZbNgOi4wLT3mRvd71Q9KE0KvMfGk6haa2GZ6bL2K/xMA8Fvvj3o1maspfUXrGcCXutaqbLqbGx/espQ==", "dev": true, "dependencies": { - "@vue/devtools-shared": "^7.0.15", + "@vue/devtools-shared": "^7.0.16", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", @@ -1435,73 +1953,73 @@ } }, "node_modules/@vue/devtools-shared": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.0.15.tgz", - "integrity": "sha512-fpfvMVvS7aDgO7x2JPFiTQ1MHcCc63/bE7yTgs278gMBybuO9b3hdiZ/k0Pw1rN+RefaU9yQiFA+5CCFc1D+6w==", + "version": "7.0.16", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.0.16.tgz", + "integrity": "sha512-Lew4FrGjDjmanaUWSueNE1Rre83k7jQpttc17MaoVw0eARWU5DgZ1F/g9GNUMZXVjbP9rwE+LL3gd9XfXCfkvA==", "dev": true, "dependencies": { "rfdc": "^1.3.1" } }, "node_modules/@vue/reactivity": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz", - "integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.21.tgz", + "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==", "dev": true, "dependencies": { - "@vue/shared": "3.4.19" + "@vue/shared": "3.4.21" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz", - "integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.21.tgz", + "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==", "dev": true, "dependencies": { - "@vue/reactivity": "3.4.19", - "@vue/shared": "3.4.19" + "@vue/reactivity": "3.4.21", + "@vue/shared": "3.4.21" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz", - "integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz", + "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==", "dev": true, "dependencies": { - "@vue/runtime-core": "3.4.19", - "@vue/shared": "3.4.19", + "@vue/runtime-core": "3.4.21", + "@vue/shared": "3.4.21", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz", - "integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.21.tgz", + "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==", "dev": true, "dependencies": { - "@vue/compiler-ssr": "3.4.19", - "@vue/shared": "3.4.19" + "@vue/compiler-ssr": "3.4.21", + "@vue/shared": "3.4.21" }, "peerDependencies": { - "vue": "3.4.19" + "vue": "3.4.21" } }, "node_modules/@vue/shared": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", - "integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz", + "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==", "dev": true }, "node_modules/@vueuse/core": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.7.2.tgz", - "integrity": "sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz", + "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==", "dev": true, "dependencies": { "@types/web-bluetooth": "^0.0.20", - "@vueuse/metadata": "10.7.2", - "@vueuse/shared": "10.7.2", - "vue-demi": ">=0.14.6" + "@vueuse/metadata": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -1534,14 +2052,14 @@ } }, "node_modules/@vueuse/integrations": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.7.2.tgz", - "integrity": "sha512-+u3RLPFedjASs5EKPc69Ge49WNgqeMfSxFn+qrQTzblPXZg6+EFzhjarS5edj2qAf6xQ93f95TUxRwKStXj/sQ==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.9.0.tgz", + "integrity": "sha512-acK+A01AYdWSvL4BZmCoJAcyHJ6EqhmkQEXbQLwev1MY7NBnS+hcEMx/BzVoR9zKI+UqEPMD9u6PsyAuiTRT4Q==", "dev": true, "dependencies": { - "@vueuse/core": "10.7.2", - "@vueuse/shared": "10.7.2", - "vue-demi": ">=0.14.6" + "@vueuse/core": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -1626,21 +2144,21 @@ } }, "node_modules/@vueuse/metadata": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.7.2.tgz", - "integrity": "sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz", + "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==", "dev": true, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "10.7.2", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.7.2.tgz", - "integrity": "sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz", + "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==", "dev": true, "dependencies": { - "vue-demi": ">=0.14.6" + "vue-demi": ">=0.14.7" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -1912,42 +2430,28 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/archiver-utils/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/archiver-utils/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/archiver-utils/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/archiver/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { - "safe-buffer": "~5.1.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/archy": { @@ -2119,6 +2623,19 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -2476,6 +2993,19 @@ "node": ">= 10" } }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2561,6 +3091,19 @@ "node": ">= 10" } }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2707,6 +3250,19 @@ "node": ">= 8.0" } }, + "node_modules/docker-modem/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/dockerode": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.5.tgz", @@ -2754,33 +3310,6 @@ "stream-shift": "^1.0.0" } }, - "node_modules/duplexify/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexify/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/duplexify/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3521,9 +4050,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/focus-trap": { @@ -3605,33 +4134,6 @@ "readable-stream": "^2.0.0" } }, - "node_modules/from2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/from2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/from2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -3844,9 +4346,9 @@ } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -4210,33 +4712,6 @@ "node": ">= 0.6.3" } }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4374,9 +4849,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", - "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -5017,6 +5492,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/pino-abstract-transport/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/pino-std-serializers": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", @@ -5095,9 +5578,9 @@ } }, "node_modules/preact": { - "version": "10.19.5", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.5.tgz", - "integrity": "sha512-OPELkDmSVbKjbFqF9tgvOowiiQ9TmsJljIzXRyNE8nGiis94pwv1siF78rQkAP1Q1738Ce6pellRg/Ns/CtHqQ==", + "version": "10.19.6", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.6.tgz", + "integrity": "sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==", "dev": true, "funding": { "type": "opencollective", @@ -5254,6 +5737,19 @@ "stream-shift": "^1.0.0" } }, + "node_modules/pumpify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5343,18 +5839,24 @@ } }, "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/readdir-glob": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", @@ -5517,9 +6019,9 @@ } }, "node_modules/rollup": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", - "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.1.tgz", + "integrity": "sha512-ggqQKvx/PsB0FaWXhIvVkSWh7a/PCLQAsMjBc+nA2M8Rv2/HG0X6zvixAB7KyZBRtifBUhy5k8voQX/mRnABPg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -5532,19 +6034,19 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.12.0", - "@rollup/rollup-android-arm64": "4.12.0", - "@rollup/rollup-darwin-arm64": "4.12.0", - "@rollup/rollup-darwin-x64": "4.12.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.12.0", - "@rollup/rollup-linux-arm64-gnu": "4.12.0", - "@rollup/rollup-linux-arm64-musl": "4.12.0", - "@rollup/rollup-linux-riscv64-gnu": "4.12.0", - "@rollup/rollup-linux-x64-gnu": "4.12.0", - "@rollup/rollup-linux-x64-musl": "4.12.0", - "@rollup/rollup-win32-arm64-msvc": "4.12.0", - "@rollup/rollup-win32-ia32-msvc": "4.12.0", - "@rollup/rollup-win32-x64-msvc": "4.12.0", + "@rollup/rollup-android-arm-eabi": "4.12.1", + "@rollup/rollup-android-arm64": "4.12.1", + "@rollup/rollup-darwin-arm64": "4.12.1", + "@rollup/rollup-darwin-x64": "4.12.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.12.1", + "@rollup/rollup-linux-arm64-gnu": "4.12.1", + "@rollup/rollup-linux-arm64-musl": "4.12.1", + "@rollup/rollup-linux-riscv64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-musl": "4.12.1", + "@rollup/rollup-win32-arm64-msvc": "4.12.1", + "@rollup/rollup-win32-ia32-msvc": "4.12.1", + "@rollup/rollup-win32-x64-msvc": "4.12.1", "fsevents": "~2.3.2" } }, @@ -5771,20 +6273,20 @@ } }, "node_modules/shiki": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.1.5.tgz", - "integrity": "sha512-754GuKIwkUdT810Xm8btuyNQPL+q3PqOkwGW/VlmAWyMYp+HbvvDt69sWXO1sm5aeczBJQjmQTTMR4GkKQNQPw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.1.7.tgz", + "integrity": "sha512-9kUTMjZtcPH3i7vHunA6EraTPpPOITYTdA5uMrvsJRexktqP0s7P3s9HVK80b4pP42FRVe03D7fT3NmJv2yYhw==", "dev": true, "dependencies": { - "@shikijs/core": "1.1.5" + "@shikijs/core": "1.1.7" } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -5929,13 +6431,18 @@ } }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -6184,6 +6691,19 @@ "node": ">=6" } }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/testcontainers": { "version": "10.7.2", "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.7.2.tgz", @@ -6250,33 +6770,6 @@ "xtend": "~4.0.1" } }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -6604,9 +7097,9 @@ } }, "node_modules/vite": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.3.tgz", - "integrity": "sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.5.tgz", + "integrity": "sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==", "dev": true, "dependencies": { "esbuild": "^0.19.3", @@ -6697,16 +7190,16 @@ } }, "node_modules/vue": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz", - "integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==", + "version": "3.4.21", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz", + "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==", "dev": true, "dependencies": { - "@vue/compiler-dom": "3.4.19", - "@vue/compiler-sfc": "3.4.19", - "@vue/runtime-dom": "3.4.19", - "@vue/server-renderer": "3.4.19", - "@vue/shared": "3.4.19" + "@vue/compiler-dom": "3.4.21", + "@vue/compiler-sfc": "3.4.21", + "@vue/runtime-dom": "3.4.21", + "@vue/server-renderer": "3.4.21", + "@vue/shared": "3.4.21" }, "peerDependencies": { "typescript": "*" @@ -6871,9 +7364,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.0.tgz", + "integrity": "sha512-j9iR8g+/t0lArF4V6NE/QCfT+CO7iLqrXAHZbJdo+LfjqP1vR8Fg5bSiaq6Q2lOD1AUEVrEVIgABvBFYojJVYQ==", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -7018,6 +7514,19 @@ "node": "*" } }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "packages/emmett": { "name": "@event-driven-io/emmett", "version": "0.4.0", @@ -7038,8 +7547,6 @@ }, "packages/emmett-esdb/node_modules/@event-driven-io/emmett": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@event-driven-io/emmett/-/emmett-0.3.0.tgz", - "integrity": "sha512-eLdMMxKCRcU6MWBfR1jJthrElEoNcybOgSVj0KIWlauOx7IDl4Ymx9mRbDoSgNTAQ5jWnITpjcMeMJXRZKuvqQ==", "dependencies": { "uuid": "9.0.1" } @@ -7057,8 +7564,6 @@ }, "packages/emmett-expressjs/node_modules/@event-driven-io/emmett": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@event-driven-io/emmett/-/emmett-0.3.0.tgz", - "integrity": "sha512-eLdMMxKCRcU6MWBfR1jJthrElEoNcybOgSVj0KIWlauOx7IDl4Ymx9mRbDoSgNTAQ5jWnITpjcMeMJXRZKuvqQ==", "dependencies": { "uuid": "9.0.1" } @@ -7089,8 +7594,6 @@ }, "packages/emmett-testcontainers/node_modules/@event-driven-io/emmett": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@event-driven-io/emmett/-/emmett-0.3.0.tgz", - "integrity": "sha512-eLdMMxKCRcU6MWBfR1jJthrElEoNcybOgSVj0KIWlauOx7IDl4Ymx9mRbDoSgNTAQ5jWnITpjcMeMJXRZKuvqQ==", "dependencies": { "uuid": "9.0.1" } diff --git a/packages/emmett-fastify/src/e2e/decider/api.ts b/packages/emmett-fastify/src/e2e/decider/api.ts index bbd039f4..29905496 100644 --- a/packages/emmett-fastify/src/e2e/decider/api.ts +++ b/packages/emmett-fastify/src/e2e/decider/api.ts @@ -1,8 +1,8 @@ import { - assertNotEmptyString, DeciderCommandHandler, - type EventStore, + assertNotEmptyString, assertPositiveNumber, + type EventStore, } from '@event-driven-io/emmett'; import { type FastifyInstance, @@ -12,7 +12,6 @@ import { import { decider } from './businessLogic'; import { type PricedProductItem, type ProductItem } from './shoppingCart'; - export const handle = DeciderCommandHandler(decider); const dummyPriceProvider = (_productId: string) => { return 100; @@ -22,110 +21,92 @@ interface ShoppingCartItem { shoppingCartId: string; } -export const RegisterRoutes = (eventStore: EventStore) => (app: FastifyInstance) => { - app.post( - '/clients/:clientId/shopping-carts', - async (request: FastifyRequest, reply: FastifyReply): Promise => { - const { clientId } = request.params as { clientId: string }; - assertNotEmptyString(clientId); - const shoppingCartId = clientId; - await handle( - eventStore, - shoppingCartId, - { +export const RegisterRoutes = + (eventStore: EventStore) => (app: FastifyInstance) => { + app.post( + '/clients/:clientId/shopping-carts', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { clientId } = request.params as { clientId: string }; + assertNotEmptyString(clientId); + const shoppingCartId = clientId; + await handle(eventStore, shoppingCartId, { type: 'OpenShoppingCart', data: { clientId: shoppingCartId, shoppingCartId, now: new Date() }, - }, - ); - reply.code(201).send({ clientId }); - }, - ); - app.post( - '/clients/:clientId/shopping-carts/:shoppingCartId/product-items', - async (request: FastifyRequest, reply: FastifyReply): Promise => { - const { shoppingCartId } = request.params as ShoppingCartItem; - assertNotEmptyString(shoppingCartId); - const { productId, quantity } = request.body as PricedProductItem; - const productItem: ProductItem = { - productId: assertNotEmptyString(productId), - quantity: assertPositiveNumber(quantity), - }; + }); + return reply.code(201).send({ id: clientId }); + }, + ); + app.post( + '/clients/:clientId/shopping-carts/:shoppingCartId/product-items', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); + const { productId, quantity } = request.body as PricedProductItem; + const productItem: ProductItem = { + productId: assertNotEmptyString(productId), + quantity: assertPositiveNumber(quantity), + }; - const unitPrice = dummyPriceProvider(productItem.productId); - await handle( - eventStore, - shoppingCartId, - { + const unitPrice = dummyPriceProvider(productItem.productId); + await handle(eventStore, shoppingCartId, { type: 'AddProductItemToShoppingCart', data: { shoppingCartId, productItem: { ...productItem, unitPrice }, }, - }, + }); + return reply.code(204).send(); + }, + ); + app.delete( + '/clients/:clientId/shopping-carts/:shoppingCartId/product-items', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); + const { productId, quantity, unitPrice } = + request.query as PricedProductItem; + const productItem: PricedProductItem = { + productId: assertNotEmptyString(productId), + quantity: assertPositiveNumber(Number(quantity)), + unitPrice: assertPositiveNumber(Number(unitPrice)), + }; - ); - reply.code(204); - }, - ); - app.delete( - '/clients/:clientId/shopping-carts/:shoppingCartId/product-items', - async (request: FastifyRequest, reply: FastifyReply): Promise => { - const { shoppingCartId } = request.params as ShoppingCartItem; - assertNotEmptyString(shoppingCartId); - const { productId, quantity, unitPrice } = request.query as PricedProductItem; - const productItem: PricedProductItem = { - productId: assertNotEmptyString(productId), - quantity: assertPositiveNumber(Number(quantity)), - unitPrice: assertPositiveNumber(Number(unitPrice)), - }; - - await handle( - eventStore, - shoppingCartId, - { + await handle(eventStore, shoppingCartId, { type: 'RemoveProductItemFromShoppingCart', data: { shoppingCartId, productItem }, - }, - ); - reply.code(204); - }, - ); - app.post( - '/clients/:clientId/shopping-carts/:shoppingCartId/confirm', - async (request: FastifyRequest, reply: FastifyReply): Promise => { - const { shoppingCartId } = request.params as ShoppingCartItem; - assertNotEmptyString(shoppingCartId); + }); + return reply.code(204).send(); + }, + ); + app.post( + '/clients/:clientId/shopping-carts/:shoppingCartId/confirm', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); - await handle( - eventStore, - shoppingCartId, - { + await handle(eventStore, shoppingCartId, { type: 'ConfirmShoppingCart', data: { shoppingCartId, now: new Date() }, - }, - - ); - reply.code(204); - }, - ); - app.delete( - '/clients/:clientId/shopping-carts/:shoppingCartId', - async (request: FastifyRequest, reply: FastifyReply): Promise => { - const { shoppingCartId } = request.params as ShoppingCartItem; - assertNotEmptyString(shoppingCartId); - try { - await handle( - eventStore, - shoppingCartId, - { + }); + return reply.code(204).send(); + }, + ); + app.delete( + '/clients/:clientId/shopping-carts/:shoppingCartId', + async (request: FastifyRequest, reply: FastifyReply): Promise => { + const { shoppingCartId } = request.params as ShoppingCartItem; + assertNotEmptyString(shoppingCartId); + try { + await handle(eventStore, shoppingCartId, { type: 'CancelShoppingCart', data: { shoppingCartId, now: new Date() }, - }, - ); - } catch (error) { - reply.code(403).send({ detail: error.message }); - } - reply.code(204); - }, - ); -}; + }); + } catch (error) { + return error instanceof Error && 'message' in error + ? reply.code(403).send({ detail: error.message }) + : reply.code(403); + } + return reply.code(204).send(); + }, + ); + }; diff --git a/packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts b/packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts index 8462ce6e..5901f7b7 100644 --- a/packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts +++ b/packages/emmett-fastify/src/e2e/decider/applicationLogicWithOC.int.spec.ts @@ -1,9 +1,13 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ +import { + assertMatches, + getInMemoryEventStore, + type EventStore, +} from '@event-driven-io/emmett'; +import { type FastifyInstance } from 'fastify'; import assert from 'node:assert/strict'; import { beforeEach, describe, it } from 'node:test'; import { v4 as uuid } from 'uuid'; -import { type FastifyInstance } from 'fastify'; -import { getInMemoryEventStore, type EventStore, assertMatches } from '@event-driven-io/emmett'; import { getApplication } from '../..'; import { RegisterRoutes } from './api'; import { ShoppingCartErrors } from './businessLogic'; @@ -13,7 +17,6 @@ describe('Application logic with optimistic concurrency using Fastify', () => { let app: FastifyInstance; let eventStore: EventStore; beforeEach(async () => { - eventStore = getInMemoryEventStore(); const registerRoutes = RegisterRoutes(eventStore); app = await getApplication({ registerRoutes }); @@ -30,13 +33,13 @@ describe('Application logic with optimistic concurrency using Fastify', () => { url: `/clients/${clientId}/shopping-carts`, }); - const current = createResponse.json(); - if (!current?.clientId) { + const current = createResponse.json<{ id: string }>(); + if (!current?.id) { assert.fail(); } - assert.ok(current.clientId); + assert.ok(current.id); - const shoppingCartId = current.clientId; + const shoppingCartId = current.id; /////////////////////////////////////////////////// // 2. Add Two Pair of Shoes /////////////////////////////////////////////////// @@ -65,7 +68,6 @@ describe('Application logic with optimistic concurrency using Fastify', () => { body: tShirt, }); - assert.equal(response.statusCode, 204); /////////////////////////////////////////////////// @@ -94,7 +96,6 @@ describe('Application logic with optimistic concurrency using Fastify', () => { assert.equal(response.statusCode, 204); - /////////////////////////////////////////////////// // 6. Try Cancel Cart /////////////////////////////////////////////////// diff --git a/packages/emmett-fastify/src/index.ts b/packages/emmett-fastify/src/index.ts index 2071dc7d..2288503d 100644 --- a/packages/emmett-fastify/src/index.ts +++ b/packages/emmett-fastify/src/index.ts @@ -1,24 +1,30 @@ -import Compress from '@fastify/compress'; -import Etag from '@fastify/etag'; -import Form from '@fastify/formbody'; +import Compress, { type FastifyCompressOptions } from '@fastify/compress'; +import Etag, { type FastifyEtagOptions } from '@fastify/etag'; +import Form, { type FastifyFormbodyOptions } from '@fastify/formbody'; import closeWithGrace from 'close-with-grace'; import Fastify, { type FastifyInstance, + type FastifyPluginAsync, + type FastifyPluginCallback, + type FastifyPluginOptions, } from 'fastify'; -const defaultPlugins = [ - { plugin: Etag, options: {} }, - { plugin: Compress, options: { global: false } }, - { plugin: Form, options: {} }, +// TODO: THIS WILL NEED TO BE BETTER TYPED +type Plugin = { + plugin: FastifyPluginAsync | FastifyPluginCallback; + options: FastifyPluginOptions; +}; + +const defaultPlugins: Plugin[] = [ + { plugin: Etag, options: {} as FastifyEtagOptions }, + { plugin: Compress, options: { global: false } as FastifyCompressOptions }, + { plugin: Form, options: {} as FastifyFormbodyOptions }, ]; export interface ApplicationOptions { serverOptions?: { logger: boolean }; registerRoutes?: (app: FastifyInstance) => void; - activeDefaultPlugins?: Array<{ - plugin: unknown; - options: Record; - }>; + activeDefaultPlugins?: Plugin[]; } export const getApplication = async (options: ApplicationOptions) => {