From 4fa892d60cfe8292d669696d12094618af126a0b Mon Sep 17 00:00:00 2001 From: Andreas Kienle Date: Tue, 13 May 2025 14:31:01 +0200 Subject: [PATCH 1/9] Prototype BFF --- frontend-config.json | 1 - server/.env.template | 17 + server/README.md | 1 + server/app.js | 23 + server/config/env.js | 26 + server/package-lock.json | 1100 ++++++++++++++++++++ server/package.json | 25 + server/plugins/auth-utils.js | 176 ++++ server/plugins/http-proxy.js | 93 ++ server/plugins/secure-session.js | 26 + server/plugins/sensible.js | 8 + server/routes/auth.js | 74 ++ server/routes/root.js | 9 + src/App.tsx | 40 +- src/context/FrontendConfigContext.tsx | 1 - src/lib/api/fetch.ts | 8 +- src/main.tsx | 43 +- src/spaces/onboarding/auth/AuthContext.tsx | 105 ++ src/utils/testing.ts | 1 - vite.config.ts | 12 + 20 files changed, 1731 insertions(+), 58 deletions(-) create mode 100644 server/.env.template create mode 100644 server/README.md create mode 100644 server/app.js create mode 100644 server/config/env.js create mode 100644 server/package-lock.json create mode 100644 server/package.json create mode 100644 server/plugins/auth-utils.js create mode 100644 server/plugins/http-proxy.js create mode 100644 server/plugins/secure-session.js create mode 100644 server/plugins/sensible.js create mode 100644 server/routes/auth.js create mode 100644 server/routes/root.js create mode 100644 src/spaces/onboarding/auth/AuthContext.tsx diff --git a/frontend-config.json b/frontend-config.json index 5d421989..86f73dda 100644 --- a/frontend-config.json +++ b/frontend-config.json @@ -1,5 +1,4 @@ { - "backendUrl": "http://localhost:3000", "gatewayUrl": "https://gateway.ui.dev-core.mcpd.shoot.canary.k8s-hana.ondemand.com/kubernetes/graphql", "landscape": "LOCAL", "documentationBaseUrl": "http://localhost:3000", diff --git a/server/.env.template b/server/.env.template new file mode 100644 index 00000000..5a864be6 --- /dev/null +++ b/server/.env.template @@ -0,0 +1,17 @@ +# OpenID Connect Configuration for Onboarding API +OIDC_ISSUER= +OIDC_CLIENT_ID= +OIDC_SCOPES= +OIDC_REDIRECT_URI=http://localhost:5173 + +POST_LOGIN_REDIRECT=http://localhost:5173 + + +# Location of the API Backend +API_BACKEND_URL= + + +# Cookie Secret +# Replace this value with a strong, randomly generated string (at least 32 characters). +# Example for generation in Node.js: require('crypto').randomBytes(32).toString('hex') +COOKIE_SECRET= diff --git a/server/README.md b/server/README.md new file mode 100644 index 00000000..f87f5c14 --- /dev/null +++ b/server/README.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/server/app.js b/server/app.js new file mode 100644 index 00000000..ba1284a0 --- /dev/null +++ b/server/app.js @@ -0,0 +1,23 @@ +import path, { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import AutoLoad from "@fastify/autoload"; +import envPlugin from "./config/env.js"; + +export const options = {}; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +export default async function(fastify, opts) { + await fastify.register(envPlugin); + + await fastify.register(AutoLoad, { + dir: join(__dirname, "plugins"), + options: { ...opts }, + }); + + await fastify.register(AutoLoad, { + dir: join(__dirname, "routes"), + options: { ...opts }, + }); +} diff --git a/server/config/env.js b/server/config/env.js new file mode 100644 index 00000000..c137d93d --- /dev/null +++ b/server/config/env.js @@ -0,0 +1,26 @@ +import fastifyPlugin from "fastify-plugin"; +import fastifyEnv from "@fastify/env"; + +const schema = { + type: "object", + required: ["OIDC_ISSUER", "OIDC_CLIENT_ID", "OIDC_REDIRECT_URI", "OIDC_SCOPES", "POST_LOGIN_REDIRECT", "COOKIE_SECRET", "API_BACKEND_URL"], + properties: { + // Application variables (.env) + OIDC_ISSUER: { type: "string" }, + OIDC_CLIENT_ID: { type: "string" }, + OIDC_REDIRECT_URI: { type: "string" }, + OIDC_SCOPES: { type: "string" }, + POST_LOGIN_REDIRECT: { type: "string" }, + COOKIE_SECRET: { type: "string" }, + API_BACKEND_URL: { type: "string" }, + + // System variables + NODE_ENV: { type: "string", enum: ["development", "production"] }, + }, +}; + +async function envPlugin(fastify) { + await fastify.register(fastifyEnv, { schema }); +} + +export default fastifyPlugin(envPlugin); diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 00000000..acc43d04 --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,1100 @@ +{ + "name": "ui-bff", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ui-bff", + "version": "1.0.0", + "dependencies": { + "@fastify/autoload": "^6.3.0", + "@fastify/cookie": "^11.0.2", + "@fastify/env": "^5.0.2", + "@fastify/http-proxy": "^11.1.2", + "@fastify/secure-session": "^8.2.0", + "@fastify/sensible": "^6.0.3", + "fastify": "^5.3.2", + "fastify-plugin": "^5.0.1" + }, + "engines": { + "node": "^22.0.0", + "npm": "^11.0.0" + } + }, + "node_modules/@fastify/ajv-compiler": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.2.tgz", + "integrity": "sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^3.0.0" + } + }, + "node_modules/@fastify/autoload": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@fastify/autoload/-/autoload-6.3.0.tgz", + "integrity": "sha512-VBYApgvqX5e+M2BAWKCxrYk9yTo8z127xsSzsSePQZlxt97tbQay74n//NDFK4ovFMgyhKSjoWtHTbdGw/RDvQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/cookie": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-11.0.2.tgz", + "integrity": "sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "cookie": "^1.0.0", + "fastify-plugin": "^5.0.0" + } + }, + "node_modules/@fastify/env": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@fastify/env/-/env-5.0.2.tgz", + "integrity": "sha512-4m/jHS3s/G/DBJVODob9sxGUei/Ij8JFbA2PYqBfoihTm+Qqae2xD9xhez68UFZu1d4SNJPIb6uAOwbNvRYw+A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "env-schema": "^6.0.0", + "fastify-plugin": "^5.0.0" + } + }, + "node_modules/@fastify/error": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.1.0.tgz", + "integrity": "sha512-KeFcciOr1eo/YvIXHP65S94jfEEqn1RxTRBT1aJaHxY5FK0/GDXYozsQMMWlZoHgi8i0s+YtrLsgj/JkUUjSkQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz", + "integrity": "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "fast-json-stringify": "^6.0.0" + } + }, + "node_modules/@fastify/forwarded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz", + "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", + "license": "MIT" + }, + "node_modules/@fastify/http-proxy": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@fastify/http-proxy/-/http-proxy-11.1.2.tgz", + "integrity": "sha512-DDceCz1DIEa4vUsQ0DhMqwiZdZUCG0RByY51k0BndBLo7bWpO3QuzLpZTS7Hr6Bp6r82SRmAinM0uPpQse1zqA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/reply-from": "^12.0.2", + "fast-querystring": "^1.1.2", + "fastify-plugin": "^5.0.1", + "ws": "^8.18.0" + } + }, + "node_modules/@fastify/merge-json-schemas": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", + "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@fastify/proxy-addr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", + "integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==", + "license": "MIT", + "dependencies": { + "@fastify/forwarded": "^3.0.0", + "ipaddr.js": "^2.1.0" + } + }, + "node_modules/@fastify/reply-from": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@fastify/reply-from/-/reply-from-12.1.0.tgz", + "integrity": "sha512-5SvMj0NnAAhno/MIv+bErCfzYxcqTueqUxCyub/i+68/CqYWroYg0/p8D0ZhrSQcDigowaKk+MEQSoLjbGwZ+g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "end-of-stream": "^1.4.4", + "fast-content-type-parse": "^2.0.0", + "fast-querystring": "^1.1.2", + "fastify-plugin": "^5.0.1", + "toad-cache": "^3.7.0", + "undici": "^7.0.0" + } + }, + "node_modules/@fastify/secure-session": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@fastify/secure-session/-/secure-session-8.2.0.tgz", + "integrity": "sha512-E1linEHVV86c0Gt+ohujcuRsCeedhD2M3X5+a2aU9Ln0YDC0bbuA7bE6QQzf/HAacOpt9+CJqV5NqdlQr9ui0A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/cookie": "^11.0.1", + "fastify-plugin": "^5.0.0", + "sodium-native": "^4.0.10" + }, + "bin": { + "secure-session": "genkey.js" + } + }, + "node_modules/@fastify/sensible": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@fastify/sensible/-/sensible-6.0.3.tgz", + "integrity": "sha512-Iyn8698hp/e5+v8SNBBruTa7UfrMEP52R16dc9jMpqSyEcPsvWFQo+R6WwHCUnJiLIsuci2ZoEZ7ilrSSCPIVg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "dequal": "^2.0.3", + "fastify-plugin": "^5.0.0", + "forwarded": "^0.2.0", + "http-errors": "^2.0.0", + "type-is": "^1.6.18", + "vary": "^1.1.2" + } + }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": 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==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/avvio": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.1.0.tgz", + "integrity": "sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==", + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "fastq": "^1.17.1" + } + }, + "node_modules/bare-addon-resolve": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.9.4.tgz", + "integrity": "sha512-unn6Vy/Yke6F99vg/7tcrvM2KUvIhTNniaSqDbam4AWkd4NhvDVSrQiRYVlNzUV2P7SPobkCK7JFVxrJk9btCg==", + "license": "Apache-2.0", + "dependencies": { + "bare-module-resolve": "^1.10.0", + "bare-semver": "^1.0.0" + }, + "peerDependencies": { + "bare-url": "*" + }, + "peerDependenciesMeta": { + "bare-url": { + "optional": true + } + } + }, + "node_modules/bare-module-resolve": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.10.2.tgz", + "integrity": "sha512-C9COe/GhWfVXKytW3DElTkiBU+Gb2OXeaVkdGdRB/lp26TVLESHkTGS876iceAGdvtPgohfp9nX8vXHGvN3++Q==", + "license": "Apache-2.0", + "dependencies": { + "bare-semver": "^1.0.0" + }, + "peerDependencies": { + "bare-url": "*" + }, + "peerDependenciesMeta": { + "bare-url": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", + "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-semver": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.1.tgz", + "integrity": "sha512-UtggzHLiTrmFOC/ogQ+Hy7VfoKoIwrP1UFcYtTxoCUdLtsIErT8+SWtOC2DH/snT9h+xDrcBEPcwKei1mzemgg==", + "license": "Apache-2.0" + }, + "node_modules/bare-url": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.1.6.tgz", + "integrity": "sha512-FgjDeR+/yDH34By4I0qB5NxAoWv7dOTYcOXwn73kr+c93HyC2lU6tnjifqUe33LKMJcDyCYPQjEAqgOQiXkE2Q==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-schema": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/env-schema/-/env-schema-6.0.1.tgz", + "integrity": "sha512-WRD40Q25pP4NUbI3g3CNU5PPzcaiX7YYcPwiCZlfR4qGsKmTlckRixgHww0/fOXiXSNKA87pwshzq0ULTK/48A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ajv": "^8.12.0", + "dotenv": "^16.4.5", + "dotenv-expand": "10.0.0" + } + }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/fast-json-stringify": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-6.0.1.tgz", + "integrity": "sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/merge-json-schemas": "^0.2.0", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^3.0.0", + "json-schema-ref-resolver": "^2.0.0", + "rfdc": "^1.2.0" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastify": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.3.2.tgz", + "integrity": "sha512-AIPqBgtqBAwkOkrnwesEE+dOyU30dQ4kh7udxeGVR05CRGwubZx+p2H8P0C4cRnQT0+EPK4VGea2DTL2RtWttg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/ajv-compiler": "^4.0.0", + "@fastify/error": "^4.0.0", + "@fastify/fast-json-stringify-compiler": "^5.0.0", + "@fastify/proxy-addr": "^5.0.0", + "abstract-logging": "^2.0.1", + "avvio": "^9.0.0", + "fast-json-stringify": "^6.0.0", + "find-my-way": "^9.0.0", + "light-my-request": "^6.0.0", + "pino": "^9.0.0", + "process-warning": "^5.0.0", + "rfdc": "^1.3.1", + "secure-json-parse": "^4.0.0", + "semver": "^7.6.0", + "toad-cache": "^3.7.0" + } + }, + "node_modules/fastify-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.0.1.tgz", + "integrity": "sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==", + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/find-my-way": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.3.0.tgz", + "integrity": "sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^5.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/json-schema-ref-resolver": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz", + "integrity": "sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/light-my-request": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", + "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "cookie": "^1.0.1", + "process-warning": "^4.0.0", + "set-cookie-parser": "^2.6.0" + } + }, + "node_modules/light-my-request/node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pino": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", + "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" + }, + "node_modules/pino/node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/require-addon": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.1.0.tgz", + "integrity": "sha512-KbXAD5q2+v1GJnkzd8zzbOxchTkStSyJZ9QwoCq3QwEXAaIlG3wDYRZGzVD357jmwaGY7hr5VaoEAL0BkF0Kvg==", + "license": "Apache-2.0", + "dependencies": { + "bare-addon-resolve": "^1.3.0", + "bare-url": "^2.1.0" + }, + "engines": { + "bare": ">=1.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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ret": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz", + "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/safe-regex2": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.0.0.tgz", + "integrity": "sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ret": "~0.5.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz", + "integrity": "sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sodium-native": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.3.tgz", + "integrity": "sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==", + "license": "MIT", + "dependencies": { + "require-addon": "^1.1.0" + } + }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.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==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.8.0.tgz", + "integrity": "sha512-vFv1GA99b7eKO1HG/4RPu2Is3FBTWBrmzqzO0mz+rLxN3yXkE4mqRcb8g8fHxzX4blEysrNZLqg5RbJLqX5buA==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 00000000..28325d39 --- /dev/null +++ b/server/package.json @@ -0,0 +1,25 @@ +{ + "name": "ui-bff", + "description": "Backend for frontend (BFF) for the UI.", + "version": "1.0.0", + "type": "module", + "engines": { + "node": "^22.0.0", + "npm": "^11.0.0" + }, + "main": "app.js", + "scripts": { + "start": "fastify start -l info -p 3001 app.js", + "dev": "fastify start -w -l info -p 3001 -P app.js" + }, + "dependencies": { + "@fastify/autoload": "^6.3.0", + "@fastify/cookie": "^11.0.2", + "@fastify/env": "^5.0.2", + "@fastify/http-proxy": "^11.1.2", + "@fastify/secure-session": "^8.2.0", + "@fastify/sensible": "^6.0.3", + "fastify": "^5.3.2", + "fastify-plugin": "^5.0.1" + } +} diff --git a/server/plugins/auth-utils.js b/server/plugins/auth-utils.js new file mode 100644 index 00000000..a90689ad --- /dev/null +++ b/server/plugins/auth-utils.js @@ -0,0 +1,176 @@ +import fp from "fastify-plugin"; +import crypto from "node:crypto"; + + +export class AuthenticationError extends Error { + constructor(message) { + super(message); + this.name = this.constructor.name; + this.code = "ERR_AUTHENTICATION"; + Error.captureStackTrace(this, this.constructor); + } +} + +async function getRemoteOpenIdConfiguration(issuerBaseUrl) { + const url = new URL("/.well-known/openid-configuration", issuerBaseUrl).toString(); + const res = await fetch(url); + if (!res.ok) { + throw new AuthenticationError(`OIDC discovery failed: ${res.status} ${res.statusText}`); + } + return res.json(); +} + + +async function authUtilsPlugin(fastify) { + fastify.decorate("discoverIssuerConfiguration", async (issuerBaseUrl) => { + fastify.log.info({ issuer: issuerBaseUrl }, "Discovering OpenId configuration."); + + const remoteConfiguration = await getRemoteOpenIdConfiguration(issuerBaseUrl); + + const requiredConfiguration = { + authorizationEndpoint: remoteConfiguration.authorization_endpoint, + tokenEndpoint: remoteConfiguration.token_endpoint, + }; + + fastify.log.info({ issuer: issuerBaseUrl, requiredConfiguration }, "OpenId configuration discovered."); + + return requiredConfiguration; + }); + + fastify.decorate("refreshAuthTokens", async (currentRefreshToken, oidcConfig, tokenEndpoint) => { + fastify.log.info("Refreshing tokens."); + + const { clientId, scopes } = oidcConfig; + + const body = new URLSearchParams({ + grant_type: "refresh_token", + refresh_token: currentRefreshToken, + client_id: clientId, + scope: scopes, + }); + + const response = await fetch(tokenEndpoint, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "Accept": "application/json", + }, + body: body.toString(), + }); + const responseBodyText = await response.text(); + if (!response.ok) { + fastify.log.error({ status: response.status, idpResponseBody: responseBodyText }, "Token refresh failed."); + throw new AuthenticationError("Token refresh failed."); + } + + const newTokens = JSON.parse(responseBodyText); + fastify.log.info("Token refresh successful; received new tokens."); + + return { + accessToken: newTokens.access_token, + refreshToken: newTokens.refresh_token, + expiresIn: newTokens.expires_in, + }; + }); + + fastify.decorate("prepareOidcLoginRedirect", (request, oidcConfig, authorizationEndpoint) => { + request.log.info("Preparing OIDC login redirect."); + + const { clientId, redirectUri, scopes } = oidcConfig; + + const state = crypto.randomBytes(16).toString("hex"); + const codeVerifier = crypto.randomBytes(32).toString("base64url"); + const codeChallenge = crypto.createHash("sha256").update(codeVerifier).digest("base64url"); + + request.session.set("oauthState", state); + request.session.set("codeVerifier", codeVerifier); + request.log.info({ + stateSet: Boolean(state), + verifierSet: Boolean(codeVerifier), + }, "OAuth state and code verifier set in session."); + + const url = new URL(authorizationEndpoint); + url.searchParams.set("response_type", "code"); + url.searchParams.set("client_id", clientId); + url.searchParams.set("redirect_uri", redirectUri); + url.searchParams.set("scope", scopes); + url.searchParams.set("state", state); + url.searchParams.set("code_challenge", codeChallenge); + url.searchParams.set("code_challenge_method", "S256"); + + request.log.info("Prepared OIDC login redirect."); + + return url.toString(); + }); + + fastify.decorate("handleOidcCallback", async (request, oidcConfig, tokenEndpoint) => { + request.log.info("Handling OIDC callback to retrieve the tokens."); + + const { clientId, redirectUri } = oidcConfig; + + const { code, state } = request.query; + if (!code) { + request.log.error("Missing authorization code in callback."); + throw new AuthenticationError("Missing code in callback."); + } + if (state !== request.session.get("oauthState")) { + request.log.error("Invalid state in callback."); + throw new AuthenticationError("Invalid state in callback."); + } + + const body = new URLSearchParams({ + grant_type: "authorization_code", + code, + redirect_uri: redirectUri, + client_id: clientId, + code_verifier: request.session.get("codeVerifier"), + }); + + const response = await fetch(tokenEndpoint, { + method: "POST", + headers: { "content-type": "application/x-www-form-urlencoded" }, + body, + }); + if (!response.ok) { + request.log.error({ status: response.status, body: await response.text() }, "Token exchange failed."); + throw new AuthenticationError("Token exchange failed."); + } + + const tokens = await response.json(); + + const result = { + accessToken: tokens.access_token, + refreshToken: tokens.refresh_token, + expiresAt: null, + userInfo: extractUserInfoFromIdToken(request, tokens.id_token), + }; + + if (tokens.expires_in && typeof tokens.expires_in === "number") { + const expiresAt = Date.now() + (tokens.expires_in * 1000); + result.expiresAt = expiresAt; + } + + request.log.info("OIDC callback succeeded; tokens retrieved."); + return result; + }); + +} + +function extractUserInfoFromIdToken(request, idToken) { + request.log.info("Extracting user info from ID token."); + + if (!idToken) { + request.log.warn("No ID token provided."); + return null; + } + + const payloadBase64 = idToken.split('.')[1]; + const decodedPayload = JSON.parse(Buffer.from(payloadBase64, 'base64').toString('utf8')); + + request.log.info("User info extracted from ID token."); + return { + email: decodedPayload.email, + } +} + +export default fp(authUtilsPlugin); diff --git a/server/plugins/http-proxy.js b/server/plugins/http-proxy.js new file mode 100644 index 00000000..f65f084d --- /dev/null +++ b/server/plugins/http-proxy.js @@ -0,0 +1,93 @@ +import fp from "fastify-plugin"; +import httpProxy from "@fastify/http-proxy"; +import { COOKIE_NAME_ONBOARDING } from "./secure-session.js"; +import { AuthenticationError } from "./auth-utils.js"; + +function proxyPlugin(fastify) { + const { API_BACKEND_URL } = fastify.config; + const { OIDC_CLIENT_ID, OIDC_SCOPES } = fastify.config; + + fastify.register(httpProxy, { + prefix: "/onboarding", + upstream: API_BACKEND_URL, + preHandler: async (request, reply) => { + request.log.info("Entering HTTP proxy preHandler."); + + // Check if there is an access token + const accessToken = request.session.get("accessToken"); + if (!accessToken) { + request.log.error("Missing access token."); + return reply.unauthorized("Missing access token."); + } + + // Check if the access token is expired or about to expire + const expiresAt = request.session.get("tokenExpiresAt"); + const now = Date.now(); + const REFRESH_BUFFER_SECONDS = 20; // to allow for network latency + if (!expiresAt || now < expiresAt - REFRESH_BUFFER_SECONDS) { + request.log.info("Access token is still valid; no refresh needed."); + return; + } + + request.log.info({ expiresAt: new Date(expiresAt).toISOString() }, "Access token is expired or about to expire; attempting refresh."); + + // Check if there is a refresh token + const refreshToken = request.session.get("refreshToken"); + if (!refreshToken) { + request.log.error("Missing refresh token; deleting session."); + request.session.delete(); + reply.clearCookie(COOKIE_NAME_ONBOARDING, { path: "/" }); + return reply.unauthorized("Session expired without token refresh capability."); + } + + // Attempt to refresh the tokens + try { + const issuerConfiguration = fastify.issuerConfiguration; + + const refreshedTokenData = await fastify.refreshAuthTokens(refreshToken, { + clientId: OIDC_CLIENT_ID, + scopes: OIDC_SCOPES, + }, issuerConfiguration.tokenEndpoint); + if (!refreshedTokenData || !refreshedTokenData.accessToken) { + request.log.error("Token refresh failed (no access token); deleting session."); + request.session.delete(); + reply.clearCookie(COOKIE_NAME_ONBOARDING, { path: "/" }); + return reply.unauthorized("Session expired and token refresh failed."); + } + + request.log.info("Token refresh successful; updating the session."); + + request.session.set("accessToken", refreshedTokenData.accessToken); + if (refreshedTokenData.refreshToken) { + request.session.set("refreshToken", refreshedTokenData.refreshToken); + } else { + request.session.delete("refreshToken"); + } + if (refreshedTokenData.expiresIn) { + const newExpiresAt = Date.now() + (refreshedTokenData.expiresIn * 1000); + request.session.set("tokenExpiresAt", newExpiresAt); + } else { + request.session.delete("tokenExpiresAt"); + } + + request.log.info("Token refresh successful and session updated; continuing with the HTTP request."); + } catch (error) { + if (error instanceof AuthenticationError) { + request.log.error("AuthenticationError during token refresh: %s", error); + return reply.unauthorized("Error during token refresh."); + } else { + throw error; + } + } + }, + replyOptions: { + rewriteRequestHeaders: (req, headers) => ({ + ...headers, + authorization: req.session.get("accessToken"), + "X-mcp-authorization": req.session.get("accessToken"), // no support for different MCP IdPs at the moment + }), + }, + }); +} + +export default fp(proxyPlugin); diff --git a/server/plugins/secure-session.js b/server/plugins/secure-session.js new file mode 100644 index 00000000..d9191408 --- /dev/null +++ b/server/plugins/secure-session.js @@ -0,0 +1,26 @@ +import secureSession from "@fastify/secure-session"; +import fp from "fastify-plugin"; +import fastifyCookie from "@fastify/cookie"; + + +export const COOKIE_NAME_ONBOARDING = "onboarding"; + +async function secureSessionPlugin(fastify) { + const { COOKIE_SECRET, NODE_ENV } = fastify.config; + + await fastify.register(fastifyCookie); + + fastify.register(secureSession, { + secret: Buffer.from(COOKIE_SECRET, "hex"), + cookieName: COOKIE_NAME_ONBOARDING, + cookie: { + path: "/", + httpOnly: true, + sameSite: "lax", + secure: NODE_ENV === "production", + maxAge: 60 * 60 * 24 * 7, // 7 days + }, + }); +} + +export default fp(secureSessionPlugin); diff --git a/server/plugins/sensible.js b/server/plugins/sensible.js new file mode 100644 index 00000000..9f9a1e63 --- /dev/null +++ b/server/plugins/sensible.js @@ -0,0 +1,8 @@ +import fp from "fastify-plugin"; +import sensible from "@fastify/sensible"; + +function sensiblePlugin(fastify) { + fastify.register(sensible, { errorHandler: false }); +} + +export default fp(sensiblePlugin); diff --git a/server/routes/auth.js b/server/routes/auth.js new file mode 100644 index 00000000..4536f383 --- /dev/null +++ b/server/routes/auth.js @@ -0,0 +1,74 @@ +import fp from "fastify-plugin"; +import { COOKIE_NAME_ONBOARDING } from "../plugins/secure-session.js"; +import { AuthenticationError } from "../plugins/auth-utils.js"; + + +async function authPlugin(fastify) { + const { OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_REDIRECT_URI, OIDC_SCOPES, POST_LOGIN_REDIRECT } = fastify.config; + + + // Make onboarding issuer configuration globally available + const issuerConfiguration = await fastify.discoverIssuerConfiguration(OIDC_ISSUER); + fastify.decorate("issuerConfiguration", issuerConfiguration); + + + fastify.get("/auth/login", async (req, reply) => { + const redirectUri = fastify.prepareOidcLoginRedirect(req, { + clientId: OIDC_CLIENT_ID, + redirectUri: OIDC_REDIRECT_URI, + scopes: OIDC_SCOPES, + }, issuerConfiguration.authorizationEndpoint); + + reply.redirect(redirectUri); + }); + + + fastify.get("/auth/callback", async (req, reply) => { + try { + const callbackResult = await fastify.handleOidcCallback(req, { + clientId: OIDC_CLIENT_ID, + redirectUri: OIDC_REDIRECT_URI, + }, issuerConfiguration.tokenEndpoint); + + req.session.set("accessToken", callbackResult.accessToken); + req.session.set("refreshToken", callbackResult.refreshToken); + req.session.set("userInfo", callbackResult.userInfo); + + if (callbackResult.expiresAt) { + req.session.set("tokenExpiresAt", callbackResult.expiresAt); + } else { + req.session.delete("tokenExpiresAt"); + } + } catch (error) { + if (error instanceof AuthenticationError) { + req.log.error("AuthenticationError during OIDC callback: %s", error); + return reply.serviceUnavailable("Error during OIDC callback."); + } else { + throw error; + } + } + + reply.redirect(POST_LOGIN_REDIRECT); + }); + + + fastify.get("/auth/status", async (req, reply) => { + const isAuthenticated = Boolean(req.session.get("accessToken")); + reply.send({ isAuthenticated }); + }); + + + fastify.get("/auth/user", async (req, reply) => { + reply.send(req.session.get("userInfo")); + }); + + + fastify.get("/auth/logout", async (_req, reply) => { + // TODO: Idp sign out flow + //_req.session.delete(); // remove payload + reply.clearCookie(COOKIE_NAME_ONBOARDING, { path: "/" }); + reply.send({ message: "Logged out" }); + }); +} + +export default fp(authPlugin); diff --git a/server/routes/root.js b/server/routes/root.js new file mode 100644 index 00000000..d064521c --- /dev/null +++ b/server/routes/root.js @@ -0,0 +1,9 @@ +import fp from "fastify-plugin"; + +function rootRoutes(fastify) { + fastify.get("/", async (_request, reply) => { + reply.code(200).send({ status: "ok", timestamp: new Date().toISOString() }); + }); +} + +export default fp(rootRoutes); diff --git a/src/App.tsx b/src/App.tsx index 1d9177d6..9f76e4b5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,5 @@ import AppRouter from './AppRouter'; -import { useAuth } from 'react-oidc-context'; -import LoginView from './views/Login'; +import { useAuth } from './spaces/onboarding/auth/AuthContext.tsx'; import '@ui5/webcomponents-icons/dist/AllIcons.d.ts'; import { useEffect, useState } from 'react'; import { SessionExpiringDialog } from './components/Dialogs/SessionExpiringDialog.tsx'; @@ -13,34 +12,6 @@ function App() { useState(false); const { t } = useTranslation(); - const [hasActiveSession, setHasActiveSession] = useState( - auth.isAuthenticated, - ); - - useEffect(() => { - setHasActiveSession(auth.isAuthenticated); - }, [auth.isAuthenticated]); - - useEffect(() => { - const unregisterAccessTokenExpiring = auth.events.addAccessTokenExpiring( - () => { - setDialogSessionExpiringIsOpen(true); - }, - ); - const unregisterAccessTokenExpired = auth.events.addAccessTokenExpired( - () => { - console.error('access token expired, show login view'); - setDialogSessionExpiringIsOpen(false); - setHasActiveSession(false); - }, - ); - - return () => { - unregisterAccessTokenExpiring(); - unregisterAccessTokenExpired(); - }; - }, [auth.events]); - const frontendConfig = useFrontendConfig(); useEffect(() => { @@ -53,10 +24,11 @@ function App() { return
{t('App.loading')}
; } - if (!hasActiveSession) { + if (!auth.isAuthenticated) { return ( <> - + {/****/} + ); } @@ -67,6 +39,10 @@ function App() { isOpen={dialogSessionExpiringIsOpen} setIsOpen={setDialogSessionExpiringIsOpen} /> +
+ {auth.isAuthenticated ? 'AUTHED' : 'NOT AUTHED'} + +
); diff --git a/src/context/FrontendConfigContext.tsx b/src/context/FrontendConfigContext.tsx index 567d8cd2..967f83c8 100644 --- a/src/context/FrontendConfigContext.tsx +++ b/src/context/FrontendConfigContext.tsx @@ -61,7 +61,6 @@ const OidcConfigSchema = z.object({ export type OIDCConfig = z.infer; const FrontendConfigSchema = z.object({ - backendUrl: z.string(), gatewayUrl: z.string(), documentationBaseUrl: z.string(), githubBaseUrl: z.string(), diff --git a/src/lib/api/fetch.ts b/src/lib/api/fetch.ts index 65c675da..bd45c89a 100644 --- a/src/lib/api/fetch.ts +++ b/src/lib/api/fetch.ts @@ -27,7 +27,6 @@ export const fetchApiServer = async ( } else { headers[contentTypeHeader] = 'application/merge-patch+json'; } - headers[authHeader] = config.crateAuthorization; // Set the jq header to do a jq transformation on the proxy server. if (jq) headers[jqHeader] = jq; @@ -39,18 +38,21 @@ export const fetchApiServer = async ( headers[workspaceNameHeader] = config.mcpConfig.workspaceName; headers[mcpNameHeader] = config.mcpConfig.controlPlaneName; headers[contextHeader] = config.mcpConfig.contextName; - headers[mcpAuthHeader] = config.mcpConfig.mcpAuthorization; } else { headers[useCrateClusterHeader] = 'true'; } - const res = await fetch(`${config.apiProxyUrl}${path}`, { + const res = await fetch(`/api/onboarding${path}`, { headers, method: httpMethod, body, }); if (!res.ok) { + if (res.status === 401) { + // Unauthorized, redirect to the login page + window.location.href = `/api/auth/login`; + } const error = new APIError( 'An error occurred while fetching the data.', res.status, diff --git a/src/main.tsx b/src/main.tsx index 5dbbee76..900c23d2 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -17,6 +17,7 @@ import { ApolloClientProvider } from './spaces/onboarding/services/ApolloClientP import { IllustratedBanner } from './components/Ui/IllustratedBanner/IllustratedBanner.tsx'; import { useTranslation } from 'react-i18next'; import IllustrationMessageType from '@ui5/webcomponents-fiori/dist/types/IllustrationMessageType.js'; +import { AuthProvider } from './spaces/onboarding/auth/AuthContext.tsx'; const ErrorFallback = ({ error }: FallbackProps) => { const { t } = useTranslation(); @@ -37,26 +38,28 @@ root.render( {}}> }> - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + , diff --git a/src/spaces/onboarding/auth/AuthContext.tsx b/src/spaces/onboarding/auth/AuthContext.tsx new file mode 100644 index 00000000..c9b2acbd --- /dev/null +++ b/src/spaces/onboarding/auth/AuthContext.tsx @@ -0,0 +1,105 @@ +import { + createContext, + useContext, + useState, + useEffect, + ReactNode, +} from 'react'; + +interface AuthContextType { + isAuthenticated: boolean; + isLoading: boolean; + error: Error | null; + login: () => void; + logout: () => Promise; +} + +const AuthContext = createContext(null); + +export function AuthProvider({ children }: { children: ReactNode }) { + const [isAuthenticated, setIsAuthenticated] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + // Handle the redirect from the IdP + useEffect(() => { + const params = new URLSearchParams(location.search); + const code = params.get('code'); + const state = params.get('state'); + const iss = params.get('iss'); + const error = params.get('error'); + const errorDescription = params.get('error_description'); + + if (error) { + throw new Error(`Error from IdP: ${error} – ${errorDescription}`); + } + + if (code && state) { + // Construct the URL to forward to the BFF + const forwardUrl = new URL('/api/auth/callback', window.location.origin); + forwardUrl.searchParams.append('code', code); + forwardUrl.searchParams.append('state', state); + if (iss) { + forwardUrl.searchParams.append('iss', iss); + } + window.location.href = forwardUrl.toString(); + } + }, [location]); + + // Check the authentication status when the component mounts + useEffect(() => { + void checkAuthStatus(); + }, []); + + async function checkAuthStatus() { + try { + const response = await fetch('/api/auth/status'); + + if (!response.ok) { + throw new Error('Authentication check failed.'); + } + + const body = await response.json(); + setIsAuthenticated(body.isAuthenticated); + } catch (err) { + setError(err instanceof Error ? err : new Error('Authentication error.')); + setIsAuthenticated(false); + } finally { + setIsLoading(false); + } + } + + const login = () => { + window.location.href = `/api/auth/login`; + }; + + const logout = async () => { + try { + const response = await fetch('/api/auth/logout'); + + if (!response.ok) { + throw new Error('Logout failed'); + } + + await checkAuthStatus(); + } catch (err) { + setError(err instanceof Error ? err : new Error('Logout error.')); + } + }; + + return ( + + {children} + + ); +} + +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) { + throw new Error('useAuth must be used within an AuthProvider.'); + } + return context; +}; diff --git a/src/utils/testing.ts b/src/utils/testing.ts index 4685b2f2..fbd3e4cb 100644 --- a/src/utils/testing.ts +++ b/src/utils/testing.ts @@ -4,7 +4,6 @@ import { Landscape } from '../context/FrontendConfigContext.tsx'; export const isInTestingMode: boolean = !!window.Cypress; const documentationBaseUrl = 'http://localhost:3000'; export const mockedFrontendConfig = { - backendUrl: 'http://localhost:3000', landscape: Landscape.Local, documentationBaseUrl: 'http://localhost:3000', links: new LinkCreator(documentationBaseUrl), diff --git a/vite.config.ts b/vite.config.ts index 627a3196..b0762169 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,4 +4,16 @@ import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], + server: { + port: 5173, + strictPort: true, + proxy: { + '/api': { + target: 'http://localhost:3001', + changeOrigin: true, + ws: true, + rewrite: (path) => path.replace(/^\/api/, ''), + }, + }, + }, }); From a6d216346600de3a4f62fc52182ec06b1cc6bb19 Mon Sep 17 00:00:00 2001 From: Andreas Kienle Date: Tue, 13 May 2025 14:40:42 +0200 Subject: [PATCH 2/9] Restore backendUrl --- frontend-config.json | 1 + src/context/FrontendConfigContext.tsx | 1 + src/lib/api/fetch.ts | 2 -- src/utils/testing.ts | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend-config.json b/frontend-config.json index 86f73dda..5d421989 100644 --- a/frontend-config.json +++ b/frontend-config.json @@ -1,4 +1,5 @@ { + "backendUrl": "http://localhost:3000", "gatewayUrl": "https://gateway.ui.dev-core.mcpd.shoot.canary.k8s-hana.ondemand.com/kubernetes/graphql", "landscape": "LOCAL", "documentationBaseUrl": "http://localhost:3000", diff --git a/src/context/FrontendConfigContext.tsx b/src/context/FrontendConfigContext.tsx index 967f83c8..567d8cd2 100644 --- a/src/context/FrontendConfigContext.tsx +++ b/src/context/FrontendConfigContext.tsx @@ -61,6 +61,7 @@ const OidcConfigSchema = z.object({ export type OIDCConfig = z.infer; const FrontendConfigSchema = z.object({ + backendUrl: z.string(), gatewayUrl: z.string(), documentationBaseUrl: z.string(), githubBaseUrl: z.string(), diff --git a/src/lib/api/fetch.ts b/src/lib/api/fetch.ts index bd45c89a..43faca74 100644 --- a/src/lib/api/fetch.ts +++ b/src/lib/api/fetch.ts @@ -5,10 +5,8 @@ const useCrateClusterHeader = 'X-use-crate'; const projectNameHeader = 'X-project'; const workspaceNameHeader = 'X-workspace'; const mcpNameHeader = 'X-mcp'; -const mcpAuthHeader = 'X-mcp-authorization'; const contextHeader = 'X-context'; const jqHeader = 'X-jq'; -const authHeader = 'Authorization'; const contentTypeHeader = 'Content-Type'; // fetchApiServer is a wrapper around fetch that adds the necessary headers for the Crate API or the MCP API server. diff --git a/src/utils/testing.ts b/src/utils/testing.ts index fbd3e4cb..4685b2f2 100644 --- a/src/utils/testing.ts +++ b/src/utils/testing.ts @@ -4,6 +4,7 @@ import { Landscape } from '../context/FrontendConfigContext.tsx'; export const isInTestingMode: boolean = !!window.Cypress; const documentationBaseUrl = 'http://localhost:3000'; export const mockedFrontendConfig = { + backendUrl: 'http://localhost:3000', landscape: Landscape.Local, documentationBaseUrl: 'http://localhost:3000', links: new LinkCreator(documentationBaseUrl), From f84f3643e7c84977698e9a17da9e427d4891bfb6 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Thu, 15 May 2025 13:10:33 +0200 Subject: [PATCH 3/9] working fastify unified server --- package-lock.json | 1060 ++++++++++++++++++++++++++++++++++++-- package.json | 3 + server.js | 37 ++ server/package-lock.json | 8 +- server/package.json | 2 +- tsconfig.json | 3 +- tsconfig.node.json | 7 +- 7 files changed, 1077 insertions(+), 43 deletions(-) create mode 100644 server.js diff --git a/package-lock.json b/package-lock.json index 0c7e8361..9b979b76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,15 @@ "version": "0.0.0", "dependencies": { "@apollo/client": "^3.13.6", + "@fastify/static": "^8.1.1", "@hookform/resolvers": "^5.0.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", "@ui5/webcomponents-icons": "^2.7.2", "@ui5/webcomponents-react": "^2.7.2", "clsx": "^2.1.1", + "dotenv": "^16.5.0", + "fastify": "^5.3.3", "graphql": "^16.10.0", "graphql-config": "^5.1.3", "i18next": "^25.0.0", @@ -1169,12 +1172,188 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@fastify/accept-negotiator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-2.0.1.tgz", + "integrity": "sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/ajv-compiler": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.2.tgz", + "integrity": "sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^3.0.0" + } + }, + "node_modules/@fastify/ajv-compiler/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.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==", + "license": "MIT" + }, "node_modules/@fastify/busboy": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==", "license": "MIT" }, + "node_modules/@fastify/error": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.1.0.tgz", + "integrity": "sha512-KeFcciOr1eo/YvIXHP65S94jfEEqn1RxTRBT1aJaHxY5FK0/GDXYozsQMMWlZoHgi8i0s+YtrLsgj/JkUUjSkQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz", + "integrity": "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "fast-json-stringify": "^6.0.0" + } + }, + "node_modules/@fastify/forwarded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz", + "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", + "license": "MIT" + }, + "node_modules/@fastify/merge-json-schemas": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", + "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@fastify/proxy-addr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", + "integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==", + "license": "MIT", + "dependencies": { + "@fastify/forwarded": "^3.0.0", + "ipaddr.js": "^2.1.0" + } + }, + "node_modules/@fastify/send": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@fastify/send/-/send-3.3.1.tgz", + "integrity": "sha512-6pofeVwaHN+E/MAofCwDqkWUliE3i++jlD0VH/LOfU8TJlCkMUSgKvA9bawDdVXxjve7XrdYMyDmkiYaoGWEtA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "escape-html": "~1.0.3", + "fast-decode-uri-component": "^1.0.1", + "http-errors": "^2.0.0", + "mime": "^3" + } + }, + "node_modules/@fastify/static": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@fastify/static/-/static-8.1.1.tgz", + "integrity": "sha512-TW9eyVHJLytZNpBlSIqd0bl1giJkEaRaPZG+5AT3L/OBKq9U8D7g/OYmc2NPQZnzPURGhMt3IAWuyVkvd2nOkQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/accept-negotiator": "^2.0.0", + "@fastify/send": "^3.2.0", + "content-disposition": "^0.5.4", + "fastify-plugin": "^5.0.0", + "fastq": "^1.17.1", + "glob": "^11.0.0" + } + }, "node_modules/@graphql-codegen/add": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz", @@ -2104,6 +2283,96 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", @@ -2163,6 +2432,15 @@ "integrity": "sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==", "license": "BSD-3-Clause" }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", @@ -3568,6 +3846,12 @@ "license": "(Unlicense OR Apache-2.0)", "optional": true }, + "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==", + "license": "MIT" + }, "node_modules/acorn": { "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", @@ -3632,6 +3916,45 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.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==", + "license": "MIT" + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -3662,7 +3985,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3672,7 +3994,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -3966,6 +4287,15 @@ "node": ">= 4.0.0" } }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/auto-bind": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", @@ -3995,6 +4325,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/avvio": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.1.0.tgz", + "integrity": "sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==", + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "fastq": "^1.17.1" + } + }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -4578,7 +4918,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -4591,7 +4930,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -4670,6 +5008,18 @@ "upper-case": "^2.0.2" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4745,7 +5095,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5085,6 +5434,15 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/dependency-graph": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", @@ -5154,7 +5512,6 @@ "version": "16.5.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -5187,6 +5544,12 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -5209,7 +5572,6 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, "license": "MIT" }, "node_modules/end-of-stream": { @@ -5470,6 +5832,12 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -6082,11 +6450,16 @@ ], "license": "MIT" }, + "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==", + "license": "MIT" + }, "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, "license": "MIT" }, "node_modules/fast-diff": { @@ -6131,19 +6504,150 @@ "dev": true, "license": "MIT" }, - "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-json-stringify": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-6.0.1.tgz", + "integrity": "sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", - "peer": true - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "license": "ISC", + "dependencies": { + "@fastify/merge-json-schemas": "^0.2.0", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^3.0.0", + "json-schema-ref-resolver": "^2.0.0", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.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==", + "license": "MIT" + }, + "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, + "license": "MIT", + "peer": 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==", + "license": "MIT", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastify": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.3.3.tgz", + "integrity": "sha512-nCBiBCw9q6jPx+JJNVgO8JVnTXeUyrGcyTKPQikRkA/PanrFcOIo4R+ZnLeOLPZPGgzjomqfVarzE0kYx7qWiQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/ajv-compiler": "^4.0.0", + "@fastify/error": "^4.0.0", + "@fastify/fast-json-stringify-compiler": "^5.0.0", + "@fastify/proxy-addr": "^5.0.0", + "abstract-logging": "^2.0.1", + "avvio": "^9.0.0", + "fast-json-stringify": "^6.0.0", + "find-my-way": "^9.0.0", + "light-my-request": "^6.0.0", + "pino": "^9.0.0", + "process-warning": "^5.0.0", + "rfdc": "^1.3.1", + "secure-json-parse": "^4.0.0", + "semver": "^7.6.0", + "toad-cache": "^3.7.0" + } + }, + "node_modules/fastify-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.0.1.tgz", + "integrity": "sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==", + "license": "MIT" + }, + "node_modules/fastify/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -6279,6 +6783,20 @@ "node": ">=8" } }, + "node_modules/find-my-way": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.3.0.tgz", + "integrity": "sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^5.0.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -6336,6 +6854,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -6580,6 +7126,29 @@ "assert-plus": "^1.0.0" } }, + "node_modules/glob": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", + "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -6594,6 +7163,30 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -6995,6 +7588,22 @@ "void-elements": "3.1.0" } }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -7195,7 +7804,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -7260,6 +7868,15 @@ "loose-envify": "^1.0.0" } }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -7501,7 +8118,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7869,7 +8485,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/isomorphic-ws": { @@ -7906,6 +8521,21 @@ "node": ">= 0.4" } }, + "node_modules/jackspeak": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", + "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/javascript-time-ago": { "version": "2.5.11", "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.5.11.tgz", @@ -7994,6 +8624,25 @@ "dev": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, + "node_modules/json-schema-ref-resolver": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz", + "integrity": "sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.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", @@ -8153,6 +8802,43 @@ "node": ">= 0.8.0" } }, + "node_modules/light-my-request": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", + "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "cookie": "^1.0.1", + "process-warning": "^4.0.0", + "set-cookie-parser": "^2.6.0" + } + }, + "node_modules/light-my-request/node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -8442,6 +9128,18 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -8498,6 +9196,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -8786,6 +9493,15 @@ "node": ">=18" } }, + "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==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8950,6 +9666,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -9061,7 +9783,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9097,6 +9818,31 @@ "node": ">=0.10.0" } }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -9147,6 +9893,59 @@ "node": ">=0.10.0" } }, + "node_modules/pino": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", + "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" + }, + "node_modules/pino/node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -9258,6 +10057,22 @@ "node": ">= 0.6.0" } }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", @@ -9356,6 +10171,12 @@ ], "license": "MIT" }, + "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==", + "license": "MIT" + }, "node_modules/raf": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -9556,6 +10377,15 @@ "node": ">= 6" } }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -9709,6 +10539,15 @@ "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -9773,6 +10612,15 @@ "node": ">=8" } }, + "node_modules/ret": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz", + "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -9787,7 +10635,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, "license": "MIT" }, "node_modules/rollup": { @@ -9897,7 +10744,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -9949,6 +10795,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-regex2": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.0.0.tgz", + "integrity": "sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ret": "~0.5.0" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -10377,6 +11251,22 @@ "dev": true, "license": "MIT" }, + "node_modules/secure-json-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz", + "integrity": "sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -10461,11 +11351,16 @@ "dev": true, "license": "MIT" }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -10478,7 +11373,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10622,6 +11516,15 @@ "tslib": "^2.0.3" } }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -10642,6 +11545,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sponge-case": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz", @@ -10685,6 +11597,15 @@ "dev": true, "license": "MIT" }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10705,7 +11626,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -10716,11 +11636,31 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/string.prototype.includes": { @@ -10840,7 +11780,19 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -11012,6 +11964,15 @@ "url": "https://opencollective.com/synckit" } }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/throttleit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", @@ -11135,6 +12096,24 @@ "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==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/tough-cookie": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", @@ -11810,7 +12789,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -11937,6 +12915,24 @@ "node": ">=8" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 8c78546a..8fec6bd4 100644 --- a/package.json +++ b/package.json @@ -20,12 +20,15 @@ }, "dependencies": { "@apollo/client": "^3.13.6", + "@fastify/static": "^8.1.1", "@hookform/resolvers": "^5.0.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", "@ui5/webcomponents-icons": "^2.7.2", "@ui5/webcomponents-react": "^2.7.2", "clsx": "^2.1.1", + "dotenv": "^16.5.0", + "fastify": "^5.3.3", "graphql": "^16.10.0", "graphql-config": "^5.1.3", "i18next": "^25.0.0", diff --git a/server.js b/server.js new file mode 100644 index 00000000..cf0fb5be --- /dev/null +++ b/server.js @@ -0,0 +1,37 @@ +import Fastify from 'fastify'; +import FastifyStatic from '@fastify/static'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; +import dotenv from 'dotenv'; +import proxy from './server/app.js'; + +dotenv.config(); + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const fastify = Fastify({ + logger: true, +}); + +fastify.register(proxy, { + prefix: '/api', +}); + +fastify.register(FastifyStatic, { + root: path.join(__dirname, 'dist'), + // prefix: '/', // optional: default '/' + // constraints: { host: 'example.com' } // optional: default {} +}); + +fastify.listen( + { + port: 5173, + }, + function (err, address) { + if (err) { + fastify.log.error(err); + process.exit(1); + } + }, +); diff --git a/server/package-lock.json b/server/package-lock.json index acc43d04..f8f5a754 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -14,7 +14,7 @@ "@fastify/http-proxy": "^11.1.2", "@fastify/secure-session": "^8.2.0", "@fastify/sensible": "^6.0.3", - "fastify": "^5.3.2", + "fastify": "^5.3.3", "fastify-plugin": "^5.0.1" }, "engines": { @@ -565,9 +565,9 @@ "license": "BSD-3-Clause" }, "node_modules/fastify": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.3.2.tgz", - "integrity": "sha512-AIPqBgtqBAwkOkrnwesEE+dOyU30dQ4kh7udxeGVR05CRGwubZx+p2H8P0C4cRnQT0+EPK4VGea2DTL2RtWttg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.3.3.tgz", + "integrity": "sha512-nCBiBCw9q6jPx+JJNVgO8JVnTXeUyrGcyTKPQikRkA/PanrFcOIo4R+ZnLeOLPZPGgzjomqfVarzE0kYx7qWiQ==", "funding": [ { "type": "github", diff --git a/server/package.json b/server/package.json index 28325d39..8a0664bb 100644 --- a/server/package.json +++ b/server/package.json @@ -19,7 +19,7 @@ "@fastify/http-proxy": "^11.1.2", "@fastify/secure-session": "^8.2.0", "@fastify/sensible": "^6.0.3", - "fastify": "^5.3.2", + "fastify": "^5.3.3", "fastify-plugin": "^5.0.1" } } diff --git a/tsconfig.json b/tsconfig.json index ad91dd14..45167634 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,7 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", + "allowJs": true, /* Linting */ "strict": true, "noUnusedLocals": true, @@ -18,7 +19,7 @@ "noFallthroughCasesInSwitch": true, "types": ["node", "cypress"] }, - "include": ["src", "cypress.d.ts"], + "include": ["src", "cypress.d.ts", "server.js"], "references": [ { "path": "./tsconfig.node.json" diff --git a/tsconfig.node.json b/tsconfig.node.json index be3f1e9e..b4812afe 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -6,8 +6,5 @@ "moduleResolution": "bundler", "allowSyntheticDefaultImports": true }, - "include": [ - "vite.config.ts", - "cypress.config.ts" - ] -} \ No newline at end of file + "include": ["vite.config.ts", "cypress.config.ts"] +} From cbd5d5b6b72b5e2ed38b5e614997b1731512388d Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Thu, 15 May 2025 13:26:09 +0200 Subject: [PATCH 4/9] working server with fastify/vite --- package-lock.json | 321 ++++++++++++++++++++++++++++++++------------- package.json | 1 + server.js | 24 +++- tsconfig.json | 2 +- tsconfig.node.json | 2 +- vite.config.js | 10 ++ vite.config.ts | 19 --- 7 files changed, 260 insertions(+), 119 deletions(-) create mode 100644 vite.config.js delete mode 100644 vite.config.ts diff --git a/package-lock.json b/package-lock.json index 9b979b76..0c3320ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@apollo/client": "^3.13.6", "@fastify/static": "^8.1.1", + "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", @@ -464,7 +465,7 @@ "version": "2.2.5", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.5.tgz", "integrity": "sha512-/g5EzJifw5GF8aren8wZ/G5oMuPoGeS6MQD3ca8ddcvdXR5UELUfdTZITCGNhNXynY/AYl3Z4plmxdj/tRl/hQ==", - "dev": true, + "devOptional": true, "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@colors/colors": { @@ -611,7 +612,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -628,7 +628,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -645,7 +644,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -662,7 +660,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -679,7 +676,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -696,7 +692,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -713,7 +708,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -730,7 +724,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -747,7 +740,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -764,7 +756,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -781,7 +772,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -798,7 +788,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -815,7 +804,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -832,7 +820,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -849,7 +836,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -866,7 +852,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -883,7 +868,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -900,7 +884,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -917,7 +900,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -934,7 +916,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -951,7 +932,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -968,7 +948,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -985,7 +964,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1002,7 +980,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1019,7 +996,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1237,6 +1213,22 @@ "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==", "license": "MIT" }, + "node_modules/@fastify/deepmerge": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-3.1.0.tgz", + "integrity": "sha512-lCVONBQINyNhM6LLezB6+2afusgEYR4G8xenMsfe+AT+iZ7Ca6upM5Ha8UkZuYSnuMw3GWl/BiPXnLMi/gSxuQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/@fastify/error": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.1.0.tgz", @@ -1297,6 +1289,28 @@ "dequal": "^2.0.3" } }, + "node_modules/@fastify/middie": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@fastify/middie/-/middie-9.0.3.tgz", + "integrity": "sha512-7OYovKXp9UKYeVMcjcFLMcSpoMkmcZmfnG+eAvtdiatN35W7c+r9y1dRfpA+pfFVNuHGGqI3W+vDTmjvcfLcMA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "fastify-plugin": "^5.0.0", + "path-to-regexp": "^8.1.0", + "reusify": "^1.0.4" + } + }, "node_modules/@fastify/proxy-addr": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", @@ -1354,6 +1368,40 @@ "glob": "^11.0.0" } }, + "node_modules/@fastify/vite": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@fastify/vite/-/vite-8.1.3.tgz", + "integrity": "sha512-+99owAUzIy5J6PQO3wbzdJD9+7g7iLhm1YeXPyQVGksnppqHXFgO5OYnNzDWFjGW2UN7bmCr5Hd0t4vfmbXZUw==", + "license": "MIT", + "dependencies": { + "@fastify/deepmerge": "^3.0.0", + "@fastify/middie": "^9.0.3", + "@fastify/static": "^8.1.1", + "fastify-plugin": "^5.0.1", + "find-cache-dir": "^5.0.0", + "fs-extra": "^11.3.0", + "html-rewriter-wasm": "^0.4.1", + "klaw": "^4.1.0" + }, + "peerDependencies": { + "fastify": ">=5", + "vite": ">=5" + } + }, + "node_modules/@fastify/vite/node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/@graphql-codegen/add": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz", @@ -2515,7 +2563,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2529,7 +2576,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2543,7 +2589,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2557,7 +2602,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2571,7 +2615,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2585,7 +2628,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2599,7 +2641,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2613,7 +2654,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2627,7 +2667,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2641,7 +2680,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2655,7 +2693,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2669,7 +2706,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2683,7 +2719,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2697,7 +2732,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2711,7 +2745,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2725,7 +2758,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2739,7 +2771,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2753,7 +2784,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2767,7 +2797,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2781,7 +2810,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2894,7 +2922,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, "license": "MIT" }, "node_modules/@types/hast": { @@ -4530,7 +4557,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "dev": true, + "devOptional": true, "license": "MIT/X11" }, "node_modules/buffer-crc32": { @@ -4943,7 +4970,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -4979,6 +5006,12 @@ "node": ">= 6" } }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "license": "ISC" + }, "node_modules/common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", @@ -5785,7 +5818,6 @@ "version": "0.25.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -6783,6 +6815,22 @@ "node": ">=8" } }, + "node_modules/find-cache-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-5.0.0.tgz", + "integrity": "sha512-OuWNfjfP05JcpAP3JPgAKUhWefjMRfI5iAoSsvE24ANYWJaepAtlSgWECSVEuRgSXpyNEc9DJwG/TZpgcOqyig==", + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-my-way": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.3.0.tgz", @@ -6948,7 +6996,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -7270,7 +7317,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -7440,7 +7486,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=8" @@ -7588,6 +7634,12 @@ "void-elements": "3.1.0" } }, + "node_modules/html-rewriter-wasm": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/html-rewriter-wasm/-/html-rewriter-wasm-0.4.1.tgz", + "integrity": "sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==", + "license": "BSD-3-Clause" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -8549,7 +8601,7 @@ "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -8696,7 +8748,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -8757,6 +8808,15 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.1.0.tgz", + "integrity": "sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw==", + "license": "MIT", + "engines": { + "node": ">=14.14.0" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", @@ -9223,7 +9283,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -9843,6 +9902,15 @@ "node": "20 || >=22" } }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -9946,6 +10014,103 @@ ], "license": "MIT" }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -9960,7 +10125,6 @@ "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -10641,7 +10805,6 @@ "version": "4.40.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.7" @@ -10714,7 +10877,7 @@ "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -10834,7 +10997,7 @@ "version": "1.87.0", "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.87.0.tgz", "integrity": "sha512-1IA3iTJNh4BkkA/nidKiVwbmkxr9o6LsPegycHMX/JYs255zpocN5GdLF1+onohQCJxbs5ldr8osKV7qNaNBjg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.0.0", @@ -10882,7 +11045,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10899,7 +11061,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10916,7 +11077,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10933,7 +11093,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10950,7 +11109,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10967,7 +11125,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10984,7 +11141,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11001,7 +11157,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11018,7 +11173,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11035,7 +11189,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11052,7 +11205,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11069,7 +11221,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11086,7 +11237,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11103,7 +11253,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11120,7 +11269,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11137,7 +11285,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11154,7 +11301,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11171,7 +11317,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11188,7 +11333,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11205,7 +11349,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11219,14 +11362,14 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.1.tgz", "integrity": "sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/sass-embedded/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -11529,7 +11672,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -11896,7 +12038,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "sync-message-port": "^1.0.0" @@ -11941,7 +12083,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=16.0.0" @@ -12003,7 +12145,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.4.4", @@ -12020,7 +12161,6 @@ "version": "6.4.4", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", - "dev": true, "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -12035,7 +12175,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -12451,7 +12590,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" @@ -12609,7 +12747,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/verror": { @@ -12631,7 +12769,6 @@ "version": "6.3.4", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz", "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -12706,7 +12843,6 @@ "version": "6.4.4", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", - "dev": true, "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -12721,7 +12857,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" diff --git a/package.json b/package.json index 8fec6bd4..a8e61b62 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "dependencies": { "@apollo/client": "^3.13.6", "@fastify/static": "^8.1.1", + "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", diff --git a/server.js b/server.js index cf0fb5be..77826326 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,6 @@ import Fastify from 'fastify'; import FastifyStatic from '@fastify/static'; +import FastifyVite from '@fastify/vite'; import { fileURLToPath } from 'node:url'; import path from 'node:path'; import dotenv from 'dotenv'; @@ -10,6 +11,8 @@ dotenv.config(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +console.log(__dirname); + const fastify = Fastify({ logger: true, }); @@ -18,13 +21,24 @@ fastify.register(proxy, { prefix: '/api', }); -fastify.register(FastifyStatic, { - root: path.join(__dirname, 'dist'), - // prefix: '/', // optional: default '/' - // constraints: { host: 'example.com' } // optional: default {} +// fastify.register(FastifyStatic, { +// root: path.join(__dirname, 'dist'), +// // prefix: '/', // optional: default '/' +// // constraints: { host: 'example.com' } // optional: default {} +// }); + +await fastify.register(FastifyVite, { + root: __dirname, + dev: process.argv.includes('--dev'), + spa: true, +}); + +fastify.get('/', (req, reply) => { + return reply.html(); }); -fastify.listen( +await fastify.vite.ready(); +await fastify.listen( { port: 5173, }, diff --git a/tsconfig.json b/tsconfig.json index 45167634..85beb6a8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,7 @@ "noFallthroughCasesInSwitch": true, "types": ["node", "cypress"] }, - "include": ["src", "cypress.d.ts", "server.js"], + "include": ["src", "cypress.d.ts", "server.js", "i18n.ts"], "references": [ { "path": "./tsconfig.node.json" diff --git a/tsconfig.node.json b/tsconfig.node.json index b4812afe..77b49109 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -6,5 +6,5 @@ "moduleResolution": "bundler", "allowSyntheticDefaultImports": true }, - "include": ["vite.config.ts", "cypress.config.ts"] + "include": ["vite.config.js", "cypress.config.ts"] } diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 00000000..4e513fb5 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,10 @@ +import { resolve } from 'node:path'; +import { defineConfig } from 'vite'; +import viteFastify from '@fastify/vite/plugin'; +import react from '@vitejs/plugin-react'; + +// https://vitejs.dev/config/ +export default defineConfig({ + root: resolve(import.meta.dirname), + plugins: [viteFastify(), react()], +}); diff --git a/vite.config.ts b/vite.config.ts deleted file mode 100644 index b0762169..00000000 --- a/vite.config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], - server: { - port: 5173, - strictPort: true, - proxy: { - '/api': { - target: 'http://localhost:3001', - changeOrigin: true, - ws: true, - rewrite: (path) => path.replace(/^\/api/, ''), - }, - }, - }, -}); From c40615d735adea56ec1a80daa5a7f16a8e28469b Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Thu, 15 May 2025 14:03:36 +0200 Subject: [PATCH 5/9] fixed build command --- server/.env.template => .env.template | 0 index.html | 4 +- package-lock.json | 371 ++++++++- package.json | 16 +- server.js | 9 - server/README.md | 1 - server/package-lock.json | 1100 ------------------------- server/package.json | 25 - src/main.tsx | 66 +- src/mount.ts | 5 + vite.config.js | 2 +- 11 files changed, 418 insertions(+), 1181 deletions(-) rename server/.env.template => .env.template (100%) delete mode 100644 server/README.md delete mode 100644 server/package-lock.json delete mode 100644 server/package.json create mode 100644 src/mount.ts diff --git a/server/.env.template b/.env.template similarity index 100% rename from server/.env.template rename to .env.template diff --git a/index.html b/index.html index b2f209ef..f97fa54e 100644 --- a/index.html +++ b/index.html @@ -14,7 +14,7 @@
- + - \ No newline at end of file + diff --git a/package-lock.json b/package-lock.json index 0c3320ce..bca77ce0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,12 @@ "version": "0.0.0", "dependencies": { "@apollo/client": "^3.13.6", + "@fastify/autoload": "^6.3.0", + "@fastify/cookie": "^11.0.2", + "@fastify/env": "^5.0.2", + "@fastify/http-proxy": "^11.1.2", + "@fastify/secure-session": "^8.2.0", + "@fastify/sensible": "^6.0.3", "@fastify/static": "^8.1.1", "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", @@ -19,6 +25,7 @@ "clsx": "^2.1.1", "dotenv": "^16.5.0", "fastify": "^5.3.3", + "fastify-plugin": "^5.0.1", "graphql": "^16.10.0", "graphql-config": "^5.1.3", "i18next": "^25.0.0", @@ -1207,12 +1214,48 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, + "node_modules/@fastify/autoload": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@fastify/autoload/-/autoload-6.3.0.tgz", + "integrity": "sha512-VBYApgvqX5e+M2BAWKCxrYk9yTo8z127xsSzsSePQZlxt97tbQay74n//NDFK4ovFMgyhKSjoWtHTbdGw/RDvQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/@fastify/busboy": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==", "license": "MIT" }, + "node_modules/@fastify/cookie": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-11.0.2.tgz", + "integrity": "sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "cookie": "^1.0.0", + "fastify-plugin": "^5.0.0" + } + }, "node_modules/@fastify/deepmerge": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-3.1.0.tgz", @@ -1229,6 +1272,26 @@ ], "license": "MIT" }, + "node_modules/@fastify/env": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@fastify/env/-/env-5.0.2.tgz", + "integrity": "sha512-4m/jHS3s/G/DBJVODob9sxGUei/Ij8JFbA2PYqBfoihTm+Qqae2xD9xhez68UFZu1d4SNJPIb6uAOwbNvRYw+A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "env-schema": "^6.0.0", + "fastify-plugin": "^5.0.0" + } + }, "node_modules/@fastify/error": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.1.0.tgz", @@ -1270,6 +1333,28 @@ "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", "license": "MIT" }, + "node_modules/@fastify/http-proxy": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@fastify/http-proxy/-/http-proxy-11.1.2.tgz", + "integrity": "sha512-DDceCz1DIEa4vUsQ0DhMqwiZdZUCG0RByY51k0BndBLo7bWpO3QuzLpZTS7Hr6Bp6r82SRmAinM0uPpQse1zqA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/reply-from": "^12.0.2", + "fast-querystring": "^1.1.2", + "fastify-plugin": "^5.0.1", + "ws": "^8.18.0" + } + }, "node_modules/@fastify/merge-json-schemas": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", @@ -1321,6 +1406,55 @@ "ipaddr.js": "^2.1.0" } }, + "node_modules/@fastify/reply-from": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/@fastify/reply-from/-/reply-from-12.1.0.tgz", + "integrity": "sha512-5SvMj0NnAAhno/MIv+bErCfzYxcqTueqUxCyub/i+68/CqYWroYg0/p8D0ZhrSQcDigowaKk+MEQSoLjbGwZ+g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "end-of-stream": "^1.4.4", + "fast-content-type-parse": "^2.0.0", + "fast-querystring": "^1.1.2", + "fastify-plugin": "^5.0.1", + "toad-cache": "^3.7.0", + "undici": "^7.0.0" + } + }, + "node_modules/@fastify/secure-session": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@fastify/secure-session/-/secure-session-8.2.0.tgz", + "integrity": "sha512-E1linEHVV86c0Gt+ohujcuRsCeedhD2M3X5+a2aU9Ln0YDC0bbuA7bE6QQzf/HAacOpt9+CJqV5NqdlQr9ui0A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/cookie": "^11.0.1", + "fastify-plugin": "^5.0.0", + "sodium-native": "^4.0.10" + }, + "bin": { + "secure-session": "genkey.js" + } + }, "node_modules/@fastify/send": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@fastify/send/-/send-3.3.1.tgz", @@ -1344,6 +1478,31 @@ "mime": "^3" } }, + "node_modules/@fastify/sensible": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@fastify/sensible/-/sensible-6.0.3.tgz", + "integrity": "sha512-Iyn8698hp/e5+v8SNBBruTa7UfrMEP52R16dc9jMpqSyEcPsvWFQo+R6WwHCUnJiLIsuci2ZoEZ7ilrSSCPIVg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "dequal": "^2.0.3", + "fastify-plugin": "^5.0.0", + "forwarded": "^0.2.0", + "http-errors": "^2.0.0", + "type-is": "^1.6.18", + "vary": "^1.1.2" + } + }, "node_modules/@fastify/static": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@fastify/static/-/static-8.1.1.tgz", @@ -4405,6 +4564,74 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/bare-addon-resolve": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.9.4.tgz", + "integrity": "sha512-unn6Vy/Yke6F99vg/7tcrvM2KUvIhTNniaSqDbam4AWkd4NhvDVSrQiRYVlNzUV2P7SPobkCK7JFVxrJk9btCg==", + "license": "Apache-2.0", + "dependencies": { + "bare-module-resolve": "^1.10.0", + "bare-semver": "^1.0.0" + }, + "peerDependencies": { + "bare-url": "*" + }, + "peerDependenciesMeta": { + "bare-url": { + "optional": true + } + } + }, + "node_modules/bare-module-resolve": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.10.2.tgz", + "integrity": "sha512-C9COe/GhWfVXKytW3DElTkiBU+Gb2OXeaVkdGdRB/lp26TVLESHkTGS876iceAGdvtPgohfp9nX8vXHGvN3++Q==", + "license": "Apache-2.0", + "dependencies": { + "bare-semver": "^1.0.0" + }, + "peerDependencies": { + "bare-url": "*" + }, + "peerDependenciesMeta": { + "bare-url": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", + "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-semver": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.1.tgz", + "integrity": "sha512-UtggzHLiTrmFOC/ogQ+Hy7VfoKoIwrP1UFcYtTxoCUdLtsIErT8+SWtOC2DH/snT9h+xDrcBEPcwKei1mzemgg==", + "license": "Apache-2.0" + }, + "node_modules/bare-url": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.1.6.tgz", + "integrity": "sha512-FgjDeR+/yDH34By4I0qB5NxAoWv7dOTYcOXwn73kr+c93HyC2lU6tnjifqUe33LKMJcDyCYPQjEAqgOQiXkE2Q==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5553,6 +5780,15 @@ "url": "https://dotenvx.com" } }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, "node_modules/dset": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", @@ -5611,7 +5847,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -5631,6 +5866,49 @@ "node": ">=8.6" } }, + "node_modules/env-schema": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/env-schema/-/env-schema-6.0.1.tgz", + "integrity": "sha512-WRD40Q25pP4NUbI3g3CNU5PPzcaiX7YYcPwiCZlfR4qGsKmTlckRixgHww0/fOXiXSNKA87pwshzq0ULTK/48A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "ajv": "^8.12.0", + "dotenv": "^16.4.5", + "dotenv-expand": "10.0.0" + } + }, + "node_modules/env-schema/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/env-schema/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==", + "license": "MIT" + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -6482,6 +6760,22 @@ ], "license": "MIT" }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "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", @@ -6976,6 +7270,15 @@ "node": ">=12.20.0" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -9136,6 +9439,15 @@ "node": ">= 0.4" } }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", @@ -9204,7 +9516,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -9214,7 +9525,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -9565,7 +9875,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -10693,6 +11002,19 @@ "throttleit": "^1.0.0" } }, + "node_modules/require-addon": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.1.0.tgz", + "integrity": "sha512-KbXAD5q2+v1GJnkzd8zzbOxchTkStSyJZ9QwoCq3QwEXAaIlG3wDYRZGzVD357jmwaGY7hr5VaoEAL0BkF0Kvg==", + "license": "Apache-2.0", + "dependencies": { + "bare-addon-resolve": "^1.3.0", + "bare-url": "^2.1.0" + }, + "engines": { + "bare": ">=1.10.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -11659,6 +11981,15 @@ "tslib": "^2.0.3" } }, + "node_modules/sodium-native": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.3.tgz", + "integrity": "sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==", + "license": "MIT", + "dependencies": { + "require-addon": "^1.1.0" + } + }, "node_modules/sonic-boom": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", @@ -12409,6 +12740,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -12580,6 +12924,15 @@ "node": ">=0.10.0" } }, + "node_modules/undici": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.9.0.tgz", + "integrity": "sha512-e696y354tf5cFZPXsF26Yg+5M63+5H3oE6Vtkh2oqbvsE2Oe7s2nIbcQh5lmG7Lp/eS29vJtTpw9+p6PX0qNSg==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -12750,6 +13103,15 @@ "devOptional": true, "license": "MIT" }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -13072,7 +13434,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/ws": { diff --git a/package.json b/package.json index a8e61b62..a63ce6a6 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,9 @@ "npm": "^11.0.0" }, "scripts": { - "dev": "vite dev", - "build": "tsc && vite build", + "dev": "node server.js --dev", + "start": "node server.js", + "build": "tsc && vite build --debug", "lint": "eslint ./src --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", "test": "cypress run --component --browser chrome", @@ -20,8 +21,6 @@ }, "dependencies": { "@apollo/client": "^3.13.6", - "@fastify/static": "^8.1.1", - "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", @@ -30,6 +29,15 @@ "clsx": "^2.1.1", "dotenv": "^16.5.0", "fastify": "^5.3.3", + "fastify-plugin": "^5.0.1", + "@fastify/autoload": "^6.3.0", + "@fastify/cookie": "^11.0.2", + "@fastify/env": "^5.0.2", + "@fastify/http-proxy": "^11.1.2", + "@fastify/secure-session": "^8.2.0", + "@fastify/sensible": "^6.0.3", + "@fastify/static": "^8.1.1", + "@fastify/vite": "^8.1.3", "graphql": "^16.10.0", "graphql-config": "^5.1.3", "i18next": "^25.0.0", diff --git a/server.js b/server.js index 77826326..b01d4fdc 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,4 @@ import Fastify from 'fastify'; -import FastifyStatic from '@fastify/static'; import FastifyVite from '@fastify/vite'; import { fileURLToPath } from 'node:url'; import path from 'node:path'; @@ -11,8 +10,6 @@ dotenv.config(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -console.log(__dirname); - const fastify = Fastify({ logger: true, }); @@ -21,12 +18,6 @@ fastify.register(proxy, { prefix: '/api', }); -// fastify.register(FastifyStatic, { -// root: path.join(__dirname, 'dist'), -// // prefix: '/', // optional: default '/' -// // constraints: { host: 'example.com' } // optional: default {} -// }); - await fastify.register(FastifyVite, { root: __dirname, dev: process.argv.includes('--dev'), diff --git a/server/README.md b/server/README.md deleted file mode 100644 index f87f5c14..00000000 --- a/server/README.md +++ /dev/null @@ -1 +0,0 @@ -# TODO \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json deleted file mode 100644 index f8f5a754..00000000 --- a/server/package-lock.json +++ /dev/null @@ -1,1100 +0,0 @@ -{ - "name": "ui-bff", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "ui-bff", - "version": "1.0.0", - "dependencies": { - "@fastify/autoload": "^6.3.0", - "@fastify/cookie": "^11.0.2", - "@fastify/env": "^5.0.2", - "@fastify/http-proxy": "^11.1.2", - "@fastify/secure-session": "^8.2.0", - "@fastify/sensible": "^6.0.3", - "fastify": "^5.3.3", - "fastify-plugin": "^5.0.1" - }, - "engines": { - "node": "^22.0.0", - "npm": "^11.0.0" - } - }, - "node_modules/@fastify/ajv-compiler": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.2.tgz", - "integrity": "sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "ajv": "^8.12.0", - "ajv-formats": "^3.0.1", - "fast-uri": "^3.0.0" - } - }, - "node_modules/@fastify/autoload": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@fastify/autoload/-/autoload-6.3.0.tgz", - "integrity": "sha512-VBYApgvqX5e+M2BAWKCxrYk9yTo8z127xsSzsSePQZlxt97tbQay74n//NDFK4ovFMgyhKSjoWtHTbdGw/RDvQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/@fastify/cookie": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-11.0.2.tgz", - "integrity": "sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "cookie": "^1.0.0", - "fastify-plugin": "^5.0.0" - } - }, - "node_modules/@fastify/env": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@fastify/env/-/env-5.0.2.tgz", - "integrity": "sha512-4m/jHS3s/G/DBJVODob9sxGUei/Ij8JFbA2PYqBfoihTm+Qqae2xD9xhez68UFZu1d4SNJPIb6uAOwbNvRYw+A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "env-schema": "^6.0.0", - "fastify-plugin": "^5.0.0" - } - }, - "node_modules/@fastify/error": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.1.0.tgz", - "integrity": "sha512-KeFcciOr1eo/YvIXHP65S94jfEEqn1RxTRBT1aJaHxY5FK0/GDXYozsQMMWlZoHgi8i0s+YtrLsgj/JkUUjSkQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/@fastify/fast-json-stringify-compiler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz", - "integrity": "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "fast-json-stringify": "^6.0.0" - } - }, - "node_modules/@fastify/forwarded": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz", - "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", - "license": "MIT" - }, - "node_modules/@fastify/http-proxy": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@fastify/http-proxy/-/http-proxy-11.1.2.tgz", - "integrity": "sha512-DDceCz1DIEa4vUsQ0DhMqwiZdZUCG0RByY51k0BndBLo7bWpO3QuzLpZTS7Hr6Bp6r82SRmAinM0uPpQse1zqA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/reply-from": "^12.0.2", - "fast-querystring": "^1.1.2", - "fastify-plugin": "^5.0.1", - "ws": "^8.18.0" - } - }, - "node_modules/@fastify/merge-json-schemas": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", - "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@fastify/proxy-addr": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", - "integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==", - "license": "MIT", - "dependencies": { - "@fastify/forwarded": "^3.0.0", - "ipaddr.js": "^2.1.0" - } - }, - "node_modules/@fastify/reply-from": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@fastify/reply-from/-/reply-from-12.1.0.tgz", - "integrity": "sha512-5SvMj0NnAAhno/MIv+bErCfzYxcqTueqUxCyub/i+68/CqYWroYg0/p8D0ZhrSQcDigowaKk+MEQSoLjbGwZ+g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/error": "^4.0.0", - "end-of-stream": "^1.4.4", - "fast-content-type-parse": "^2.0.0", - "fast-querystring": "^1.1.2", - "fastify-plugin": "^5.0.1", - "toad-cache": "^3.7.0", - "undici": "^7.0.0" - } - }, - "node_modules/@fastify/secure-session": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@fastify/secure-session/-/secure-session-8.2.0.tgz", - "integrity": "sha512-E1linEHVV86c0Gt+ohujcuRsCeedhD2M3X5+a2aU9Ln0YDC0bbuA7bE6QQzf/HAacOpt9+CJqV5NqdlQr9ui0A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/cookie": "^11.0.1", - "fastify-plugin": "^5.0.0", - "sodium-native": "^4.0.10" - }, - "bin": { - "secure-session": "genkey.js" - } - }, - "node_modules/@fastify/sensible": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@fastify/sensible/-/sensible-6.0.3.tgz", - "integrity": "sha512-Iyn8698hp/e5+v8SNBBruTa7UfrMEP52R16dc9jMpqSyEcPsvWFQo+R6WwHCUnJiLIsuci2ZoEZ7ilrSSCPIVg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@lukeed/ms": "^2.0.2", - "dequal": "^2.0.3", - "fastify-plugin": "^5.0.0", - "forwarded": "^0.2.0", - "http-errors": "^2.0.0", - "type-is": "^1.6.18", - "vary": "^1.1.2" - } - }, - "node_modules/@lukeed/ms": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", - "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": 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==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/avvio": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.1.0.tgz", - "integrity": "sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==", - "license": "MIT", - "dependencies": { - "@fastify/error": "^4.0.0", - "fastq": "^1.17.1" - } - }, - "node_modules/bare-addon-resolve": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/bare-addon-resolve/-/bare-addon-resolve-1.9.4.tgz", - "integrity": "sha512-unn6Vy/Yke6F99vg/7tcrvM2KUvIhTNniaSqDbam4AWkd4NhvDVSrQiRYVlNzUV2P7SPobkCK7JFVxrJk9btCg==", - "license": "Apache-2.0", - "dependencies": { - "bare-module-resolve": "^1.10.0", - "bare-semver": "^1.0.0" - }, - "peerDependencies": { - "bare-url": "*" - }, - "peerDependenciesMeta": { - "bare-url": { - "optional": true - } - } - }, - "node_modules/bare-module-resolve": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.10.2.tgz", - "integrity": "sha512-C9COe/GhWfVXKytW3DElTkiBU+Gb2OXeaVkdGdRB/lp26TVLESHkTGS876iceAGdvtPgohfp9nX8vXHGvN3++Q==", - "license": "Apache-2.0", - "dependencies": { - "bare-semver": "^1.0.0" - }, - "peerDependencies": { - "bare-url": "*" - }, - "peerDependenciesMeta": { - "bare-url": { - "optional": true - } - } - }, - "node_modules/bare-os": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz", - "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==", - "license": "Apache-2.0", - "engines": { - "bare": ">=1.14.0" - } - }, - "node_modules/bare-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", - "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", - "license": "Apache-2.0", - "dependencies": { - "bare-os": "^3.0.1" - } - }, - "node_modules/bare-semver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bare-semver/-/bare-semver-1.0.1.tgz", - "integrity": "sha512-UtggzHLiTrmFOC/ogQ+Hy7VfoKoIwrP1UFcYtTxoCUdLtsIErT8+SWtOC2DH/snT9h+xDrcBEPcwKei1mzemgg==", - "license": "Apache-2.0" - }, - "node_modules/bare-url": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.1.6.tgz", - "integrity": "sha512-FgjDeR+/yDH34By4I0qB5NxAoWv7dOTYcOXwn73kr+c93HyC2lU6tnjifqUe33LKMJcDyCYPQjEAqgOQiXkE2Q==", - "license": "Apache-2.0", - "dependencies": { - "bare-path": "^3.0.0" - } - }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/dotenv": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", - "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/env-schema": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/env-schema/-/env-schema-6.0.1.tgz", - "integrity": "sha512-WRD40Q25pP4NUbI3g3CNU5PPzcaiX7YYcPwiCZlfR4qGsKmTlckRixgHww0/fOXiXSNKA87pwshzq0ULTK/48A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "ajv": "^8.12.0", - "dotenv": "^16.4.5", - "dotenv-expand": "10.0.0" - } - }, - "node_modules/fast-content-type-parse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", - "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "node_modules/fast-json-stringify": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-6.0.1.tgz", - "integrity": "sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/merge-json-schemas": "^0.2.0", - "ajv": "^8.12.0", - "ajv-formats": "^3.0.1", - "fast-uri": "^3.0.0", - "json-schema-ref-resolver": "^2.0.0", - "rfdc": "^1.2.0" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "fast-decode-uri-component": "^1.0.1" - } - }, - "node_modules/fast-redact": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", - "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastify": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.3.3.tgz", - "integrity": "sha512-nCBiBCw9q6jPx+JJNVgO8JVnTXeUyrGcyTKPQikRkA/PanrFcOIo4R+ZnLeOLPZPGgzjomqfVarzE0kYx7qWiQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/ajv-compiler": "^4.0.0", - "@fastify/error": "^4.0.0", - "@fastify/fast-json-stringify-compiler": "^5.0.0", - "@fastify/proxy-addr": "^5.0.0", - "abstract-logging": "^2.0.1", - "avvio": "^9.0.0", - "fast-json-stringify": "^6.0.0", - "find-my-way": "^9.0.0", - "light-my-request": "^6.0.0", - "pino": "^9.0.0", - "process-warning": "^5.0.0", - "rfdc": "^1.3.1", - "secure-json-parse": "^4.0.0", - "semver": "^7.6.0", - "toad-cache": "^3.7.0" - } - }, - "node_modules/fastify-plugin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.0.1.tgz", - "integrity": "sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==", - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/find-my-way": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.3.0.tgz", - "integrity": "sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-querystring": "^1.0.0", - "safe-regex2": "^5.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/json-schema-ref-resolver": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz", - "integrity": "sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/light-my-request": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", - "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause", - "dependencies": { - "cookie": "^1.0.1", - "process-warning": "^4.0.0", - "set-cookie-parser": "^2.6.0" - } - }, - "node_modules/light-my-request/node_modules/process-warning": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", - "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/pino": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", - "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^2.0.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^4.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", - "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", - "license": "MIT", - "dependencies": { - "split2": "^4.0.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", - "license": "MIT" - }, - "node_modules/pino/node_modules/process-warning": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", - "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/process-warning": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", - "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "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==", - "license": "MIT" - }, - "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==", - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/require-addon": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/require-addon/-/require-addon-1.1.0.tgz", - "integrity": "sha512-KbXAD5q2+v1GJnkzd8zzbOxchTkStSyJZ9QwoCq3QwEXAaIlG3wDYRZGzVD357jmwaGY7hr5VaoEAL0BkF0Kvg==", - "license": "Apache-2.0", - "dependencies": { - "bare-addon-resolve": "^1.3.0", - "bare-url": "^2.1.0" - }, - "engines": { - "bare": ">=1.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==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ret": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz", - "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "license": "MIT" - }, - "node_modules/safe-regex2": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.0.0.tgz", - "integrity": "sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "ret": "~0.5.0" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/secure-json-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz", - "integrity": "sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/sodium-native": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.3.tgz", - "integrity": "sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==", - "license": "MIT", - "dependencies": { - "require-addon": "^1.1.0" - } - }, - "node_modules/sonic-boom": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", - "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "license": "MIT", - "dependencies": { - "real-require": "^0.2.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==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/undici": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.8.0.tgz", - "integrity": "sha512-vFv1GA99b7eKO1HG/4RPu2Is3FBTWBrmzqzO0mz+rLxN3yXkE4mqRcb8g8fHxzX4blEysrNZLqg5RbJLqX5buA==", - "license": "MIT", - "engines": { - "node": ">=20.18.1" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", - "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/server/package.json b/server/package.json deleted file mode 100644 index 8a0664bb..00000000 --- a/server/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "ui-bff", - "description": "Backend for frontend (BFF) for the UI.", - "version": "1.0.0", - "type": "module", - "engines": { - "node": "^22.0.0", - "npm": "^11.0.0" - }, - "main": "app.js", - "scripts": { - "start": "fastify start -l info -p 3001 app.js", - "dev": "fastify start -w -l info -p 3001 -P app.js" - }, - "dependencies": { - "@fastify/autoload": "^6.3.0", - "@fastify/cookie": "^11.0.2", - "@fastify/env": "^5.0.2", - "@fastify/http-proxy": "^11.1.2", - "@fastify/secure-session": "^8.2.0", - "@fastify/sensible": "^6.0.3", - "fastify": "^5.3.3", - "fastify-plugin": "^5.0.1" - } -} diff --git a/src/main.tsx b/src/main.tsx index 900c23d2..efa47ddc 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,5 +1,4 @@ import React, { Suspense } from 'react'; -import { createRoot } from 'react-dom/client'; import './index.css'; import App from './App'; import { BusyIndicator, ThemeProvider } from '@ui5/webcomponents-react'; @@ -31,36 +30,35 @@ const ErrorFallback = ({ error }: FallbackProps) => { ); }; -const rootElement = document.getElementById('root'); -const root = createRoot(rootElement!); - -root.render( - - {}}> - }> - - - - - - - - - - - - - - - - - - - - - , -); +export function createApp() { + return ( + + {}}> + }> + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/mount.ts b/src/mount.ts new file mode 100644 index 00000000..394f3425 --- /dev/null +++ b/src/mount.ts @@ -0,0 +1,5 @@ +import { createRoot } from 'react-dom/client'; +import { createApp } from './main.tsx'; + +const root = createRoot(document.getElementById('root')!); +root.render(createApp()); diff --git a/vite.config.js b/vite.config.js index 4e513fb5..b793f108 100644 --- a/vite.config.js +++ b/vite.config.js @@ -6,5 +6,5 @@ import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ export default defineConfig({ root: resolve(import.meta.dirname), - plugins: [viteFastify(), react()], + plugins: [viteFastify({ spa: true }), react()], }); From fcb0b097cd058618fae804e66e9aed697c7b3e6a Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Thu, 15 May 2025 14:04:47 +0200 Subject: [PATCH 6/9] fix: linting --- vite.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite.config.js b/vite.config.js index b793f108..deaa5246 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,6 +1,6 @@ import { resolve } from 'node:path'; import { defineConfig } from 'vite'; -import viteFastify from '@fastify/vite/plugin'; +import { viteFastify } from '@fastify/vite/plugin'; import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ From 86bb01533f5025a51bdb137d14babd89fa30c761 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Thu, 15 May 2025 14:05:17 +0200 Subject: [PATCH 7/9] removed debug flag --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a63ce6a6..3503fffb 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "dev": "node server.js --dev", "start": "node server.js", - "build": "tsc && vite build --debug", + "build": "tsc && vite build", "lint": "eslint ./src --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", "test": "cypress run --component --browser chrome", From 53e802b1c618c9c8cc6fa5460050fabb17f7fd92 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Thu, 15 May 2025 16:16:56 +0200 Subject: [PATCH 8/9] made dockerfile compatible with new fastify server --- Dockerfile | 24 ++++++++++++++++++------ server.js | 3 ++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8a4e9c27..98818536 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,14 +9,26 @@ COPY package*.json ./ # Install dependencies RUN npm ci -# Build +# Build ENV NODE_ENV=production COPY . . RUN npm run build -# Use the latest LTS version of Nginx as the serving image -# https://hub.docker.com/_/nginx -FROM nginx:1.28.0-alpine-slim@sha256:39a9a15e0a81914a96fa9ffa980cdfe08e2e5e73ae3424f341ad1f470147c413 +# The same image but now only install the production dependencies as the frontend is already built using vite in the build-stage +FROM node:22-alpine3.20@sha256:686b8892b69879ef5bfd6047589666933508f9a5451c67320df3070ba0e9807b AS production -COPY nginx.conf /etc/nginx/templates/default.conf.template -COPY --from=build-stage /usr/src/app/dist /usr/share/nginx/html \ No newline at end of file +WORKDIR /usr/src/app + +# copy over package.json from the origin file system again so it can be done in parallel from docker (if configured) +COPY package*.json ./ +# install only dependencies which are not marked as dev +RUN npm ci --omit=dev + +# copy over necessary files for the server +COPY server.js ./ +COPY server server + +# copy over precompiled frontend +COPY --from=build-stage /usr/src/app/dist dist + +CMD ["npm", "run", "start"] diff --git a/server.js b/server.js index b01d4fdc..cc9e422a 100644 --- a/server.js +++ b/server.js @@ -29,9 +29,10 @@ fastify.get('/', (req, reply) => { }); await fastify.vite.ready(); -await fastify.listen( +fastify.listen( { port: 5173, + host: '0.0.0.0', }, function (err, address) { if (err) { From 59af70c53ff8258180ff652070aa9027eeb7144e Mon Sep 17 00:00:00 2001 From: Andreas Kienle Date: Tue, 20 May 2025 15:35:59 +0200 Subject: [PATCH 9/9] Remove oidc-client --- frontend-config.json | 8 +- package-lock.json | 62 ++------ package.json | 2 - public/locales/en.json | 6 - server/routes/auth.js | 15 +- src/App.tsx | 28 +--- src/components/Core/ApiConfigWrapper.tsx | 10 +- src/components/Core/ShellBar.tsx | 6 +- .../Dialogs/CreateProjectDialogContainer.tsx | 9 +- .../CreateWorkspaceDialogContainer.tsx | 8 +- .../Dialogs/SessionExpiringDialog.tsx | 61 -------- src/context/AuthProviderOnboarding.tsx | 34 ----- src/context/FrontendConfigContext.tsx | 9 -- src/lib/api/types/apiConfig.ts | 22 +-- src/lib/oidc/shared.ts | 139 ------------------ src/lib/oidc/useUsername.ts | 7 - src/lib/shared/McpContext.tsx | 17 +-- src/main.tsx | 43 +++--- src/spaces/onboarding/auth/AuthContext.tsx | 83 +++++++---- src/spaces/onboarding/auth/auth.schemas.ts | 12 ++ .../ApolloClientProvider.tsx | 4 +- src/utils/testing.ts | 1 - src/views/Login.tsx | 4 +- 23 files changed, 134 insertions(+), 456 deletions(-) delete mode 100644 src/components/Dialogs/SessionExpiringDialog.tsx delete mode 100644 src/context/AuthProviderOnboarding.tsx delete mode 100644 src/lib/oidc/shared.ts delete mode 100644 src/lib/oidc/useUsername.ts create mode 100644 src/spaces/onboarding/auth/auth.schemas.ts diff --git a/frontend-config.json b/frontend-config.json index 554acc41..8422425c 100644 --- a/frontend-config.json +++ b/frontend-config.json @@ -1,11 +1,5 @@ { - "backendUrl": "http://localhost:3000", "gatewayUrl": "http://localhost:3000", "landscape": "LOCAL", - "documentationBaseUrl": "http://localhost:3000", - "oidcConfig": { - "clientId": "clientId", - "issuerUrl": "issuer-url", - "scopes": [] - } + "documentationBaseUrl": "http://localhost:3000" } diff --git a/package-lock.json b/package-lock.json index b0da70e2..2984d39e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,13 +31,11 @@ "i18next": "^25.0.0", "javascript-time-ago": "^2.5.11", "js-yaml": "^4.1.0", - "oidc-client-ts": "^3.1.0", "react": "19.1.0", "react-dom": "19.1.0", "react-error-boundary": "^6.0.0", "react-hook-form": "^7.54.2", "react-i18next": "^15.4.1", - "react-oidc-context": "^3.2.0", "react-router-dom": "^7.2.0", "react-syntax-highlighter": "^15.6.1", "react-time-ago": "^7.3.3", @@ -2654,15 +2652,15 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", - "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz", + "integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.4.0", - "@emnapi/runtime": "^1.4.0", + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" } }, @@ -3904,13 +3902,15 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.1.44", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.44.tgz", - "integrity": "sha512-m4XeohMT+Dj2RZfxnbiFR+Cv5dEC0H7C6TlxRQT7GK2556solm99kxgzJp/trKrZvanZcOFyw7aABykUTfWyrg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.0.tgz", + "integrity": "sha512-6vn3QDy+ysqHGkbH9fU9uyWptqNc638dgPy0uAlh/XpniTBp+0WeVlXGW74zqggex/CwYOhK8t5GVo/FH3NMPw==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.24.0" + }, "peerDependencies": { - "@typescript-eslint/utils": ">= 8.24.0", "eslint": ">= 8.57.0", "typescript": ">= 5.0.0", "vitest": "*" @@ -3951,9 +3951,9 @@ } }, "node_modules/@whatwg-node/node-fetch": { - "version": "0.7.19", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.7.19.tgz", - "integrity": "sha512-ippPt75epj7Tg6H5znI9lBBQ4gi+x23QsIF7UN1Z02MUqzhbkjhGsUtNnYGS3osrqvyKtbGKmEya6IqIPRmtdw==", + "version": "0.7.20", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.7.20.tgz", + "integrity": "sha512-2LI5HkZcdAODb6umb7MUxkWYNUi3j6apgQvIzp+X3w3AVPdvVsshvjaMo4gwLeFtfs+cyMNOLTm9Hhm/TXq6DA==", "license": "MIT", "dependencies": { "@fastify/busboy": "^3.1.1", @@ -9521,15 +9521,6 @@ "node": ">=4.0" } }, - "node_modules/jwt-decode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", - "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -10305,18 +10296,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oidc-client-ts": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.2.1.tgz", - "integrity": "sha512-hS5AJ5s/x4bXhHvNJT1v+GGvzHUwdRWqNQQbSrp10L1IRmzfRGKQ3VWN3dstJb+oF3WtAyKezwD2+dTEIyBiAA==", - "license": "Apache-2.0", - "dependencies": { - "jwt-decode": "^4.0.0" - }, - "engines": { - "node": ">=18" - } - }, "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", @@ -11285,19 +11264,6 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, - "node_modules/react-oidc-context": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/react-oidc-context/-/react-oidc-context-3.3.0.tgz", - "integrity": "sha512-302T/ma4AOVAxrHdYctDSKXjCq9KNHT564XEO2yOPxRfxEP58xa4nz+GQinNl8x7CnEXECSM5JEjQJk3Cr5BvA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "oidc-client-ts": "^3.1.0", - "react": ">=16.14.0" - } - }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", diff --git a/package.json b/package.json index 2e4c68f8..eac4a3ef 100644 --- a/package.json +++ b/package.json @@ -43,13 +43,11 @@ "i18next": "^25.0.0", "javascript-time-ago": "^2.5.11", "js-yaml": "^4.1.0", - "oidc-client-ts": "^3.1.0", "react": "19.1.0", "react-dom": "19.1.0", "react-error-boundary": "^6.0.0", "react-hook-form": "^7.54.2", "react-i18next": "^15.4.1", - "react-oidc-context": "^3.2.0", "react-router-dom": "^7.2.0", "react-syntax-highlighter": "^15.6.1", "react-time-ago": "^7.3.3", diff --git a/public/locales/en.json b/public/locales/en.json index 77b0852e..b2ab9f20 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -117,12 +117,6 @@ "columnEmailHeader": "Email", "columnRoleHeader": "Role" }, - "SessionExpiringDialog": { - "dialogHeader": "Your session is expiring soon...", - "signOutButton": "Sign Out", - "stayButton": "Stay Signed In", - "sessionText": "Your session expires soon and you will be signed out automatically. To continue working, press 'Stay Signed in'." - }, "IllustratedError": { "titleText": "Something went wrong", "subtitleText": "Contact admins for help" diff --git a/server/routes/auth.js b/server/routes/auth.js index 4536f383..2bfcfcef 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -52,18 +52,17 @@ async function authPlugin(fastify) { }); - fastify.get("/auth/status", async (req, reply) => { - const isAuthenticated = Boolean(req.session.get("accessToken")); - reply.send({ isAuthenticated }); - }); - + fastify.get("/auth/me", async (req, reply) => { + const accessToken = req.session.get("accessToken"); + const userInfo = req.session.get("userInfo"); - fastify.get("/auth/user", async (req, reply) => { - reply.send(req.session.get("userInfo")); + const isAuthenticated = Boolean(accessToken); + const user = isAuthenticated ? userInfo : null; + reply.send({ isAuthenticated, user }); }); - fastify.get("/auth/logout", async (_req, reply) => { + fastify.post("/auth/logout", async (_req, reply) => { // TODO: Idp sign out flow //_req.session.delete(); // remove payload reply.clearCookie(COOKIE_NAME_ONBOARDING, { path: "/" }); diff --git a/src/App.tsx b/src/App.tsx index 9f76e4b5..06e8f725 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,17 +1,14 @@ import AppRouter from './AppRouter'; import { useAuth } from './spaces/onboarding/auth/AuthContext.tsx'; import '@ui5/webcomponents-icons/dist/AllIcons.d.ts'; -import { useEffect, useState } from 'react'; -import { SessionExpiringDialog } from './components/Dialogs/SessionExpiringDialog.tsx'; +import { useEffect } from 'react'; import { useFrontendConfig } from './context/FrontendConfigContext.tsx'; import { useTranslation } from 'react-i18next'; +import LoginView from './views/Login.tsx'; function App() { const auth = useAuth(); - const [dialogSessionExpiringIsOpen, setDialogSessionExpiringIsOpen] = - useState(false); const { t } = useTranslation(); - const frontendConfig = useFrontendConfig(); useEffect(() => { @@ -25,27 +22,10 @@ function App() { } if (!auth.isAuthenticated) { - return ( - <> - {/****/} - - - ); + return ; } - return ( - <> - -
- {auth.isAuthenticated ? 'AUTHED' : 'NOT AUTHED'} - -
- - - ); + return ; } export default App; diff --git a/src/components/Core/ApiConfigWrapper.tsx b/src/components/Core/ApiConfigWrapper.tsx index b7bbbf52..69df750c 100644 --- a/src/components/Core/ApiConfigWrapper.tsx +++ b/src/components/Core/ApiConfigWrapper.tsx @@ -1,20 +1,12 @@ import { ApiConfigProvider } from '../Shared/k8s/index.ts'; import { Outlet } from 'react-router-dom'; -import { useAuth } from 'react-oidc-context'; import { generateCrateAPIConfig } from '../../lib/api/types/apiConfig.ts'; -import { useFrontendConfig } from '../../context/FrontendConfigContext.tsx'; // ApiConfigWrapper is a component that provides the ApiConfigProvider with the oidc access token from the oidc context. export default function ApiConfigWrapper() { - const auth = useAuth(); - const token = !auth.isAuthenticated ? '' : auth.user?.access_token; - const { backendUrl } = useFrontendConfig(); - return ( <> - + diff --git a/src/components/Core/ShellBar.tsx b/src/components/Core/ShellBar.tsx index 61bb4155..d07940e7 100644 --- a/src/components/Core/ShellBar.tsx +++ b/src/components/Core/ShellBar.tsx @@ -11,7 +11,7 @@ import { ShellBarDomRef, Ui5CustomEvent, } from '@ui5/webcomponents-react'; -import { useAuth } from 'react-oidc-context'; +import { useAuth } from '../../spaces/onboarding/auth/AuthContext.tsx'; import { RefObject, useEffect, useRef, useState } from 'react'; import { ShellBarProfileClickEventDetail } from '@ui5/webcomponents-fiori/dist/ShellBar.js'; import PopoverPlacement from '@ui5/webcomponents/dist/types/PopoverPlacement.js'; @@ -59,7 +59,7 @@ export function ShellBarComponent() { className={styles.TestShellbar} profile={ } @@ -123,7 +123,7 @@ const ProfilePopover = ({ icon="log" onClick={() => { setOpen(false); - auth.removeUser(); + void auth.logout(); }} > {t('ShellBar.signOutButton')} diff --git a/src/components/Dialogs/CreateProjectDialogContainer.tsx b/src/components/Dialogs/CreateProjectDialogContainer.tsx index 7de801de..e13d3bef 100644 --- a/src/components/Dialogs/CreateProjectDialogContainer.tsx +++ b/src/components/Dialogs/CreateProjectDialogContainer.tsx @@ -8,11 +8,10 @@ import { } from './CreateProjectWorkspaceDialog.tsx'; import { useToast } from '../../context/ToastContext.tsx'; -import { useAuthSubject } from '../../lib/oidc/useUsername.ts'; +import { useAuth } from '../../spaces/onboarding/auth/AuthContext.tsx'; import { MemberRoles } from '../../lib/api/types/shared/members.ts'; import { useTranslation } from 'react-i18next'; - import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { @@ -46,10 +45,10 @@ export function CreateProjectDialogContainer({ members: [], }, }); - - const username = useAuthSubject(); - const { t } = useTranslation(); + const { user } = useAuth(); + + const username = user?.email; const clearForm = useCallback(() => { resetField('name'); diff --git a/src/components/Dialogs/CreateWorkspaceDialogContainer.tsx b/src/components/Dialogs/CreateWorkspaceDialogContainer.tsx index 7af1cca6..267ead65 100644 --- a/src/components/Dialogs/CreateWorkspaceDialogContainer.tsx +++ b/src/components/Dialogs/CreateWorkspaceDialogContainer.tsx @@ -17,7 +17,7 @@ import { import { projectnameToNamespace } from '../../utils'; import { ListWorkspaces } from '../../lib/api/types/crate/listWorkspaces'; import { useToast } from '../../context/ToastContext.tsx'; -import { useAuthSubject } from '../../lib/oidc/useUsername.ts'; +import { useAuth } from '../../spaces/onboarding/auth/AuthContext.tsx'; import { Member, MemberRoles } from '../../lib/api/types/shared/members.ts'; import { useTranslation } from 'react-i18next'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -56,10 +56,10 @@ export function CreateWorkspaceDialogContainer({ members: [], }, }); - - const username = useAuthSubject(); - const { t } = useTranslation(); + const { user } = useAuth(); + + const username = user?.email; const clearForm = useCallback(() => { resetField('name'); diff --git a/src/components/Dialogs/SessionExpiringDialog.tsx b/src/components/Dialogs/SessionExpiringDialog.tsx deleted file mode 100644 index a2128182..00000000 --- a/src/components/Dialogs/SessionExpiringDialog.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { - Bar, - Dialog, - Text, - Toolbar, - ToolbarButton, -} from '@ui5/webcomponents-react'; -import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js'; -import { useTranslation } from 'react-i18next'; -import { useAuth } from 'react-oidc-context'; - -interface SessionExpiringDialogProps { - isOpen: boolean; - setIsOpen: (isOpen: boolean) => void; -} - -export function SessionExpiringDialog({ - isOpen, - setIsOpen, -}: SessionExpiringDialogProps) { - const auth = useAuth(); - const { t } = useTranslation(); - - return ( - <> - - { - setIsOpen(false); - auth.signoutSilent(); - auth.removeUser(); - }} - /> - { - setIsOpen(false); - auth.signinSilent(); - }} - /> - - } - /> - } - > - {t('SessionExpiringDialog.sessionText')} - - - ); -} diff --git a/src/context/AuthProviderOnboarding.tsx b/src/context/AuthProviderOnboarding.tsx deleted file mode 100644 index 42e86670..00000000 --- a/src/context/AuthProviderOnboarding.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { ReactNode } from 'react'; -import { AuthProvider, AuthProviderProps } from 'react-oidc-context'; -import { OIDCConfig, useFrontendConfig } from './FrontendConfigContext.tsx'; -import { WebStorageStateStore } from 'oidc-client-ts'; - -interface AuthProviderOnboardingProps { - children?: ReactNode; -} - -export function AuthProviderOnboarding({ - children, -}: AuthProviderOnboardingProps) { - const { oidcConfig } = useFrontendConfig(); - - const authConfig = buildAuthProviderConfig(oidcConfig); - return {children}; -} - -function buildAuthProviderConfig(oidcConfig: OIDCConfig) { - const userStore = new WebStorageStateStore({ store: window.localStorage }); - - const props: AuthProviderProps = { - authority: oidcConfig.issuerUrl, - client_id: oidcConfig.clientId, - redirect_uri: window.location.origin, - scope: oidcConfig.scopes.join(' '), - userStore: userStore, - automaticSilentRenew: false, // we show a window instead that asks the user to renew the token - onSigninCallback: () => { - window.history.replaceState({}, document.title, window.location.pathname); - }, - }; - return props; -} diff --git a/src/context/FrontendConfigContext.tsx b/src/context/FrontendConfigContext.tsx index 7d800b45..f7d19ee2 100644 --- a/src/context/FrontendConfigContext.tsx +++ b/src/context/FrontendConfigContext.tsx @@ -41,19 +41,10 @@ export const useFrontendConfig = () => { return context; }; -const OidcConfigSchema = z.object({ - clientId: z.string(), - issuerUrl: z.string(), - scopes: z.array(z.string()), -}); -export type OIDCConfig = z.infer; - const FrontendConfigSchema = z.object({ - backendUrl: z.string(), gatewayUrl: z.string(), documentationBaseUrl: z.string(), githubBaseUrl: z.string(), - oidcConfig: OidcConfigSchema, landscape: z.optional(z.nativeEnum(Landscape)), }); type FrontendConfig = z.infer; diff --git a/src/lib/api/types/apiConfig.ts b/src/lib/api/types/apiConfig.ts index 32e53c33..b9ee9b67 100644 --- a/src/lib/api/types/apiConfig.ts +++ b/src/lib/api/types/apiConfig.ts @@ -1,11 +1,3 @@ -type Auth = { - crateAuthorization: string; -}; - -type ProxyConfig = { - apiProxyUrl: string; -}; - type McpConfig = { projectName: string; workspaceName: string; @@ -14,18 +6,12 @@ type McpConfig = { }; //syntax basically combines all the atrributes from the types into one -export type ApiConfig = ProxyConfig & - Auth & { - mcpConfig: McpConfig | undefined; - }; +export type ApiConfig = { + mcpConfig: McpConfig | undefined; +}; -export const generateCrateAPIConfig = ( - apiProxyUrl: string, - token: string, -): ApiConfig => { +export const generateCrateAPIConfig = (): ApiConfig => { return { - crateAuthorization: token, - apiProxyUrl: apiProxyUrl, mcpConfig: undefined, }; }; diff --git a/src/lib/oidc/shared.ts b/src/lib/oidc/shared.ts deleted file mode 100644 index 0d5756b2..00000000 --- a/src/lib/oidc/shared.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { AuthProviderProps } from 'react-oidc-context'; -import { WebStorageStateStore } from 'oidc-client-ts'; -import yaml from 'js-yaml'; - -// Extract the oidc configuration from the kubeconfig for the current context -export function GetAuthPropsForCurrentContext(data: string): AuthProviderProps { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const kubeconfig = yaml.load(data as string) as any; - - const currentContext = kubeconfig['current-context']; - if (!currentContext) { - throw new Error('oidc extraction: current context not found'); - } - const context = LookupContextByName(currentContext, kubeconfig); - return GetAuthPropsForContext(context, kubeconfig); -} - -// Extract the oidc configuration from the kubeconfig for the given context name -export function GetAuthPropsForContextName( - contextName: string, - data: string, -): AuthProviderProps { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const kubeconfig = yaml.load(data as string) as any; - const context = LookupContextByName(contextName, kubeconfig); - return GetAuthPropsForContext(context, kubeconfig); -} - -// Extract the oidc configuration from the kubeconfig for the given context from the users section -export function GetAuthPropsForContext( - context: Context, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - kubeconfig: any, -): AuthProviderProps { - if (!kubeconfig.users) { - throw new Error('oidc extraction: no users in kubeconfig'); - } - let user = lookupUserByName(context.context.user, kubeconfig); - if (!user) { - throw new Error('oidc extraction: user name of context not found'); - } - if (!user.user) { - throw new Error('oidc extraction: user object not found'); - } - user = user.user; - if (!user.exec && user.exec.command !== 'kubectl') { - throw new Error('oidc extraction: only kubectl is supported for now'); - } - const args = user.exec.args; - if (!args) { - throw new Error('oidc extraction: not enough arguments in kubeconfig'); - } - if (args[0] !== 'oidc-login') { - throw new Error('oidc extraction: kubectl exec command is not oidc-login'); - } - const isPKCE = args.includes('--oidc-use-pkce'); - if (!isPKCE) { - throw new Error('oidc extraction: only PKCE is supported for now'); - } - const authority = findArgument(args, '--oidc-issuer-url'); - const clientId = findArgument(args, '--oidc-client-id'); - const scopes = findArguments(args, '--oidc-extra-scope'); - const redirectUri = getDefaultRedirectUri(); - const userStore = new WebStorageStateStore({ store: window.localStorage }); - if (!authority) { - throw new Error('oidc extraction: issuer url not found'); - } - if (!clientId) { - throw new Error('oidc extraction: client id not found'); - } - const props: AuthProviderProps = { - authority: authority, - client_id: clientId, - redirect_uri: redirectUri, - scope: scopes.join(' '), - userStore: userStore, - automaticSilentRenew: false, // we show a window instead that asks the user to renew the token - onSigninCallback: () => { - window.history.replaceState({}, document.title, window.location.pathname); - }, - }; - return props; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function LookupContextByName(contextName: string, kubeconfig: any) { - const contexts = kubeconfig.contexts as Context[]; - for (let i = 0; i < contexts.length; i++) { - if (contexts[i].name === contextName) { - return contexts[i]; - } - } - throw new Error('oidc extraction: context not found'); -} - -// Find the argument that starts with key and return its value -function findArgument(args: string[], key: string): string | undefined { - for (let i = 0; i < args.length; i++) { - if (args[i].startsWith(key)) { - return args[i].split('=')[1]; - } - } - return undefined; -} - -// Find all arguments that start with key and return their values -function findArguments(args: string[], key: string): string[] { - const values: string[] = []; - for (let i = 0; i < args.length; i++) { - if (args[i].startsWith(key)) { - values.push(args[i].split('=')[1]); - } - } - return values; -} -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function lookupUserByName(username: string, kubeconfig: any) { - const users = kubeconfig.users; - for (let i = 0; i < users.length; i++) { - if (users[i].name === username) { - return users[i]; - } - } - return undefined; -} -function getDefaultRedirectUri() { - return window.location.origin; -} - -type Context = { - name: string; - context: { - user: string; - namespace: string; - cluster: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - extensions: any; - }; -}; diff --git a/src/lib/oidc/useUsername.ts b/src/lib/oidc/useUsername.ts deleted file mode 100644 index 30f56c95..00000000 --- a/src/lib/oidc/useUsername.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useAuth } from 'react-oidc-context'; - -// returns the user.profile.sub (subject as in email) of the currently logged in user -export function useAuthSubject() { - const auth = useAuth(); - return auth.user?.profile?.sub; -} diff --git a/src/lib/shared/McpContext.tsx b/src/lib/shared/McpContext.tsx index eda4f197..e30bb808 100644 --- a/src/lib/shared/McpContext.tsx +++ b/src/lib/shared/McpContext.tsx @@ -1,11 +1,6 @@ import { createContext, ReactNode, useContext } from 'react'; import { ControlPlane as ManagedControlPlaneResource } from '../api/types/crate/controlPlanes.ts'; -import { GetAuthPropsForContextName } from '../oidc/shared.ts'; -import { AuthProvider } from 'react-oidc-context'; -import { - ApiConfigContext, - ApiConfigProvider, -} from '../../components/Shared/k8s'; +import { ApiConfigProvider } from '../../components/Shared/k8s'; import useResource from '../api/useApiResource.ts'; import { GetKubeconfig } from '../api/types/crate/getKubeconfig.ts'; @@ -61,14 +56,11 @@ export const McpContextProvider = ({ children, context }: Props) => { function RequireDownstreamLogin(props: { children?: ReactNode }) { const mcp = useContext(McpContext); - const parentApiConfig = useContext(ApiConfigContext); return ( <> - - {children} - + {children} ); } diff --git a/src/main.tsx b/src/main.tsx index efa47ddc..77092524 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -11,7 +11,6 @@ import { DarkModeSystemSwitcher } from './components/Core/DarkModeSystemSwitcher import '.././i18n.ts'; import './utils/i18n/timeAgo'; import { ErrorBoundary, FallbackProps } from 'react-error-boundary'; -import { AuthProviderOnboarding } from './context/AuthProviderOnboarding.tsx'; import { ApolloClientProvider } from './spaces/onboarding/services/ApolloClientProvider/ApolloClientProvider.tsx'; import { IllustratedBanner } from './components/Ui/IllustratedBanner/IllustratedBanner.tsx'; import { useTranslation } from 'react-i18next'; @@ -35,28 +34,26 @@ export function createApp() { {}}> }> - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/spaces/onboarding/auth/AuthContext.tsx b/src/spaces/onboarding/auth/AuthContext.tsx index c9b2acbd..bebe71ed 100644 --- a/src/spaces/onboarding/auth/AuthContext.tsx +++ b/src/spaces/onboarding/auth/AuthContext.tsx @@ -1,14 +1,10 @@ -import { - createContext, - useContext, - useState, - useEffect, - ReactNode, -} from 'react'; +import { createContext, useState, useEffect, ReactNode, use } from 'react'; +import { MeResponseSchema, User } from './auth.schemas'; interface AuthContextType { - isAuthenticated: boolean; isLoading: boolean; + isAuthenticated: boolean; + user: User | null; error: Error | null; login: () => void; logout: () => Promise; @@ -18,6 +14,7 @@ const AuthContext = createContext(null); export function AuthProvider({ children }: { children: ReactNode }) { const [isAuthenticated, setIsAuthenticated] = useState(false); + const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); @@ -27,12 +24,6 @@ export function AuthProvider({ children }: { children: ReactNode }) { const code = params.get('code'); const state = params.get('state'); const iss = params.get('iss'); - const error = params.get('error'); - const errorDescription = params.get('error_description'); - - if (error) { - throw new Error(`Error from IdP: ${error} – ${errorDescription}`); - } if (code && state) { // Construct the URL to forward to the BFF @@ -44,25 +35,51 @@ export function AuthProvider({ children }: { children: ReactNode }) { } window.location.href = forwardUrl.toString(); } - }, [location]); + }, []); // Check the authentication status when the component mounts useEffect(() => { - void checkAuthStatus(); + // Only run checkAuthStatus if not currently handling a redirect + const params = new URLSearchParams(window.location.search); + if (!params.has('code') && !params.has('error')) { + void refreshAuthStatus(); + } }, []); - async function checkAuthStatus() { - try { - const response = await fetch('/api/auth/status'); + async function refreshAuthStatus() { + setIsLoading(true); + setError(null); + try { + const response = await fetch('/api/auth/me'); if (!response.ok) { - throw new Error('Authentication check failed.'); + let errorBody; + try { + errorBody = await response.json(); + } catch (_) { + /* safe to ignore */ + } + throw new Error( + errorBody?.message || + `Authentication check failed with status: ${response.status}`, + ); } const body = await response.json(); - setIsAuthenticated(body.isAuthenticated); + const validationResult = MeResponseSchema.safeParse(body); + if (!validationResult.success) { + throw new Error( + `Auth API response validation failed: ${validationResult.error.flatten()}`, + ); + } + + const { isAuthenticated: apiIsAuthenticated, user: apiUser } = + validationResult.data; + setUser(apiUser); + setIsAuthenticated(apiIsAuthenticated); } catch (err) { setError(err instanceof Error ? err : new Error('Authentication error.')); + setUser(null); setIsAuthenticated(false); } finally { setIsLoading(false); @@ -75,29 +92,39 @@ export function AuthProvider({ children }: { children: ReactNode }) { const logout = async () => { try { - const response = await fetch('/api/auth/logout'); + const response = await fetch('/api/auth/logout', { + method: 'POST', + }); if (!response.ok) { - throw new Error('Logout failed'); + let errorBody; + try { + errorBody = await response.json(); + } catch (_) { + /* safe to ignore */ + } + throw new Error( + errorBody?.message || `Logout failed with status: ${response.status}`, + ); } - await checkAuthStatus(); + await refreshAuthStatus(); } catch (err) { setError(err instanceof Error ? err : new Error('Logout error.')); } }; return ( - {children} - + ); } export const useAuth = () => { - const context = useContext(AuthContext); + const context = use(AuthContext); if (!context) { throw new Error('useAuth must be used within an AuthProvider.'); } diff --git a/src/spaces/onboarding/auth/auth.schemas.ts b/src/spaces/onboarding/auth/auth.schemas.ts new file mode 100644 index 00000000..926c1556 --- /dev/null +++ b/src/spaces/onboarding/auth/auth.schemas.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + +export const UserSchema = z.object({ + email: z.string().email('Invalid email format.'), +}); + +export const MeResponseSchema = z.object({ + isAuthenticated: z.boolean(), + user: UserSchema.nullable(), +}); + +export type User = z.infer; diff --git a/src/spaces/onboarding/services/ApolloClientProvider/ApolloClientProvider.tsx b/src/spaces/onboarding/services/ApolloClientProvider/ApolloClientProvider.tsx index 3361efe4..df1a4e72 100644 --- a/src/spaces/onboarding/services/ApolloClientProvider/ApolloClientProvider.tsx +++ b/src/spaces/onboarding/services/ApolloClientProvider/ApolloClientProvider.tsx @@ -6,11 +6,9 @@ import { } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; import { ReactNode } from 'react'; -import { useAuth } from 'react-oidc-context'; import { useFrontendConfig } from '../../../../context/FrontendConfigContext.tsx'; export function ApolloClientProvider({ children }: { children: ReactNode }) { - const auth = useAuth(); const { gatewayUrl } = useFrontendConfig(); const httpLink = createHttpLink({ @@ -21,7 +19,7 @@ export function ApolloClientProvider({ children }: { children: ReactNode }) { return { headers: { ...headers, - authorization: `bearer ${auth.user?.access_token}`, + //authorization: `bearer ${auth.user?.access_token}`, // TODO }, }; }); diff --git a/src/utils/testing.ts b/src/utils/testing.ts index ab7c96ff..55fabe62 100644 --- a/src/utils/testing.ts +++ b/src/utils/testing.ts @@ -5,7 +5,6 @@ const documentationBaseUrl = 'http://localhost:3000'; const githubBaseUrl = 'https://github.com/example/repo'; export const mockedFrontendConfig = { - backendUrl: 'http://localhost:3000', landscape: Landscape.Local, documentationBaseUrl: documentationBaseUrl, githubBaseUrl: githubBaseUrl, diff --git a/src/views/Login.tsx b/src/views/Login.tsx index b78d3d83..45c603e1 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -1,4 +1,4 @@ -import { useAuth } from 'react-oidc-context'; +import { useAuth } from '../spaces/onboarding/auth/AuthContext.tsx'; import { Button, Card, FlexBox, Text } from '@ui5/webcomponents-react'; import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js'; import './login.css'; @@ -34,7 +34,7 @@ export default function LoginView() {