From 00b48c1f412b3a61feae292820c476d267150161 Mon Sep 17 00:00:00 2001 From: donpat1to Date: Fri, 31 Oct 2025 14:24:56 +0100 Subject: [PATCH] changed dev routing away from faulty proxy --- backend/package.json | 6 +- backend/src/server.ts | 127 +++++++++++++++++++++++++------ frontend/vite.config.ts | 8 +- package-lock.json | 161 +++++++++++++++++++++++++++------------- 4 files changed, 223 insertions(+), 79 deletions(-) diff --git a/backend/package.json b/backend/package.json index c98b1df..d274aab 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,7 +4,8 @@ "type": "module", "scripts": { "dev": "npm run build && npx tsx src/server.ts", - "build": "tsc", + "dev:single": "cross-env NODE_ENV=development npx tsx src/server.ts", + "build": "tsc", "start": "node dist/server.js", "prestart": "npm run build", "test": "jest", @@ -32,6 +33,7 @@ "@types/jest": "^29.5.0", "ts-node": "^10.9.0", "typescript": "^5.0.0", - "tsx": "^4.0.0" + "tsx": "^4.0.0", + "cross-env": "10.1.0" } } \ No newline at end of file diff --git a/backend/src/server.ts b/backend/src/server.ts index 4891d92..962827a 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -5,6 +5,7 @@ import { fileURLToPath } from 'url'; import { initializeDatabase } from './scripts/initializeDatabase.js'; import fs from 'fs'; import helmet from 'helmet'; +import type { ViteDevServer } from 'vite'; // Route imports import authRoutes from './routes/auth.js'; @@ -22,6 +23,62 @@ const app = express(); const PORT = 3002; const isDevelopment = process.env.NODE_ENV === 'development'; +let vite: ViteDevServer | undefined; + +if (isDevelopment) { + // Dynamically import and setup Vite middleware + const setupViteDevServer = async () => { + try { + const { createServer } = await import('vite'); + vite = await createServer({ + server: { middlewareMode: true }, + appType: 'spa' + }); + app.use(vite.middlewares); + console.log('๐Ÿ”ง Vite dev server integrated with Express'); + } catch (error) { + console.warn('โš ๏ธ Vite integration failed, using static files:', error); + } + }; + setupViteDevServer(); +} + +const configureStaticFiles = () => { + const possiblePaths = [ + // Production path (Docker) + '/app/frontend-build', + // Development paths + path.resolve(__dirname, '../../frontend/dist'), + path.resolve(__dirname, '../frontend/dist'), // Added for monorepo + path.resolve(process.cwd(), 'frontend/dist'), // Current directory + path.resolve(process.cwd(), '../frontend/dist'), // Parent directory + // Vite dev server fallback + ...(isDevelopment ? [path.resolve(__dirname, '../../frontend')] : []) + ]; + + for (const testPath of possiblePaths) { + try { + if (fs.existsSync(testPath)) { + // In development, check for dist or direct source + if (fs.existsSync(path.join(testPath, 'index.html'))) { + console.log('โœ… Found frontend at:', testPath); + app.use(express.static(testPath)); + return testPath; + } + // For Vite dev server in development + else if (isDevelopment && fs.existsSync(path.join(testPath, 'index.html'))) { + console.log('๐Ÿ”ง Development: Serving frontend source from:', testPath); + app.use(express.static(testPath)); + return testPath; + } + } + } catch (error) { + // Silent catch + } + } + return null; +}; + app.set('trust proxy', true); // Security configuration @@ -81,8 +138,8 @@ app.use('/api/scheduling', schedulingRoutes); // Health route app.get('/api/health', (req: express.Request, res: express.Response) => { - res.json({ - status: 'OK', + res.json({ + status: 'OK', message: 'Backend lรคuft!', timestamp: new Date().toISOString(), mode: process.env.NODE_ENV || 'development' @@ -118,6 +175,7 @@ const findFrontendBuildPath = (): string | null => { }; const frontendBuildPath = findFrontendBuildPath(); +const staticPath = configureStaticFiles(); if (frontendBuildPath) { app.use(express.static(frontendBuildPath)); @@ -130,46 +188,71 @@ if (frontendBuildPath) { } // Root route -app.get('/', (req, res) => { - if (!frontendBuildPath) { - if (isDevelopment) { - return res.redirect('http://localhost:3003'); +app.get('/', async (req, res) => { + // In development with Vite middleware + if (vite) { + try { + const template = fs.readFileSync( + path.resolve(__dirname, '../../frontend/index.html'), + 'utf-8' + ); + const html = await vite.transformIndexHtml(req.url, template); + res.send(html); + } catch (error) { + res.status(500).send('Vite dev server error'); } - return res.status(500).send('Frontend build not found'); + return; } - + + // Fallback to static file serving + if (!frontendBuildPath) { + return res.status(500).send('Frontend not available'); + } + const indexPath = path.join(frontendBuildPath, 'index.html'); res.sendFile(indexPath); }); // Client-side routing fallback -app.get('*', (req, res) => { +app.get('*', async (req, res, next) => { if (req.path.startsWith('/api/')) { - return res.status(404).json({ error: 'API endpoint not found' }); + return next(); // API routes handled normally } - - if (!frontendBuildPath) { - if (isDevelopment) { - return res.redirect(`http://localhost:3003${req.path}`); + + // Vite dev server handling + if (vite) { + try { + const template = fs.readFileSync( + path.resolve(__dirname, '../../frontend/index.html'), + 'utf-8' + ); + const html = await vite.transformIndexHtml(req.url, template); + return res.send(html); + } catch (error) { + console.error('Vite transformation error:', error); } - return res.status(500).json({ error: 'Frontend application not available' }); } - - const indexPath = path.join(frontendBuildPath, 'index.html'); - res.sendFile(indexPath); + + // Static file fallback + if (staticPath) { + const indexPath = path.join(staticPath, 'index.html'); + return res.sendFile(indexPath); + } + + res.status(500).send('Frontend not available'); }); // Error handling app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => { console.error('Error:', err); - + if (process.env.NODE_ENV === 'production') { - res.status(500).json({ + res.status(500).json({ error: 'Internal server error', message: 'Something went wrong' }); } else { - res.status(500).json({ + res.status(500).json({ error: 'Internal server error', message: err.message, stack: err.stack @@ -196,7 +279,7 @@ const initializeApp = async () => { if (frontendBuildPath) { console.log(`๐Ÿ“ Frontend: http://localhost:${PORT}`); } else if (isDevelopment) { - console.log(`๐Ÿ“ Frontend (Vite): http://localhost:3003`); + console.log(`๐Ÿ“ Frontend (Vite): http://localhost:3002`); } console.log(`๐Ÿ“ API: http://localhost:${PORT}/api`); }); diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index f765ea1..9080687 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -14,16 +14,16 @@ export default defineConfig(({ mode }) => { NODE_ENV: mode, ENABLE_PRO: env.ENABLE_PRO || 'false', VITE_APP_TITLE: env.APP_TITLE || 'Shift Planning App', - VITE_API_URL: isProduction ? '/api' : '/api', + VITE_API_URL: isProduction ? '/api' : 'http://localhost:3002/api', } return { plugins: [react()], - server: { - port: 3003, + server: isDevelopment ? undefined : { + port: 3002, host: true, - //open: isDevelopment, + open: true, proxy: { '/api': { target: 'http://localhost:3002', diff --git a/package-lock.json b/package-lock.json index ceb0797..a955e1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "@types/jest": "^29.5.0", "@types/jsonwebtoken": "^9.0.2", "@types/uuid": "^9.0.2", + "cross-env": "10.1.0", "ts-node": "^10.9.0", "tsx": "^4.0.0", "typescript": "^5.0.0" @@ -259,6 +260,7 @@ "backend/node_modules/@types/node": { "version": "24.7.0", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.14.0" } @@ -890,11 +892,6 @@ "license": "MIT", "optional": true }, - "backend/node_modules/isexe": { - "version": "2.0.0", - "license": "ISC", - "optional": true - }, "backend/node_modules/jest-diff": { "version": "29.7.0", "dev": true, @@ -1777,20 +1774,6 @@ "dev": true, "license": "MIT" }, - "backend/node_modules/which": { - "version": "2.0.2", - "license": "ISC", - "optional": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "backend/node_modules/wide-align": { "version": "1.1.5", "license": "ISC", @@ -1874,6 +1857,7 @@ "version": "7.28.5", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2116,6 +2100,13 @@ "node": ">=6.9.0" } }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "dev": true, + "license": "MIT" + }, "node_modules/@esbuild/win32-x64": { "version": "0.21.5", "cpu": [ @@ -2297,10 +2288,6 @@ "win32" ] }, - "node_modules/@schichtenplaner/premium": { - "resolved": "premium", - "link": true - }, "node_modules/@sinclair/typebox": { "version": "0.34.41", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", @@ -2321,7 +2308,6 @@ "integrity": "sha512-hcFZIjW8yQz8O8//2WTIXylm5Xsgc+lW9ISLgUk1xGmptIJQRdlhVIXCpSyLrQaaRiyhQRaVg7l3BD9S216BHw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=14.0.0" }, @@ -2565,7 +2551,6 @@ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" @@ -2576,8 +2561,7 @@ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.8", @@ -2639,6 +2623,7 @@ "version": "19.2.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2719,7 +2704,6 @@ "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", @@ -2737,7 +2721,6 @@ "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", @@ -2765,7 +2748,6 @@ "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tinyrainbow": "^2.0.0" }, @@ -2779,7 +2761,6 @@ "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tinyspy": "^4.0.3" }, @@ -2793,7 +2774,6 @@ "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", @@ -2877,7 +2857,6 @@ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" } @@ -2888,7 +2867,6 @@ "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "tslib": "^2.0.1" }, @@ -2981,6 +2959,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -3065,7 +3044,6 @@ "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -3100,7 +3078,6 @@ "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 16" } @@ -3201,6 +3178,39 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/cross-env": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "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", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", @@ -3245,7 +3255,6 @@ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -3407,7 +3416,6 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3422,7 +3430,6 @@ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "^1.0.0" } @@ -3846,6 +3853,13 @@ "node": ">=0.12.0" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true, + "license": "ISC" + }, "node_modules/jest-diff": { "version": "30.2.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", @@ -3980,8 +3994,7 @@ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lru-cache": { "version": "5.1.1", @@ -4007,7 +4020,6 @@ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } @@ -4203,6 +4215,16 @@ "node": ">= 0.8" } }, + "node_modules/path-key": { + "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" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -4215,7 +4237,6 @@ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 14.16" } @@ -4346,6 +4367,7 @@ "node_modules/react": { "version": "19.2.0", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -4353,6 +4375,7 @@ "node_modules/react-dom": { "version": "19.2.0", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -4409,7 +4432,6 @@ "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", @@ -4586,6 +4608,29 @@ "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "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" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -4725,7 +4770,6 @@ "integrity": "sha512-WQMfNsbyHO8fx5bLatsLATzvFwzG42xHnq8W9s2HzjhGzQ2Pp77k7nRWXMuRNvvv+4ypKhJdqeDl8S9kwWuz2A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^1.6.0", @@ -4761,7 +4805,6 @@ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -4801,6 +4844,7 @@ "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -4819,8 +4863,7 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tinyglobby": { "version": "0.2.15", @@ -4843,7 +4886,6 @@ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=14.0.0" } @@ -4854,7 +4896,6 @@ "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=14.0.0" } @@ -4905,6 +4946,7 @@ "version": "5.9.3", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4987,6 +5029,7 @@ "version": "6.4.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -5111,13 +5154,28 @@ "@esbuild/win32-x64": "0.25.11" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -5142,6 +5200,7 @@ "premium": { "name": "@schichtenplaner/premium", "version": "1.0.0", + "extraneous": true, "workspaces": [ "backendPRO", "frontendPRO"