From 4d132b2be8c1d079f07f066f8080b4971b5e76d2 Mon Sep 17 00:00:00 2001 From: Theo Ephraim Date: Mon, 2 Dec 2024 21:05:05 -0800 Subject: [PATCH] mvp of fastify integration --- .changeset/good-vans-hide.md | 6 + .../packages/fastify/.dmno/config.mts | 18 + .../packages/fastify/.dmno/tsconfig.json | 7 + example-repo/packages/fastify/package.json | 24 ++ .../packages/fastify/src/dmno-env.d.ts | 4 + example-repo/packages/fastify/src/index.ts | 78 ++++ example-repo/packages/fastify/tsconfig.json | 13 + example-repo/pnpm-lock.yaml | 390 +++++++++++++++--- .../core/src/globals-injector/injector.ts | 8 +- packages/core/src/lib/redaction-helpers.ts | 8 + packages/docs-site/astro.config.ts | 30 +- .../docs/docs/integrations/fastify.mdx | 68 +++ .../docs/docs/integrations/overview.mdx | 9 +- packages/docs-site/src/pages/docs/index.astro | 18 +- packages/integrations/fastify/.eslintrc.cjs | 6 + packages/integrations/fastify/README.md | 39 ++ packages/integrations/fastify/dmno.meta.json | 3 + packages/integrations/fastify/package.json | 65 +++ packages/integrations/fastify/src/index.ts | 56 +++ packages/integrations/fastify/tsconfig.json | 15 + packages/integrations/fastify/tsup.config.ts | 24 ++ pnpm-lock.yaml | 235 +++++++++++ 22 files changed, 1040 insertions(+), 84 deletions(-) create mode 100644 .changeset/good-vans-hide.md create mode 100644 example-repo/packages/fastify/.dmno/config.mts create mode 100644 example-repo/packages/fastify/.dmno/tsconfig.json create mode 100644 example-repo/packages/fastify/package.json create mode 100644 example-repo/packages/fastify/src/dmno-env.d.ts create mode 100644 example-repo/packages/fastify/src/index.ts create mode 100644 example-repo/packages/fastify/tsconfig.json create mode 100644 packages/docs-site/src/content/docs/docs/integrations/fastify.mdx create mode 100644 packages/integrations/fastify/.eslintrc.cjs create mode 100644 packages/integrations/fastify/README.md create mode 100644 packages/integrations/fastify/dmno.meta.json create mode 100644 packages/integrations/fastify/package.json create mode 100644 packages/integrations/fastify/src/index.ts create mode 100644 packages/integrations/fastify/tsconfig.json create mode 100644 packages/integrations/fastify/tsup.config.ts diff --git a/.changeset/good-vans-hide.md b/.changeset/good-vans-hide.md new file mode 100644 index 00000000..40255a1f --- /dev/null +++ b/.changeset/good-vans-hide.md @@ -0,0 +1,6 @@ +--- +"@dmno/fastify-integration": patch +"dmno": patch +--- + +initial version of fastify integration diff --git a/example-repo/packages/fastify/.dmno/config.mts b/example-repo/packages/fastify/.dmno/config.mts new file mode 100644 index 00000000..2ee58766 --- /dev/null +++ b/example-repo/packages/fastify/.dmno/config.mts @@ -0,0 +1,18 @@ +import { DmnoBaseTypes, defineDmnoService } from 'dmno'; + +export default defineDmnoService({ + pick: [], + settings: { + preventClientLeaks: true + }, + schema: { + PORT: { + extends: DmnoBaseTypes.port, + value: 3001 + }, + SOME_SECRET: { + value: 'shhh-dont-leak-me', + sensitive: true, + } + }, +}); diff --git a/example-repo/packages/fastify/.dmno/tsconfig.json b/example-repo/packages/fastify/.dmno/tsconfig.json new file mode 100644 index 00000000..db661d7a --- /dev/null +++ b/example-repo/packages/fastify/.dmno/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "dmno/tsconfigs/dmno-folder", + "include": [ + "./**/*.mts", + "./.typegen/global.d.ts" + ] +} \ No newline at end of file diff --git a/example-repo/packages/fastify/package.json b/example-repo/packages/fastify/package.json new file mode 100644 index 00000000..67e2745d --- /dev/null +++ b/example-repo/packages/fastify/package.json @@ -0,0 +1,24 @@ +{ + "name": "fastify", + "version": "1.0.0", + "description": "", + "main": "index.js", + "type": "module", + "scripts": { + "dev": "dmno run -w -- vite-node --watch src/index.ts" + }, + "keywords": [ ], + "author": "", + "license": "ISC", + "dependencies": { + "dmno": "link:../../../packages/core", + "@dmno/fastify-integration": "link:../../../packages/integrations/fastify", + "fastify": "^5.1.0" + }, + "devDependencies": { + "@types/node": "^20.12.7", + "fastify-tsconfig": "^2.0.0", + "vite": "^5", + "vite-node": "^2.1.8" + } +} diff --git a/example-repo/packages/fastify/src/dmno-env.d.ts b/example-repo/packages/fastify/src/dmno-env.d.ts new file mode 100644 index 00000000..5ec80415 --- /dev/null +++ b/example-repo/packages/fastify/src/dmno-env.d.ts @@ -0,0 +1,4 @@ +// inject DMNO_CONFIG global +/// +// inject DMNO_PUBLIC_CONFIG global +/// diff --git a/example-repo/packages/fastify/src/index.ts b/example-repo/packages/fastify/src/index.ts new file mode 100644 index 00000000..47446f41 --- /dev/null +++ b/example-repo/packages/fastify/src/index.ts @@ -0,0 +1,78 @@ +import Fastify from 'fastify'; +import { dmnoFastifyPlugin } from '@dmno/fastify-integration'; + +const fastify = Fastify({ + logger: true, + forceCloseConnections: true, // needed for vite-node HMR +}) + +// register our DMNO fastify plugin +fastify.register(dmnoFastifyPlugin); + +// ~ ROUTES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +fastify.get('/', function (request, reply) { + console.log('`console.log` tests ---------------------------------------') + console.log('log a secret:', DMNO_CONFIG.SOME_SECRET); + console.log('log a secret in array:', [DMNO_CONFIG.SOME_SECRET]); + console.log('log a secret in obj:', { secret: DMNO_CONFIG.SOME_SECRET }); + + console.log('`request.log` tests ---------------------------------------') + request.log.info(DMNO_CONFIG.SOME_SECRET, 'asdf'); // added as `msg` + request.log.info([DMNO_CONFIG.SOME_SECRET]); // added as `0` + request.log.info({ secret: DMNO_CONFIG.SOME_SECRET }); // overwrites keys on the obj + + reply.send({ + hello: 'world', + demos: [ + `http://${request.host}/leak`, + `http://${request.host}/intercept` + ] + }) +}); + +fastify.get('/leak', function (request, reply) { + // leak the secret as part of the response + reply.send({ + superSecretKey: DMNO_CONFIG.SOME_SECRET, + message: 'this endpoint should throw due to leaking a secret in the response', + }) +}); + +fastify.get('/intercept', async function (request, reply) { + // send a secret to a domain that is not part of the allow list + await fetch('https://api.sampleapis.com/coffee/hot', { + headers: { + 'x-auth': DMNO_CONFIG.SOME_SECRET + } + }); + + reply.send({ message: 'this endpoint should throw due to a leaked secret' }); +}); + +// ~ START THE SERVER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +fastify.listen({ port: DMNO_CONFIG.PORT }, function (err, address) { + if (err) { + fastify.log.error(err) + process.exit(1) + } + + console.log(`Server now listening @ ${address.replace('[::1]', 'localhost')}`); +}) + + +// ~ Live reload / HMR using vite-node ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if (import.meta.hot) { + import.meta.hot.on("vite:beforeFullReload", async () => { + await fastify.close(); + + }); + import.meta.hot.dispose(() => { + console.log('hot.dispose'); + fastify.close() + }); +} + +process.on('exit', () => { + console.log('process.exit'); + fastify.close() +}) diff --git a/example-repo/packages/fastify/tsconfig.json b/example-repo/packages/fastify/tsconfig.json new file mode 100644 index 00000000..c1e860c3 --- /dev/null +++ b/example-repo/packages/fastify/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "fastify-tsconfig", + "compilerOptions": { + "outDir": "dist", + "sourceMap": true, + "composite": true, + "types": [ "vite/client" ], + "strict": true + }, + "include": [ + "src/**/*.ts" + ] +} diff --git a/example-repo/pnpm-lock.yaml b/example-repo/pnpm-lock.yaml index 798c72f4..3457b198 100644 --- a/example-repo/pnpm-lock.yaml +++ b/example-repo/pnpm-lock.yaml @@ -209,6 +209,31 @@ importers: specifier: ^4.19.2 version: 4.19.2 + packages/fastify: + dependencies: + '@dmno/fastify-integration': + specifier: link:../../../packages/integrations/fastify + version: link:../../../packages/integrations/fastify + dmno: + specifier: link:../../../packages/core + version: link:../../../packages/core + fastify: + specifier: ^5.1.0 + version: 5.1.0 + devDependencies: + '@types/node': + specifier: ^20.12.7 + version: 20.14.13 + fastify-tsconfig: + specifier: ^2.0.0 + version: 2.0.0 + vite: + specifier: ^5 + version: 5.3.5(@types/node@20.14.13)(terser@5.31.3) + vite-node: + specifier: ^2.1.8 + version: 2.1.8(@types/node@20.14.13)(terser@5.31.3) + packages/group1: dependencies: dmno: @@ -253,7 +278,7 @@ importers: version: 8.4.40 tailwindcss: specifier: ^3.4.3 - version: 3.4.7(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) + version: 3.4.7(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4)) typescript: specifier: ^5.4.5 version: 5.5.4 @@ -302,7 +327,7 @@ importers: version: link:../../../packages/integrations/remix '@remix-run/dev': specifier: ^2.10.3 - version: 2.10.3(@remix-run/react@2.10.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@remix-run/serve@2.10.3(typescript@5.5.4))(@types/node@20.14.13)(terser@5.31.3)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.13)(terser@5.31.3)) + version: 2.10.3(@remix-run/react@2.10.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@remix-run/serve@2.10.3(typescript@5.5.4))(@types/node@20.14.13)(terser@5.31.3)(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.13)(terser@5.31.3)) '@types/react': specifier: ^18.2.20 version: 18.3.3 @@ -326,7 +351,7 @@ importers: version: 8.57.0 eslint-import-resolver-typescript: specifier: ^3.6.1 - version: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + version: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: specifier: ^2.28.1 version: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) @@ -344,7 +369,7 @@ importers: version: 8.4.40 tailwindcss: specifier: ^3.4.4 - version: 3.4.7(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) + version: 3.4.7(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4)) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -1369,10 +1394,22 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@fastify/ajv-compiler@4.0.1': + resolution: {integrity: sha512-DxrBdgsjNLP0YM6W5Hd6/Fmj43S8zMKiFJYgi+Ri3htTGAowPVG/tG1wpnWLMjufEnehRivUCKZ1pLDIoZdTuw==} + '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} + '@fastify/error@4.0.0': + resolution: {integrity: sha512-OO/SA8As24JtT1usTUTKgGH7uLvhfwZPwlptRi2Dp5P4KKmJI3gvsZ8MIHnNwDs4sLf/aai5LzTyl66xr7qMxA==} + + '@fastify/fast-json-stringify-compiler@5.0.1': + resolution: {integrity: sha512-f2d3JExJgFE3UbdFcpPwqNUEoHWmt8pAKf8f+9YuLESdefA0WgqxeT6DrGL4Yrf/9ihXNSKOqpjEmurV405meA==} + + '@fastify/merge-json-schemas@0.1.1': + resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + '@hapi/bourne@3.0.0': resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} @@ -2537,6 +2574,9 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -2568,9 +2608,20 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -2718,6 +2769,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + autoprefixer@10.4.19: resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} engines: {node: ^10 || ^12 || >=14} @@ -2729,6 +2784,9 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + avvio@9.1.0: + resolution: {integrity: sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==} + axe-core@4.9.1: resolution: {integrity: sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==} engines: {node: '>=4'} @@ -3108,6 +3166,10 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + cookies@0.9.1: resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} engines: {node: '>= 0.8'} @@ -3269,6 +3331,15 @@ packages: supports-color: optional: true + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} @@ -3787,6 +3858,9 @@ packages: externality@1.0.2: resolution: {integrity: sha512-LyExtJWKxtgVzmgtEHyQtLFpw1KFhQphF9nTG8TpAIVkiI/xQ3FJh75tRFLYl4hkn7BNIIdLJInuDAavX35pMw==} + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -3800,12 +3874,35 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fast-json-stringify@6.0.0: + resolution: {integrity: sha512-FGMKZwniMTgZh7zQp9b6XnBVxUmKVahQLQeRQHqwYmPDqDhcEKZ3BaQsxelFFI5PY7nN71OEeiL47/zUWcYe1A==} + fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} fast-npm-meta@0.1.1: resolution: {integrity: sha512-uS9DjGncI/9XZ6HJFrci0WzSi++N8Jskbb2uB7+9SQlrgA3VaLhXhV9Gl5HwIGESHkayYYZFGnVNhJwRDKCWIA==} + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + + fast-uri@2.4.0: + resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} + + fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + + fastify-tsconfig@2.0.0: + resolution: {integrity: sha512-pvYwdtbZUJr/aTD7ZE0rGlvtYpx7IThHKVLBoqCKmT3FJpwm23XA2+PDmq8ZzfqqG4ajpyrHd5bkIixcIFjPhQ==} + engines: {node: '>=18.0.0'} + + fastify@5.1.0: + resolution: {integrity: sha512-0SdUC5AoiSgMSc2Vxwv3WyKzyGMDJRAW/PgNsK1kZrnkO6MeqUIW9ovVg9F2UGIqtIcclYMyeJa4rK6OZc7Jxg==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -3827,6 +3924,10 @@ packages: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} + find-my-way@9.1.0: + resolution: {integrity: sha512-Y5jIsuYR4BwWDYYQ2A/RWWE6gD8a0FMgtU+HOq1WKku+Cwdz8M1v8wcAmRXXM1/iqtoqg06v+LjAxMYbCjViMw==} + engines: {node: '>=14'} + find-up-simple@1.0.0: resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} engines: {node: '>=18'} @@ -4581,9 +4682,15 @@ packages: resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + json-schema-ref-resolver@1.0.1: + resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -4681,6 +4788,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + light-my-request@6.3.0: + resolution: {integrity: sha512-bWTAPJmeWQH5suJNYwG0f5cs0p6ho9e6f1Ppoxv5qMosY+s9Ir2+ZLvvHcgA7VTDop4zl/NCHhOVVqU+kd++Ow==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -5463,6 +5573,10 @@ packages: ohash@1.1.3: resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + on-finished@2.3.0: resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} engines: {node: '>= 0.8'} @@ -5668,6 +5782,16 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.5.0: + resolution: {integrity: sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==} + hasBin: true + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -5987,6 +6111,9 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process-warning@4.0.0: + resolution: {integrity: sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==} + process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} @@ -6047,6 +6174,9 @@ packages: queue-tick@1.0.1: resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} @@ -6114,6 +6244,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + redis-errors@1.2.0: resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} engines: {node: '>=4'} @@ -6233,6 +6367,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + require-like@0.1.2: resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} @@ -6267,6 +6405,10 @@ packages: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} + engines: {node: '>=10'} + retext-latin@3.1.0: resolution: {integrity: sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==} @@ -6347,6 +6489,13 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + safe-regex2@4.0.0: + resolution: {integrity: sha512-Hvjfv25jPDVr3U+4LDzBuZPPOymELG3PYcSk5hcevooo1yxxamQL/bHs/GrEPGmMoMEwRrHVGiCA1pXi97B8Ew==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -6360,6 +6509,9 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -6460,6 +6612,9 @@ packages: smob@1.5.0: resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} @@ -6498,6 +6653,10 @@ packages: resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} engines: {node: '>=0.10.0'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -6719,16 +6878,15 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - tinyrainbow@1.2.0: - resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} - engines: {node: '>=14.0.0'} - to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -6737,6 +6895,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toad-cache@3.7.0: + resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} + engines: {node: '>=12'} + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -7192,8 +7354,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite-node@2.0.4: - resolution: {integrity: sha512-ZpJVkxcakYtig5iakNeL7N3trufe3M6vGuzYAr4GsbCTwobDeyPJpE4cjDhhPluv8OvQCFzu2LWp6GkoKRITXA==} + vite-node@2.1.8: + resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -8398,8 +8560,24 @@ snapshots: '@eslint/js@8.57.0': {} + '@fastify/ajv-compiler@4.0.1': + dependencies: + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-uri: 3.0.3 + '@fastify/busboy@2.1.1': {} + '@fastify/error@4.0.0': {} + + '@fastify/fast-json-stringify-compiler@5.0.1': + dependencies: + fast-json-stringify: 6.0.0 + + '@fastify/merge-json-schemas@0.1.1': + dependencies: + fast-deep-equal: 3.1.3 + '@hapi/bourne@3.0.0': {} '@humanwhocodes/config-array@0.11.14': @@ -8878,7 +9056,7 @@ snapshots: unenv: 1.10.0 unplugin: 1.12.0 vite: 5.3.5(@types/node@20.14.13)(terser@5.31.3) - vite-node: 2.0.4(@types/node@20.14.13)(terser@5.31.3) + vite-node: 2.1.8(@types/node@20.14.13)(terser@5.31.3) vite-plugin-checker: 0.7.2(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.13)(terser@5.31.3))(vue-tsc@2.0.29(typescript@5.5.4)) vue: 3.4.34(typescript@5.5.4) vue-bundle-renderer: 2.1.0 @@ -8972,7 +9150,7 @@ snapshots: '@prisma/engines@4.16.2': {} - '@remix-run/dev@2.10.3(@remix-run/react@2.10.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@remix-run/serve@2.10.3(typescript@5.5.4))(@types/node@20.14.13)(terser@5.31.3)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.13)(terser@5.31.3))': + '@remix-run/dev@2.10.3(@remix-run/react@2.10.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@remix-run/serve@2.10.3(typescript@5.5.4))(@types/node@20.14.13)(terser@5.31.3)(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4))(typescript@5.5.4)(vite@5.3.5(@types/node@20.14.13)(terser@5.31.3))': dependencies: '@babel/core': 7.24.9 '@babel/generator': 7.25.0 @@ -9016,7 +9194,7 @@ snapshots: pidtree: 0.6.0 postcss: 8.4.40 postcss-discard-duplicates: 5.1.0(postcss@8.4.40) - postcss-load-config: 4.0.2(postcss@8.4.40)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) + postcss-load-config: 4.0.2(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4)) postcss-modules: 6.0.0(postcss@8.4.40) prettier: 2.8.8 pretty-ms: 7.0.1 @@ -9963,6 +10141,8 @@ snapshots: dependencies: event-target-shim: 5.0.1 + abstract-logging@2.0.1: {} + accepts@1.3.8: dependencies: mime-types: 2.1.35 @@ -9993,6 +10173,10 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -10000,6 +10184,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-align@3.0.1: dependencies: string-width: 4.2.3 @@ -10249,6 +10440,8 @@ snapshots: asynckit@0.4.0: {} + atomic-sleep@1.0.0: {} + autoprefixer@10.4.19(postcss@8.4.40): dependencies: browserslist: 4.23.2 @@ -10263,6 +10456,11 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 + avvio@9.1.0: + dependencies: + '@fastify/error': 4.0.0 + fastq: 1.17.1 + axe-core@4.9.1: {} axios@0.27.2(debug@4.3.6): @@ -10653,6 +10851,8 @@ snapshots: cookie@0.6.0: {} + cookie@1.0.2: {} + cookies@0.9.1: dependencies: depd: 2.0.0 @@ -10809,6 +11009,10 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.3.7: + dependencies: + ms: 2.1.3 + decode-named-character-reference@1.0.2: dependencies: character-entities: 2.0.2 @@ -11304,24 +11508,7 @@ snapshots: debug: 4.3.6 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - fast-glob: 3.3.2 - get-tsconfig: 4.7.6 - is-core-module: 2.15.0 - is-glob: 4.0.3 - transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - - supports-color - - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0): - dependencies: - debug: 4.3.6 - enhanced-resolve: 5.17.1 - eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.6 @@ -11333,7 +11520,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -11344,17 +11531,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.5.4) - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0) - transitivePeerDependencies: - - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 @@ -11365,7 +11541,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.0 is-glob: 4.0.3 @@ -11659,6 +11835,8 @@ snapshots: pathe: 1.1.2 ufo: 1.5.4 + fast-decode-uri-component@1.0.1: {} + fast-deep-equal@3.1.3: {} fast-fifo@1.3.2: {} @@ -11673,10 +11851,50 @@ snapshots: fast-json-stable-stringify@2.1.0: {} + fast-json-stringify@6.0.0: + dependencies: + '@fastify/merge-json-schemas': 0.1.1 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-deep-equal: 3.1.3 + fast-uri: 2.4.0 + json-schema-ref-resolver: 1.0.1 + rfdc: 1.4.1 + fast-levenshtein@2.0.6: {} fast-npm-meta@0.1.1: {} + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-redact@3.5.0: {} + + fast-uri@2.4.0: {} + + fast-uri@3.0.3: {} + + fastify-tsconfig@2.0.0: {} + + fastify@5.1.0: + dependencies: + '@fastify/ajv-compiler': 4.0.1 + '@fastify/error': 4.0.0 + '@fastify/fast-json-stringify-compiler': 5.0.1 + abstract-logging: 2.0.1 + avvio: 9.1.0 + fast-json-stringify: 6.0.0 + find-my-way: 9.1.0 + light-my-request: 6.3.0 + pino: 9.5.0 + process-warning: 4.0.0 + proxy-addr: 2.0.7 + rfdc: 1.4.1 + secure-json-parse: 2.7.0 + semver: 7.6.3 + toad-cache: 3.7.0 + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -11707,6 +11925,12 @@ snapshots: transitivePeerDependencies: - supports-color + find-my-way@9.1.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 4.0.0 + find-up-simple@1.0.0: {} find-up@4.1.0: @@ -12542,8 +12766,14 @@ snapshots: json-parse-even-better-errors@3.0.2: {} + json-schema-ref-resolver@1.0.1: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@1.0.2: @@ -12674,6 +12904,12 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + light-my-request@6.3.0: + dependencies: + cookie: 1.0.2 + process-warning: 4.0.0 + set-cookie-parser: 2.6.0 + lilconfig@2.1.0: {} lilconfig@3.1.2: {} @@ -14067,6 +14303,8 @@ snapshots: ohash@1.1.3: {} + on-exit-leak-free@2.1.2: {} + on-finished@2.3.0: dependencies: ee-first: 1.1.1 @@ -14289,6 +14527,26 @@ snapshots: pify@4.0.1: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.0.0: {} + + pino@9.5.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pirates@4.0.6: {} pkg-dir@4.2.0: @@ -14356,7 +14614,7 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.40 - postcss-load-config@4.0.2(postcss@8.4.40)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)): + postcss-load-config@4.0.2(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4)): dependencies: lilconfig: 3.1.2 yaml: 2.5.0 @@ -14578,6 +14836,8 @@ snapshots: process-nextick-args@2.0.1: {} + process-warning@4.0.0: {} + process@0.11.10: {} promise-inflight@1.0.1: {} @@ -14637,6 +14897,8 @@ snapshots: queue-tick@1.0.1: {} + quick-format-unescaped@4.0.4: {} + radix3@1.1.2: {} randombytes@2.1.0: @@ -14719,6 +14981,8 @@ snapshots: dependencies: picomatch: 2.3.1 + real-require@0.2.0: {} + redis-errors@1.2.0: {} redis-parser@3.0.0: @@ -14883,6 +15147,8 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + require-like@0.1.2: {} resolve-from@4.0.0: {} @@ -14915,6 +15181,8 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + ret@0.5.0: {} + retext-latin@3.1.0: dependencies: '@types/nlcst': 1.0.4 @@ -15035,6 +15303,12 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 + safe-regex2@4.0.0: + dependencies: + ret: 0.5.0 + + safe-stable-stringify@2.5.0: {} + safer-buffer@2.1.2: {} scheduler@0.23.2: @@ -15048,6 +15322,8 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 + secure-json-parse@2.7.0: {} + semver@6.3.1: {} semver@7.6.3: {} @@ -15191,6 +15467,10 @@ snapshots: smob@1.5.0: {} + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + source-map-js@1.2.0: {} source-map-support@0.5.21: @@ -15224,6 +15504,8 @@ snapshots: speakingurl@14.0.1: {} + split2@4.2.0: {} + sprintf-js@1.0.3: {} ssri@10.0.6: @@ -15416,7 +15698,7 @@ snapshots: system-architecture@0.1.0: {} - tailwindcss@3.4.7(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)): + tailwindcss@3.4.7(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -15435,7 +15717,7 @@ snapshots: postcss: 8.4.40 postcss-import: 15.1.0(postcss@8.4.40) postcss-js: 4.0.1(postcss@8.4.40) - postcss-load-config: 4.0.2(postcss@8.4.40)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) + postcss-load-config: 4.0.2(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.3(@swc/helpers@0.5.5))(@types/node@20.14.13)(typescript@5.5.4)) postcss-nested: 6.2.0(postcss@8.4.40) postcss-selector-parser: 6.1.1 resolve: 1.22.8 @@ -15496,6 +15778,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + through2@2.0.5: dependencies: readable-stream: 2.3.8 @@ -15503,14 +15789,14 @@ snapshots: tiny-invariant@1.3.3: {} - tinyrainbow@1.2.0: {} - to-fast-properties@2.0.0: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + toad-cache@3.7.0: {} + toidentifier@1.0.1: {} toml@3.0.0: {} @@ -16051,12 +16337,12 @@ snapshots: - supports-color - terser - vite-node@2.0.4(@types/node@20.14.13)(terser@5.31.3): + vite-node@2.1.8(@types/node@20.14.13)(terser@5.31.3): dependencies: cac: 6.7.14 - debug: 4.3.6 + debug: 4.3.7 + es-module-lexer: 1.5.4 pathe: 1.1.2 - tinyrainbow: 1.2.0 vite: 5.3.5(@types/node@20.14.13)(terser@5.31.3) transitivePeerDependencies: - '@types/node' diff --git a/packages/core/src/globals-injector/injector.ts b/packages/core/src/globals-injector/injector.ts index a67a18dc..ab8be5f9 100644 --- a/packages/core/src/globals-injector/injector.ts +++ b/packages/core/src/globals-injector/injector.ts @@ -1,5 +1,7 @@ +import kleur from 'kleur'; import { redactString, + redactSensitiveConfig, resetSensitiveConfigRedactor, patchGlobalConsoleToRedactSensitiveLogs, unpatchGlobalConsoleSensitiveLogRedaction, @@ -242,6 +244,8 @@ function isString(s: any) { return Object.prototype.toString.call(s) === '[object String]'; } +(globalThis as any)._dmnoRedact = redactSensitiveConfig; + // reusable leak scanning helper function, used by various integrations (globalThis as any)._dmnoLeakScan = function _dmnoLeakScan( toScan: string | Response | ReadableStream, @@ -262,8 +266,8 @@ function isString(s: any) { // so we'll write a nicer error message to help the user debug console.error([ // eslint-disable-line no-console '', - '🚨 DETECTED LEAKED SENSITIVE CONFIG 🚨', - `> Config item key: ${itemKey}`, + `🚨 ${kleur.bgRed(' DETECTED LEAKED SENSITIVE CONFIG ')} 🚨`, + `> Config item key: ${kleur.blue(itemKey)}`, ...meta?.method ? [`> Scan method: ${meta.method}`] : [], ...meta?.file ? [`> File: ${meta.file}`] : [], '', diff --git a/packages/core/src/lib/redaction-helpers.ts b/packages/core/src/lib/redaction-helpers.ts index 18c4001b..47632708 100644 --- a/packages/core/src/lib/redaction-helpers.ts +++ b/packages/core/src/lib/redaction-helpers.ts @@ -119,6 +119,14 @@ export function redactSensitiveConfig(o: any): any { if (Array.isArray(o)) { return o.map(redactSensitiveConfig); } + // try to redact if it's a plain object - not necessarily great for perf... + if (o && typeof (o) === 'object' && Object.getPrototypeOf(o) === Object.prototype) { + try { + return JSON.parse(redactSensitiveConfig(JSON.stringify(o))); + } catch (err) { + return o; + } + } const type = typeof o; if (type === 'string' || (type === 'object' && Object.prototype.toString.call(o) === '[object String]')) { diff --git a/packages/docs-site/astro.config.ts b/packages/docs-site/astro.config.ts index 5b34d693..87e9a88e 100644 --- a/packages/docs-site/astro.config.ts +++ b/packages/docs-site/astro.config.ts @@ -190,29 +190,13 @@ export default defineConfig({ label: 'Integrations', badge: 'New', items: [ - { - label: 'Overview', - link: '/docs/integrations/overview/', - }, - { - label: 'Remix', - link: '/docs/integrations/remix/', - }, - { - label: 'Next.js', - link: '/docs/integrations/nextjs/', - }, - { - label: 'Astro', - link: '/docs/integrations/astro/', - }, - { - label: 'Vite', - link: '/docs/integrations/vite/', - }, { - label: 'Node.js', - link: '/docs/integrations/node/', - }, + { label: 'Overview', link: '/docs/integrations/overview/' }, + { label: 'Remix', link: '/docs/integrations/remix/' }, + { label: 'Next.js', link: '/docs/integrations/nextjs/' }, + { label: 'Astro', link: '/docs/integrations/astro/' }, + { label: 'Vite', link: '/docs/integrations/vite/' }, + { label: 'Fastify', link: '/docs/integrations/fastify/' }, + { label: 'Node.js', link: '/docs/integrations/node/' }, ], }, { label: 'Platforms', diff --git a/packages/docs-site/src/content/docs/docs/integrations/fastify.mdx b/packages/docs-site/src/content/docs/docs/integrations/fastify.mdx new file mode 100644 index 00000000..50971b23 --- /dev/null +++ b/packages/docs-site/src/content/docs/docs/integrations/fastify.mdx @@ -0,0 +1,68 @@ +--- +title: Fastify +description: Use DMNO to manage your Fastify app's environment variables +npmPackage: "@dmno/fastify-integration" +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components' +import TabbedCode from '@/components/TabbedCode.astro'; +import BugReportLink from '@/components/BugReportLink.astro'; + +Fastify does not provide any built-in handling of env vars, although there is a [fastify-env](https://github.com/fastify/fastify-env) plugin, which intenally uses dotenv files with json schema and ajv for validations. Whether you use this plugin, or have wired up something yourself, we think using DMNO instead will provides tons of advantages. + +### Installation + +While `dmno init` will automatically detect that you are using Fastify and install the necessary integration packages for you, you may also want to install them yourself: + + + +Then, wherever you initialize your `fastify` instance and register plugins, import and register our `dmnoFastifyPlugin`: + +```diff lang="js" +import Fastify from 'fastify'; ++import { dmnoFastifyPlugin } from '@dmno/fastify-integration'; + +const fastify = Fastify({ /* ... */ }) + ++fastify.register(dmnoFastifyPlugin); +``` + +### Configure your configuration schema + +`dmno init` will scaffold out the `schema` in your `config.mts` files based on your existing `.env` files. See our [Schema Guide](/docs/guides/schema/) for the specifics of how to author additional updates to your DMNO `schema`. + +### Adjusting package.json scripts +Becauase there is no dev server running where we can spawn a dmno server, we must run our dev and boot commands via [`dmno run`](/docs/reference/cli/run/). You'll want to adjust your package.json scripts accordingly: + +```diff lang="json" title="package.json" ins=/(dmno run (-w )?-- )/ +{ + "name": "yourapp", + "scripts": { + "dev": "dmno run -w -- nodemon src/main.js", + "start": "dmno run -- node src/main.js" + }, + // ... +} +``` + +You'll probably also want to run any other one-off scripts or other tools that require config via `dmno run` so that they get your config and secrets injected. + +## Accessing config + +> Use `DMNO_CONFIG` instead of `process.env` 🎉 + +You'll now have fully typed and validated config and some cool security features described below. + + +## Security and leak prevention + +Aside from the general DX improvements that DMNO provides, it also introduces important security features to keep your secrets safe: +- redacts your sensitive config from logs +- intercepts requests that send sensitive config to the wrong place +- stops returning sensitive config as part of server responses + +You can read more about these features and how to enable/disable them in our [Security Guide](/docs/get-started/security/). + +The Fastify plugin does its best to enable these things automatically, but it would be entirely reasonable to disable these features, and use the underlying helpers to customize the behavior. + + diff --git a/packages/docs-site/src/content/docs/docs/integrations/overview.mdx b/packages/docs-site/src/content/docs/docs/integrations/overview.mdx index 1b900f7d..6475e417 100644 --- a/packages/docs-site/src/content/docs/docs/integrations/overview.mdx +++ b/packages/docs-site/src/content/docs/docs/integrations/overview.mdx @@ -49,7 +49,6 @@ Legend: | Dynamic Config | Access config items at runtime | 🧰| | | Middleware | Detects leaked secrets | 🧰 | | - ### [Vite](/docs/integrations/vite/) | Feature | Description | Supported | Notes | @@ -59,3 +58,11 @@ Legend: | Dynamic Config | Access config items at runtime | 🧰| | | DMNO Types | Framework specific types from DMNO | 🗓️ | | | Middleware | Detects leaked secrets | 🗓️ | | + +### [Fastify](/docs/integrations/fastify/) + +| Feature | Description | Supported | Notes | +| :--- | :--- | :--- | :--- | +| Public Config | Access non-sensitive items | ✅ | | +| Sensitive Config | Access sensitive items | ✅ | +| Middleware | Detects leaked secrets | ✅ | | diff --git a/packages/docs-site/src/pages/docs/index.astro b/packages/docs-site/src/pages/docs/index.astro index a56a9a1f..6e289461 100644 --- a/packages/docs-site/src/pages/docs/index.astro +++ b/packages/docs-site/src/pages/docs/index.astro @@ -9,6 +9,7 @@ import NextLogoSvg from '~icons/logos/nextjs?raw'; import RemixLogoSvg from '~icons/logos/remix-icon?raw'; import AstroLogoSvg from '~icons/devicon/astro?raw'; import NodeLogoSvg from '~icons/logos/nodejs-icon?raw'; +import FastifyLogoSvg from '~icons/logos/fastify-icon?raw'; --- + +
@@ -97,7 +101,6 @@ import NodeLogoSvg from '~icons/logos/nodejs-icon?raw';