From 7702310a9c16d78d2dbd906169ff40c4003b9010 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Fri, 27 Feb 2026 19:06:06 +0100 Subject: [PATCH] chore: remove Directus CMS and related dependencies --- apps/sample-website/package.json | 5 +- docker-compose.yml | 56 - package.json | 10 - packages/acquisition-manager/package.json | 34 - packages/acquisition-manager/src/index.ts | 19 - packages/acquisition-manager/src/module.vue | 468 --- packages/acquisition/build.mjs | 55 - packages/acquisition/package.json | 31 - packages/acquisition/src/index.ts | 236 -- packages/cli/src/index.ts | 168 +- packages/cms-infra/Dockerfile | 11 - packages/cms-infra/database/RELOAD_TEST | 0 packages/cms-infra/database/data.db | Bin 360448 -> 0 bytes packages/cms-infra/docker-compose.yml | 53 - packages/cms-infra/package.json | 18 - packages/cms-infra/schema/current.yaml | 1203 -------- packages/cms-infra/schema/current_v2.yaml | 2046 ------------- packages/cms-infra/schema/snapshot.yaml | 2383 --------------- packages/company-manager/package.json | 34 - packages/company-manager/src/index.ts | 14 - packages/company-manager/src/module.vue | 224 -- packages/concept-engine/src/_test_pipeline.ts | 53 +- packages/concept-engine/src/cli.ts | 240 +- packages/concept-engine/src/dummy.test.ts | 7 + packages/concept-engine/src/llm-client.ts | 183 +- packages/concept-engine/src/pipeline.ts | 473 +-- packages/concept-engine/src/scraper.ts | 697 +++-- packages/content-engine/src/orchestrator.ts | 34 +- packages/customer-manager/package.json | 34 - packages/customer-manager/src/index.ts | 14 - packages/customer-manager/src/module.vue | 538 ---- .../directus-extension-toolkit/package.json | 35 - .../src/MintelManagerLayout.vue | 102 - .../src/MintelSelect.vue | 62 - .../src/MintelStatCard.vue | 84 - .../directus-extension-toolkit/src/index.ts | 3 - .../directus-extension-toolkit/vite.config.ts | 24 - .../estimation-engine/src/_test_pipeline.ts | 74 +- packages/estimation-engine/src/cli.ts | 103 +- packages/estimation-engine/src/llm-client.ts | 172 +- packages/estimation-engine/src/pipeline.ts | 410 +-- packages/estimation-engine/src/types.ts | 122 +- packages/estimation-engine/src/validators.ts | 552 ++-- packages/feedback-commander/package.json | 31 - packages/feedback-commander/src/index.ts | 14 - packages/feedback-commander/src/module.vue | 731 ----- packages/image-processor/package.json | 1 + packages/image-processor/src/processor.ts | 1 - packages/image-processor/tsup.config.ts | 28 +- packages/infra/package.json | 1 - .../website/scripts/setup-directus.ts | 53 - .../templates/website/src/lib/directus.ts | 12 - .../journaling/src/clients/data-commons.ts | 2 +- packages/journaling/src/clients/trends.ts | 2 +- packages/next-feedback/package.json | 1 - packages/next-feedback/src/handlers/index.ts | 95 +- packages/next-utils/package.json | 1 - packages/next-utils/src/directus.ts | 72 - packages/next-utils/src/index.ts | 1 - packages/pdf-library/package.json | 1 - packages/people-manager/package.json | 34 - packages/people-manager/src/index.ts | 14 - packages/people-manager/src/module.vue | 317 -- packages/unified-dashboard/package.json | 31 - packages/unified-dashboard/src/index.ts | 14 - packages/unified-dashboard/src/module.vue | 146 - pnpm-lock.yaml | 2683 +---------------- scripts/cms-apply.sh | 77 - scripts/cms-reconcile.sh | 56 - scripts/cms-snapshot.sh | 23 - scripts/cms-up.sh | 27 - scripts/fix_snapshot_v3.py | 96 - scripts/patch-cms.sh | 116 - scripts/sync-directus.sh | 123 - scripts/sync-extensions.sh | 138 - scripts/validate-cms.sh | 91 - scripts/validate-extensions.sh | 67 - scripts/validate-sdk-imports.sh | 100 - scripts/verify-extensions-live.sh | 46 - 79 files changed, 1733 insertions(+), 14597 deletions(-) delete mode 100644 packages/acquisition-manager/package.json delete mode 100644 packages/acquisition-manager/src/index.ts delete mode 100644 packages/acquisition-manager/src/module.vue delete mode 100644 packages/acquisition/build.mjs delete mode 100644 packages/acquisition/package.json delete mode 100644 packages/acquisition/src/index.ts delete mode 100644 packages/cms-infra/Dockerfile delete mode 100644 packages/cms-infra/database/RELOAD_TEST delete mode 100644 packages/cms-infra/database/data.db delete mode 100644 packages/cms-infra/docker-compose.yml delete mode 100644 packages/cms-infra/package.json delete mode 100644 packages/cms-infra/schema/current.yaml delete mode 100644 packages/cms-infra/schema/current_v2.yaml delete mode 100644 packages/cms-infra/schema/snapshot.yaml delete mode 100644 packages/company-manager/package.json delete mode 100644 packages/company-manager/src/index.ts delete mode 100644 packages/company-manager/src/module.vue create mode 100644 packages/concept-engine/src/dummy.test.ts delete mode 100644 packages/customer-manager/package.json delete mode 100644 packages/customer-manager/src/index.ts delete mode 100644 packages/customer-manager/src/module.vue delete mode 100644 packages/directus-extension-toolkit/package.json delete mode 100644 packages/directus-extension-toolkit/src/MintelManagerLayout.vue delete mode 100644 packages/directus-extension-toolkit/src/MintelSelect.vue delete mode 100644 packages/directus-extension-toolkit/src/MintelStatCard.vue delete mode 100644 packages/directus-extension-toolkit/src/index.ts delete mode 100644 packages/directus-extension-toolkit/vite.config.ts delete mode 100644 packages/feedback-commander/package.json delete mode 100644 packages/feedback-commander/src/index.ts delete mode 100644 packages/feedback-commander/src/module.vue delete mode 100644 packages/infra/templates/website/scripts/setup-directus.ts delete mode 100644 packages/infra/templates/website/src/lib/directus.ts delete mode 100644 packages/next-utils/src/directus.ts delete mode 100644 packages/people-manager/package.json delete mode 100644 packages/people-manager/src/index.ts delete mode 100644 packages/people-manager/src/module.vue delete mode 100644 packages/unified-dashboard/package.json delete mode 100644 packages/unified-dashboard/src/index.ts delete mode 100644 packages/unified-dashboard/src/module.vue delete mode 100755 scripts/cms-apply.sh delete mode 100755 scripts/cms-reconcile.sh delete mode 100755 scripts/cms-snapshot.sh delete mode 100755 scripts/cms-up.sh delete mode 100644 scripts/fix_snapshot_v3.py delete mode 100755 scripts/patch-cms.sh delete mode 100755 scripts/sync-directus.sh delete mode 100755 scripts/sync-extensions.sh delete mode 100755 scripts/validate-cms.sh delete mode 100644 scripts/validate-extensions.sh delete mode 100755 scripts/validate-sdk-imports.sh delete mode 100755 scripts/verify-extensions-live.sh diff --git a/apps/sample-website/package.json b/apps/sample-website/package.json index 2aa468b..fa8af8b 100644 --- a/apps/sample-website/package.json +++ b/apps/sample-website/package.json @@ -15,11 +15,12 @@ "pagespeed:test": "mintel pagespeed" }, "dependencies": { + "@mintel/image-processor": "workspace:*", + "@mintel/next-observability": "workspace:*", "@mintel/next-utils": "workspace:*", "@mintel/observability": "workspace:*", - "@mintel/next-observability": "workspace:*", - "@mintel/image-processor": "workspace:*", "@sentry/nextjs": "10.38.0", + "@tensorflow/tfjs-backend-wasm": "^4.22.0", "next": "16.1.6", "next-intl": "^4.8.2", "react": "^19.0.0", diff --git a/docker-compose.yml b/docker-compose.yml index 9b59505..7b4952b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,8 +11,6 @@ services: restart: always networks: - infra - environment: - - DIRECTUS_URL=${DIRECTUS_URL:-http://directus:8055} env_file: - .env ports: @@ -24,60 +22,6 @@ services: - "caddy=http://${TRAEFIK_HOST:-acquisition.localhost}" - "caddy.reverse_proxy={{upstreams 3000}}" - directus: - image: registry.infra.mintel.me/mintel/directus:${IMAGE_TAG:-latest} - healthcheck: - test: [ "CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8055/server/health" ] - interval: 30s - timeout: 10s - retries: 3 - start_period: 5s - restart: always - networks: - - infra - env_file: - - .env - environment: - KEY: ${DIRECTUS_KEY:-mintel-key} - SECRET: ${DIRECTUS_SECRET:-mintel-secret} - ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL:-admin@mintel.me} - ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD:-mintel-admin} - DB_CLIENT: 'pg' - DB_HOST: 'at-mintel-directus-db' - DB_PORT: '5432' - DB_DATABASE: ${DIRECTUS_DB_NAME:-directus} - DB_USER: ${DIRECTUS_DB_USER:-directus} - DB_PASSWORD: ${DIRECTUS_DB_PASSWORD:-mintel-db-pass} - WEBSOCKETS_ENABLED: 'true' - PUBLIC_URL: ${DIRECTUS_URL:-http://localhost:8055} - ports: - - "8055:8055" - volumes: - - ./directus/uploads:/directus/uploads - - ./directus/extensions:/directus/extensions - - ./directus/schema:/directus/schema - labels: - - "traefik.enable=true" - - "traefik.http.routers.sample-website-directus.rule=Host(`${DIRECTUS_HOST:-cms.sample-website.localhost}`)" - - "traefik.http.services.sample-website-directus.loadbalancer.server.port=8055" - - "caddy=http://${DIRECTUS_HOST:-cms.at.localhost}" - - "caddy.reverse_proxy={{upstreams 8055}}" - - at-mintel-directus-db: - image: postgres:15-alpine - restart: always - networks: - - infra - environment: - POSTGRES_DB: ${DIRECTUS_DB_NAME:-directus} - POSTGRES_USER: ${DIRECTUS_DB_USER:-directus} - POSTGRES_PASSWORD: ${DIRECTUS_DB_PASSWORD:-mintel-db-pass} - volumes: - - directus-db-data:/var/lib/postgresql/data - networks: infra: external: true - -volumes: - directus-db-data: diff --git a/package.json b/package.json index b4c5a56..d591506 100644 --- a/package.json +++ b/package.json @@ -10,16 +10,6 @@ "changeset": "changeset", "version-packages": "changeset version", "sync-versions": "tsx scripts/sync-versions.ts --", - "cms:dev": "pnpm --filter @mintel/cms-infra dev", - "cms:up": "pnpm --filter @mintel/cms-infra up", - "cms:down": "pnpm --filter @mintel/cms-infra down", - "cms:logs": "pnpm --filter @mintel/cms-infra logs", - "cms:schema:snapshot": "./scripts/cms-snapshot.sh", - "cms:schema:apply": "./scripts/cms-apply.sh local", - "cms:schema:apply:infra": "./scripts/cms-apply.sh infra", - "cms:sync:push": "./scripts/sync-directus.sh push infra", - "cms:sync:pull": "./scripts/sync-directus.sh pull infra", - "build:extensions": "./scripts/sync-extensions.sh", "release": "pnpm build && changeset publish", "release:tag": "pnpm build && pnpm -r publish --no-git-checks --access public", "prepare": "husky" diff --git a/packages/acquisition-manager/package.json b/packages/acquisition-manager/package.json deleted file mode 100644 index 6ac5683..0000000 --- a/packages/acquisition-manager/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "acquisition-manager", - "description": "Custom High-Fidelity Management for Directus", - "icon": "extension", - "version": "1.8.21", - "type": "module", - "keywords": [ - "directus", - "directus-extension", - "directus-extension-module" - ], - "directus:extension": { - "type": "module", - "path": "dist/index.js", - "source": "src/index.ts", - "host": "app", - "name": "acquisition manager" - }, - "scripts": { - "build": "directus-extension build", - "dev": "directus-extension build -w" - }, - "dependencies": { - "@mintel/directus-extension-toolkit": "workspace:*" - }, - "devDependencies": { - "@directus/extensions-sdk": "11.0.2", - "vue": "^3.4.0" - }, - "repository": { - "type": "git", - "url": "https://git.infra.mintel.me/mmintel/at-mintel.git" - } -} diff --git a/packages/acquisition-manager/src/index.ts b/packages/acquisition-manager/src/index.ts deleted file mode 100644 index cfd5aee..0000000 --- a/packages/acquisition-manager/src/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { defineModule } from "@directus/extensions-sdk"; -import ModuleComponent from "./module.vue"; - -export default defineModule({ - id: "acquisition-manager", - name: "Acquisition", - icon: "auto_awesome", - routes: [ - { - path: "", - component: ModuleComponent, - }, - { - path: ":id", - component: ModuleComponent, - props: true - } - ], -}); diff --git a/packages/acquisition-manager/src/module.vue b/packages/acquisition-manager/src/module.vue deleted file mode 100644 index a046785..0000000 --- a/packages/acquisition-manager/src/module.vue +++ /dev/null @@ -1,468 +0,0 @@ - - - - - diff --git a/packages/acquisition/build.mjs b/packages/acquisition/build.mjs deleted file mode 100644 index 917688d..0000000 --- a/packages/acquisition/build.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import { build } from 'esbuild'; -import { resolve, dirname } from 'path'; -import { mkdirSync } from 'fs'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const entryPoint = resolve(__dirname, 'src/index.ts'); -const outfile = resolve(__dirname, 'dist/index.js'); - -try { - mkdirSync(dirname(outfile), { recursive: true }); -} catch { - // ignore -} - -console.log(`Building from ${entryPoint} to ${outfile}...`); - -build({ - entryPoints: [entryPoint], - bundle: true, - platform: 'node', - target: 'node18', - outfile: outfile, - jsx: 'automatic', - format: 'esm', - // footer: { - // js: "module.exports = module.exports.default || module.exports;", - // }, - loader: { - '.tsx': 'tsx', - '.ts': 'ts', - '.js': 'js', - }, - external: ["canvas", "fs", "path", "os", "http", "https", "zlib", "stream", "util", "url", "net", "tls", "crypto"], - plugins: [{ - name: 'mock-canvas', - setup(build) { - build.onResolve({ filter: /^canvas/ }, args => ({ path: args.path, namespace: 'mock-canvas' })); - build.onLoad({ filter: /.*/, namespace: 'mock-canvas' }, () => ({ contents: 'export default {};', loader: 'js' })); - } - }, { - name: 'mock-jsdom', - setup(build) { - build.onResolve({ filter: /^jsdom/ }, args => ({ path: args.path, namespace: 'mock-jsdom' })); - build.onLoad({ filter: /.*/, namespace: 'mock-jsdom' }, () => ({ contents: 'export default {};', loader: 'js' })); - } - }] -}).then(() => { - console.log("Build succeeded!"); -}).catch((e) => { - console.error("Build failed:", e); - process.exit(1); -}); diff --git a/packages/acquisition/package.json b/packages/acquisition/package.json deleted file mode 100644 index ce2f0c7..0000000 --- a/packages/acquisition/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "acquisition", - "version": "1.8.21", - "type": "module", - "directus:extension": { - "type": "endpoint", - "path": "dist/index.js", - "source": "src/index.ts", - "host": "^11.0.0" - }, - "scripts": { - "build": "node build.mjs", - "dev": "node build.mjs --watch" - }, - "devDependencies": { - "@directus/extensions-sdk": "11.0.2", - "@mintel/pdf": "workspace:*", - "@mintel/mail": "workspace:*", - "esbuild": "^0.25.0", - "typescript": "^5.6.3" - }, - "dependencies": { - "jquery": "^3.7.1", - "react": "^19.2.4", - "react-dom": "^19.2.4" - }, - "repository": { - "type": "git", - "url": "https://git.infra.mintel.me/mmintel/at-mintel.git" - } -} diff --git a/packages/acquisition/src/index.ts b/packages/acquisition/src/index.ts deleted file mode 100644 index de855f3..0000000 --- a/packages/acquisition/src/index.ts +++ /dev/null @@ -1,236 +0,0 @@ -import { defineEndpoint } from "@directus/extensions-sdk"; -import { AcquisitionService, PdfEngine } from "@mintel/pdf/server"; -import { - render, - SiteAuditTemplate, - ProjectEstimateTemplate, -} from "@mintel/mail"; -import { createElement } from "react"; -import * as path from "path"; -import * as fs from "fs"; - -export default defineEndpoint((router, { services, env }) => { - const { ItemsService, MailService } = services; - - router.get("/ping", (req, res) => res.send("pong")); - - router.post("/audit/:id", async (req: any, res: any) => { - const { id } = req.params; - const leadsService = new ItemsService("leads", { - schema: req.schema, - accountability: req.accountability, - }); - - try { - const lead = await leadsService.readOne(id); - if (!lead) return res.status(404).send({ error: "Lead not found" }); - - await leadsService.updateOne(id, { status: "auditing" }); - - const acqService = new AcquisitionService(env.OPENROUTER_API_KEY); - const result = await acqService.runFullSequence( - lead.website_url, - lead.briefing, - lead.comments, - ); - - await leadsService.updateOne(id, { - status: "audit_ready", - ai_state: result.state, - audit_context: JSON.stringify(result.usage), - }); - - res.send({ success: true, result }); - } catch (error: any) { - console.error("Audit failed:", error); - await leadsService.updateOne(id, { - status: "new", - comments: `Audit failed: ${error.message}`, - }); - res.status(500).send({ error: error.message }); - } - }); - - router.post("/audit-email/:id", async (req: any, res: any) => { - const { id } = req.params; - const { ItemsService, MailService } = services; - const leadsService = new ItemsService("leads", { - schema: req.schema, - accountability: req.accountability, - }); - const _peopleService = new ItemsService("people", { - schema: req.schema, - accountability: req.accountability, - }); - const companiesService = new ItemsService("companies", { - schema: req.schema, - accountability: req.accountability, - }); - const mailService = new MailService({ - schema: req.schema, - accountability: req.accountability, - }); - - try { - const lead = await leadsService.readOne(id, { - fields: ["*", "company.*", "contact_person.*"], - }); - if (!lead || !lead.ai_state) - return res.status(400).send({ error: "Lead or Audit not ready" }); - - let recipientEmail = lead.contact_email; - let companyName = lead.company?.name || lead.company_name; - - if (lead.contact_person) { - recipientEmail = lead.contact_person.email || recipientEmail; - - if (lead.contact_person.company) { - const personCompany = await companiesService.readOne( - lead.contact_person.company, - ); - companyName = personCompany?.name || companyName; - } - } - - if (!recipientEmail) - return res.status(400).send({ error: "No recipient email found" }); - - const auditHighlights = [ - `Projekt-Typ: ${lead.ai_state.projectType === "website" ? "Website" : "Web App"}`, - ...(lead.ai_state.sitemap || []) - .slice(0, 3) - .map((item: any) => `Potenzial in: ${item.category}`), - ]; - - const html = await render( - createElement(SiteAuditTemplate, { - companyName: companyName, - websiteUrl: lead.website_url, - auditHighlights, - }), - ); - - await mailService.send({ - to: recipientEmail, - subject: `Analyse Ihrer Webpräsenz: ${companyName}`, - html, - }); - - await leadsService.updateOne(id, { - status: "contacted", - last_contacted_at: new Date().toISOString(), - }); - - res.send({ success: true }); - } catch (error: any) { - console.error("Audit Email failed:", error); - res.status(500).send({ error: error.message }); - } - }); - - router.post("/estimate/:id", async (req: any, res: any) => { - const { id } = req.params; - const leadsService = new ItemsService("leads", { - schema: req.schema, - accountability: req.accountability, - }); - - try { - const lead = await leadsService.readOne(id); - if (!lead || !lead.ai_state) - return res.status(400).send({ error: "Lead or AI state not found" }); - - const pdfEngine = new PdfEngine(); - const filename = `estimate_${id}_${Date.now()}.pdf`; - const storageRoot = env.STORAGE_LOCAL_ROOT || "./storage"; - const outputPath = path.join(storageRoot, filename); - - await pdfEngine.generateEstimatePdf(lead.ai_state, outputPath); - - await leadsService.updateOne(id, { - audit_pdf_path: filename, - }); - - res.send({ success: true, filename }); - } catch (error: any) { - console.error("PDF Generation failed:", error); - res.status(500).send({ error: error.message }); - } - }); - - router.post("/estimate-email/:id", async (req: any, res: any) => { - const { id } = req.params; - const leadsService = new ItemsService("leads", { - schema: req.schema, - accountability: req.accountability, - }); - const _peopleService = new ItemsService("people", { - schema: req.schema, - accountability: req.accountability, - }); - const companiesService = new ItemsService("companies", { - schema: req.schema, - accountability: req.accountability, - }); - const mailService = new MailService({ - schema: req.schema, - accountability: req.accountability, - }); - - try { - const lead = await leadsService.readOne(id, { - fields: ["*", "company.*", "contact_person.*"], - }); - if (!lead || !lead.audit_pdf_path) - return res.status(400).send({ error: "PDF not generated" }); - - let recipientEmail = lead.contact_email; - let companyName = lead.company?.name || lead.company_name; - - if (lead.contact_person) { - recipientEmail = lead.contact_person.email || recipientEmail; - - if (lead.contact_person.company) { - const personCompany = await companiesService.readOne( - lead.contact_person.company, - ); - companyName = personCompany?.name || companyName; - } - } - - if (!recipientEmail) - return res.status(400).send({ error: "No recipient email found" }); - - const html = await render( - createElement(ProjectEstimateTemplate, { - companyName: companyName, - }), - ); - - const storageRoot = env.STORAGE_LOCAL_ROOT || "./storage"; - const attachmentPath = path.join(storageRoot, lead.audit_pdf_path); - - await mailService.send({ - to: recipientEmail, - subject: `Ihre Projekt-Schätzung: ${companyName}`, - html, - attachments: [ - { - filename: `Angebot_${companyName}.pdf`, - content: fs.readFileSync(attachmentPath), - }, - ], - }); - - await leadsService.updateOne(id, { - status: "contacted", - last_contacted_at: new Date().toISOString(), - }); - - res.send({ success: true }); - } catch (error: any) { - console.error("Estimate Email failed:", error); - res.status(500).send({ error: error.message }); - } - }); -}); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 467d089..8faabae 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -36,153 +36,15 @@ program console.log( chalk.yellow(` 📱 App: http://localhost:3000 -🗄️ CMS: http://localhost:8055/admin 🚦 Traefik: http://localhost:8080 `), ); execSync( - "docker compose down --remove-orphans && docker compose up -d app directus at-mintel-directus-db", + "docker compose down --remove-orphans && docker compose up -d app", { stdio: "inherit" }, ); }); -const directus = program - .command("directus") - .description("Directus management commands"); - -directus - .command("bootstrap") - .description("Setup Directus branding and settings") - .action(async () => { - const { execSync } = await import("child_process"); - console.log(chalk.blue("🎨 Bootstrapping Directus...")); - execSync("npx tsx --env-file=.env scripts/setup-directus.ts", { - stdio: "inherit", - }); - }); - -directus - .command("bootstrap-feedback") - .description("Setup Directus collections and flows for Feedback") - .action(async () => { - const { execSync } = await import("child_process"); - console.log(chalk.blue("📧 Bootstrapping Visual Feedback System...")); - // Use the logic from setup-feedback-hardened.ts - const bootstrapScript = ` -import { createDirectus, rest, authentication, createCollection, createDashboard, createPanel, createItems, createPermission, readPolicies, readRoles, readUsers } from '@directus/sdk'; - -async function setup() { - const url = process.env.DIRECTUS_URL || 'http://localhost:8055'; - const email = process.env.DIRECTUS_ADMIN_EMAIL; - const password = process.env.DIRECTUS_ADMIN_PASSWORD; - - if (!email || !password) { - console.error('❌ DIRECTUS_ADMIN_EMAIL or DIRECTUS_ADMIN_PASSWORD not set'); - process.exit(1); - } - - const client = createDirectus(url).with(authentication('json')).with(rest()); - - try { - console.log('🔑 Authenticating...'); - await client.login(email, password); - - const roles = await client.request(readRoles()); - const adminRole = roles.find(r => r.name === 'Administrator'); - const policies = await client.request(readPolicies()); - const adminPolicy = policies.find(p => p.name === 'Administrator'); - - console.log('🏗️ Creating Collection "visual_feedback"...'); - try { - await client.request(createCollection({ - collection: 'visual_feedback', - meta: { icon: 'feedback', display_template: '{{user_name}}: {{text}}' }, - fields: [ - { field: 'id', type: 'uuid', schema: { is_primary_key: true } }, - { field: 'status', type: 'string', schema: { default_value: 'open' }, meta: { interface: 'select-dropdown' } }, - { field: 'url', type: 'string' }, - { field: 'selector', type: 'string' }, - { field: 'x', type: 'float' }, - { field: 'y', type: 'float' }, - { field: 'type', type: 'string' }, - { field: 'text', type: 'text' }, - { field: 'user_name', type: 'string' }, - { field: 'user_identity', type: 'string' }, - { field: 'screenshot', type: 'uuid', meta: { interface: 'file' } }, - { field: 'date_created', type: 'timestamp', schema: { default_value: 'NOW()' } } - ] - } as any)); - } catch (_e) { console.log(' (Collection might already exist)'); } - - try { - await client.request(createCollection({ - collection: 'visual_feedback_comments', - meta: { icon: 'comment' }, - fields: [ - { field: 'id', type: 'integer', schema: { is_primary_key: true, has_auto_increment: true } }, - { field: 'feedback_id', type: 'uuid', meta: { interface: 'select-dropdown' } }, - { field: 'user_name', type: 'string' }, - { field: 'text', type: 'text' }, - { field: 'date_created', type: 'timestamp', schema: { default_value: 'NOW()' } } - ] - } as any)); - } catch (e) { } - - if (adminPolicy) { - console.log('🔐 Granting ALL permissions to Administrator Policy...'); - for (const coll of ['visual_feedback', 'visual_feedback_comments']) { - for (const action of ['create', 'read', 'update', 'delete']) { - try { - await client.request(createPermission({ - collection: coll, - action, - fields: ['*'], - policy: adminPolicy.id - } as any)); - } catch (_e) { } - } - } - } - - console.log('📊 Creating Dashboard...'); - try { - const dash = await client.request(createDashboard({ name: 'Visual Feedback', icon: 'feedback', color: '#6366f1' })); - await client.request(createPanel({ - dashboard: dash.id, - name: 'Total Feedbacks', - type: 'metric', - width: 12, height: 6, position_x: 1, position_y: 1, - options: { collection: 'visual_feedback', function: 'count', field: 'id' } - } as any)); - } catch (e) { } - - console.log('✨ FEEDBACK BOOTSTRAP DONE.'); - } catch (e) { console.error('❌ FAILURE:', e); } -} -setup(); - `; - const tempFile = path.join(process.cwd(), "temp-bootstrap-feedback.ts"); - await fs.writeFile(tempFile, bootstrapScript); - try { - execSync("npx tsx --env-file=.env " + tempFile, { stdio: "inherit" }); - } finally { - await fs.remove(tempFile); - } - }); - -directus - .command("sync ") - .description("Sync Directus data (push/pull) for a specific environment") - .action(async (action, env) => { - const { execSync } = await import("child_process"); - console.log( - chalk.blue(`📥 Executing Directus sync: ${action} -> ${env}...`), - ); - execSync(`./scripts/sync-directus.sh ${action} ${env}`, { - stdio: "inherit", - }); - }); - program .command("pagespeed") .description("Run PageSpeed (Lighthouse) tests") @@ -221,13 +83,6 @@ program lint: "next lint", typecheck: "tsc --noEmit", test: "vitest run --passWithNoTests", - "directus:bootstrap": "mintel directus bootstrap", - "directus:push:testing": "mintel directus sync push testing", - "directus:pull:testing": "mintel directus sync pull testing", - "directus:push:staging": "mintel directus sync push staging", - "directus:pull:staging": "mintel directus sync pull staging", - "directus:push:prod": "mintel directus sync push production", - "directus:pull:prod": "mintel directus sync pull production", "pagespeed:test": "mintel pagespeed", }, dependencies: { @@ -236,7 +91,6 @@ program "react-dom": "^19.0.0", "@mintel/next-utils": "workspace:*", "@mintel/next-observability": "workspace:*", - "@directus/sdk": "^21.0.0", }, devDependencies: { "@types/node": "^20.0.0", @@ -473,15 +327,6 @@ export default function Home() { } } - // Create Directus structure - await fs.ensureDir(path.join(fullPath, "directus/uploads")); - await fs.ensureDir(path.join(fullPath, "directus/extensions")); - await fs.writeFile(path.join(fullPath, "directus/uploads/.gitkeep"), ""); - await fs.writeFile( - path.join(fullPath, "directus/extensions/.gitkeep"), - "", - ); - // Create .env.example const envExample = `# Project PROJECT_NAME=${projectName} @@ -493,21 +338,10 @@ AUTH_COOKIE_NAME=mintel_gatekeeper_session # Host Config (Local) TRAEFIK_HOST=\`${projectName}.localhost\` -DIRECTUS_HOST=\`cms.${projectName}.localhost\` # Next.js NEXT_PUBLIC_BASE_URL=http://${projectName}.localhost -# Directus -DIRECTUS_URL=http://cms.${projectName}.localhost -DIRECTUS_KEY=$(openssl rand -hex 32 2>/dev/null || echo "mintel-key") -DIRECTUS_SECRET=$(openssl rand -hex 32 2>/dev/null || echo "mintel-secret") -DIRECTUS_ADMIN_EMAIL=admin@mintel.me -DIRECTUS_ADMIN_PASSWORD=mintel-admin-pass -DIRECTUS_DB_NAME=directus -DIRECTUS_DB_USER=directus -DIRECTUS_DB_PASSWORD=mintel-db-pass - # Sentry / Glitchtip SENTRY_DSN= diff --git a/packages/cms-infra/Dockerfile b/packages/cms-infra/Dockerfile deleted file mode 100644 index 8bb8e15..0000000 --- a/packages/cms-infra/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM directus/directus:11 - -USER root -# Install dependencies in a way that avoids metadata conflicts in the root -RUN mkdir -p /directus/lib-dependencies && \ - cd /directus/lib-dependencies && \ - npm init -y && \ - npm install vue @vueuse/core vue-router -# Ensure they are in the NODE_PATH -ENV NODE_PATH="/directus/lib-dependencies/node_modules:${NODE_PATH}" -USER node diff --git a/packages/cms-infra/database/RELOAD_TEST b/packages/cms-infra/database/RELOAD_TEST deleted file mode 100644 index e69de29..0000000 diff --git a/packages/cms-infra/database/data.db b/packages/cms-infra/database/data.db deleted file mode 100644 index 6487ca4fb56aec02f82ab3c1fad9dba443e39aee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 360448 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 - - - - - - - - - -
-
- Notizen / Adresse -

{{ selectedCompany.notes || '---' }}

-
-
- - - - - -
- - - - - diff --git a/packages/concept-engine/src/_test_pipeline.ts b/packages/concept-engine/src/_test_pipeline.ts index 07a6b1e..3dfbc75 100644 --- a/packages/concept-engine/src/_test_pipeline.ts +++ b/packages/concept-engine/src/_test_pipeline.ts @@ -1,40 +1,39 @@ -import { config as dotenvConfig } from 'dotenv'; -import * as path from 'node:path'; -import * as fs from 'node:fs/promises'; -import { EstimationPipeline } from './pipeline.js'; +import { config as dotenvConfig } from "dotenv"; +import * as path from "node:path"; +import * as fs from "node:fs/promises"; +import { ConceptPipeline } from "./pipeline.js"; -dotenvConfig({ path: path.resolve(process.cwd(), '../../.env') }); +dotenvConfig({ path: path.resolve(process.cwd(), "../../.env") }); const briefing = await fs.readFile( - path.resolve(process.cwd(), '../../data/briefings/etib.txt'), - 'utf8', + path.resolve(process.cwd(), "../../data/briefings/etib.txt"), + "utf8", ); console.log(`Briefing loaded: ${briefing.length} chars`); -const pipeline = new EstimationPipeline( - { - openrouterKey: process.env.OPENROUTER_API_KEY || '', - zyteApiKey: process.env.ZYTE_API_KEY, - outputDir: path.resolve(process.cwd(), '../../out/estimations'), - crawlDir: path.resolve(process.cwd(), '../../data/crawls'), - }, - { - onStepStart: (id, name) => console.log(`[CB] Starting: ${id}`), - onStepComplete: (id) => console.log(`[CB] Done: ${id}`), - onStepError: (id, err) => console.error(`[CB] Error in ${id}: ${err}`), - }, +const pipeline = new ConceptPipeline( + { + openrouterKey: process.env.OPENROUTER_API_KEY || "", + zyteApiKey: process.env.ZYTE_API_KEY, + outputDir: path.resolve(process.cwd(), "../../out/estimations"), + crawlDir: path.resolve(process.cwd(), "../../data/crawls"), + }, + { + onStepStart: (id, _name) => console.log(`[CB] Starting: ${id}`), + onStepComplete: (id) => console.log(`[CB] Done: ${id}`), + onStepError: (id, err) => console.error(`[CB] Error in ${id}: ${err}`), + }, ); try { - const result = await pipeline.run({ - briefing, - url: 'https://www.e-tib.com', - }); + await pipeline.run({ + briefing, + url: "https://www.e-tib.com", + }); - console.log('\n✨ Pipeline complete!'); - console.log('Validation:', result.validationResult?.passed ? 'PASSED' : 'FAILED'); + console.log("\n✨ Pipeline complete!"); } catch (err: any) { - console.error('\n❌ Pipeline failed:', err.message); - console.error(err.stack); + console.error("\n❌ Pipeline failed:", err.message); + console.error(err.stack); } diff --git a/packages/concept-engine/src/cli.ts b/packages/concept-engine/src/cli.ts index d67d425..6795ca0 100644 --- a/packages/concept-engine/src/cli.ts +++ b/packages/concept-engine/src/cli.ts @@ -18,132 +18,146 @@ dotenvConfig({ path: path.resolve(process.cwd(), ".env") }); const program = new Command(); program - .name("concept") - .description("AI-powered project concept generator") - .version("1.0.0"); + .name("concept") + .description("AI-powered project concept generator") + .version("1.0.0"); program - .command("run") - .description("Run the full concept pipeline") - .argument("[briefing]", "Briefing text or @path/to/file.txt") - .option("--url ", "Target website URL") - .option("--comments ", "Additional notes") - .option("--clear-cache", "Clear crawl cache and re-crawl") - .option("--output ", "Output directory", "../../out/concepts") - .option("--crawl-dir ", "Crawl data directory", "../../data/crawls") - .action(async (briefingArg: string | undefined, options: any) => { - const openrouterKey = process.env.OPENROUTER_API_KEY || process.env.OPENROUTER_KEY; - if (!openrouterKey) { - console.error("❌ OPENROUTER_API_KEY not found in environment."); - process.exit(1); - } + .command("run") + .description("Run the full concept pipeline") + .argument("[briefing]", "Briefing text or @path/to/file.txt") + .option("--url ", "Target website URL") + .option("--comments ", "Additional notes") + .option("--clear-cache", "Clear crawl cache and re-crawl") + .option("--output ", "Output directory", "../../out/concepts") + .option("--crawl-dir ", "Crawl data directory", "../../data/crawls") + .action(async (briefingArg: string | undefined, options: any) => { + const openrouterKey = + process.env.OPENROUTER_API_KEY || process.env.OPENROUTER_KEY; + if (!openrouterKey) { + console.error("❌ OPENROUTER_API_KEY not found in environment."); + process.exit(1); + } - let briefing = briefingArg || ""; + let briefing = briefingArg || ""; - // Handle @file references - if (briefing.startsWith("@")) { - const rawPath = briefing.substring(1); - const filePath = rawPath.startsWith("/") - ? rawPath - : path.resolve(process.cwd(), rawPath); - if (!existsSync(filePath)) { - console.error(`❌ Briefing file not found: ${filePath}`); - process.exit(1); - } - briefing = await fs.readFile(filePath, "utf8"); - console.log(`📄 Loaded briefing from: ${filePath}`); - } + // Handle @file references + if (briefing.startsWith("@")) { + const rawPath = briefing.substring(1); + const filePath = rawPath.startsWith("/") + ? rawPath + : path.resolve(process.cwd(), rawPath); + if (!existsSync(filePath)) { + console.error(`❌ Briefing file not found: ${filePath}`); + process.exit(1); + } + briefing = await fs.readFile(filePath, "utf8"); + console.log(`📄 Loaded briefing from: ${filePath}`); + } - // Auto-discover URL from briefing - let url = options.url; - if (!url && briefing) { - const urlMatch = briefing.match(/https?:\/\/[^\s]+/); - if (urlMatch) { - url = urlMatch[0]; - console.log(`🔗 Discovered URL in briefing: ${url}`); - } - } + // Auto-discover URL from briefing + let url = options.url; + if (!url && briefing) { + const urlMatch = briefing.match(/https?:\/\/[^\s]+/); + if (urlMatch) { + url = urlMatch[0]; + console.log(`🔗 Discovered URL in briefing: ${url}`); + } + } - if (!briefing && !url) { - console.error("❌ Provide a briefing text or --url"); - process.exit(1); - } + if (!briefing && !url) { + console.error("❌ Provide a briefing text or --url"); + process.exit(1); + } - const pipeline = new ConceptPipeline( - { - openrouterKey, - zyteApiKey: process.env.ZYTE_API_KEY, - outputDir: path.resolve(process.cwd(), options.output), - crawlDir: path.resolve(process.cwd(), options.crawlDir), - }, - { - onStepStart: (id, name) => { - // Will be enhanced with Ink spinner later - }, - onStepComplete: (id, result) => { - // Will be enhanced with Ink UI later - }, - }, - ); + const pipeline = new ConceptPipeline( + { + openrouterKey, + zyteApiKey: process.env.ZYTE_API_KEY, + outputDir: path.resolve(process.cwd(), options.output), + crawlDir: path.resolve(process.cwd(), options.crawlDir), + }, + { + onStepStart: (_id, _name) => { + // Will be enhanced with Ink spinner later + }, + onStepComplete: (_id, _result) => { + // Will be enhanced with Ink UI later + }, + }, + ); - try { - await pipeline.run({ - briefing, - url, - comments: options.comments, - clearCache: options.clearCache, - }); + try { + await pipeline.run({ + briefing, + url, + comments: options.comments, + clearCache: options.clearCache, + }); - console.log("\n✨ Concept generation complete!"); - } catch (err) { - console.error(`\n❌ Pipeline failed: ${(err as Error).message}`); - process.exit(1); - } - }); + console.log("\n✨ Concept generation complete!"); + } catch (err) { + console.error(`\n❌ Pipeline failed: ${(err as Error).message}`); + process.exit(1); + } + }); program - .command("analyze") - .description("Only crawl and analyze a website (no LLM)") - .argument("", "Website URL to analyze") - .option("--crawl-dir ", "Crawl data directory", "../../data/crawls") - .option("--clear-cache", "Clear existing crawl cache") - .action(async (url: string, options: any) => { - const { crawlSite } = await import("./scraper.js"); - const { analyzeSite } = await import("./analyzer.js"); + .command("analyze") + .description("Only crawl and analyze a website (no LLM)") + .argument("", "Website URL to analyze") + .option("--crawl-dir ", "Crawl data directory", "../../data/crawls") + .option("--clear-cache", "Clear existing crawl cache") + .action(async (url: string, options: any) => { + const { crawlSite } = await import("./scraper.js"); + const { analyzeSite } = await import("./analyzer.js"); - if (options.clearCache) { - const { clearCrawlCache } = await import("./scraper.js"); - const domain = new URL(url).hostname; - await clearCrawlCache(path.resolve(process.cwd(), options.crawlDir), domain); - } + if (options.clearCache) { + const { clearCrawlCache } = await import("./scraper.js"); + const domain = new URL(url).hostname; + await clearCrawlCache( + path.resolve(process.cwd(), options.crawlDir), + domain, + ); + } - const pages = await crawlSite(url, { - zyteApiKey: process.env.ZYTE_API_KEY, - crawlDir: path.resolve(process.cwd(), options.crawlDir), - }); - - const domain = new URL(url).hostname; - const profile = analyzeSite(pages, domain); - - console.log("\n📊 Site Profile:"); - console.log(` Domain: ${profile.domain}`); - console.log(` Total Pages: ${profile.totalPages}`); - console.log(` Navigation: ${profile.navigation.map((n) => n.label).join(", ")}`); - console.log(` Features: ${profile.existingFeatures.join(", ") || "none"}`); - console.log(` Services: ${profile.services.join(", ") || "none"}`); - console.log(` External Domains: ${profile.externalDomains.join(", ") || "none"}`); - console.log(` Company: ${profile.companyInfo.name || "unbekannt"}`); - console.log(` Tax ID: ${profile.companyInfo.taxId || "unbekannt"}`); - console.log(` Colors: ${profile.colors.join(", ")}`); - console.log(` Images Found: ${profile.images.length}`); - console.log(` Social: ${Object.entries(profile.socialLinks).map(([k, v]) => `${k}`).join(", ") || "none"}`); - - const outputPath = path.join( - path.resolve(process.cwd(), options.crawlDir), - domain.replace(/\./g, "-"), - "_site_profile.json", - ); - console.log(`\n📦 Full profile saved to: ${outputPath}`); + const pages = await crawlSite(url, { + zyteApiKey: process.env.ZYTE_API_KEY, + crawlDir: path.resolve(process.cwd(), options.crawlDir), }); + const domain = new URL(url).hostname; + const profile = analyzeSite(pages, domain); + + console.log("\n📊 Site Profile:"); + console.log(` Domain: ${profile.domain}`); + console.log(` Total Pages: ${profile.totalPages}`); + console.log( + ` Navigation: ${profile.navigation.map((n) => n.label).join(", ")}`, + ); + console.log(` Features: ${profile.existingFeatures.join(", ") || "none"}`); + console.log(` Services: ${profile.services.join(", ") || "none"}`); + console.log( + ` External Domains: ${profile.externalDomains.join(", ") || "none"}`, + ); + console.log(` Company: ${profile.companyInfo.name || "unbekannt"}`); + console.log(` Tax ID: ${profile.companyInfo.taxId || "unbekannt"}`); + console.log(` Colors: ${profile.colors.join(", ")}`); + console.log(` Images Found: ${profile.images.length}`); + console.log( + ` Social: ${ + Object.entries(profile.socialLinks) + .map(([_k, _v]) => `${_k}`) + .join(", ") || "none" + }`, + ); + + const outputPath = path.join( + path.resolve(process.cwd(), options.crawlDir), + domain.replace(/\./g, "-"), + "_site_profile.json", + ); + console.log(`\n📦 Full profile saved to: ${outputPath}`); + }); + program.parse(); diff --git a/packages/concept-engine/src/dummy.test.ts b/packages/concept-engine/src/dummy.test.ts new file mode 100644 index 0000000..a795b9f --- /dev/null +++ b/packages/concept-engine/src/dummy.test.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from "vitest"; + +describe("concept-engine", () => { + it("should pass", () => { + expect(true).toBe(true); + }); +}); diff --git a/packages/concept-engine/src/llm-client.ts b/packages/concept-engine/src/llm-client.ts index 39a0111..bc24361 100644 --- a/packages/concept-engine/src/llm-client.ts +++ b/packages/concept-engine/src/llm-client.ts @@ -5,20 +5,20 @@ import axios from "axios"; interface LLMRequestOptions { - model: string; - systemPrompt: string; - userPrompt: string; - jsonMode?: boolean; - apiKey: string; + model: string; + systemPrompt: string; + userPrompt: string; + jsonMode?: boolean; + apiKey: string; } interface LLMResponse { - content: string; - usage: { - promptTokens: number; - completionTokens: number; - cost: number; - }; + content: string; + usage: { + promptTokens: number; + completionTokens: number; + cost: number; + }; } /** @@ -26,108 +26,117 @@ interface LLMResponse { * Handles markdown fences, control chars, trailing commas. */ export function cleanJson(str: string): string { - let cleaned = str.replace(/```json\n?|```/g, "").trim(); - cleaned = cleaned.replace( - /[\u0000-\u0009\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, - " ", - ); - cleaned = cleaned.replace(/,\s*([\]}])/g, "$1"); - return cleaned; + let cleaned = str.replace(/```json\n?|```/g, "").trim(); + // eslint-disable-next-line no-control-regex + cleaned = cleaned.replace(/[\x00-\x1f\x7f-\x9f]/gi, " "); + cleaned = cleaned.replace(/,\s*([\]}])/g, "$1"); + return cleaned; } /** * Send a request to an LLM via OpenRouter. */ -export async function llmRequest(options: LLMRequestOptions): Promise { - const { model, systemPrompt, userPrompt, jsonMode = true, apiKey } = options; +export async function llmRequest( + options: LLMRequestOptions, +): Promise { + const { model, systemPrompt, userPrompt, jsonMode = true, apiKey } = options; - const startTime = Date.now(); - - const resp = await axios.post( - "https://openrouter.ai/api/v1/chat/completions", - { - model, - messages: [ - { role: "system", content: systemPrompt }, - { role: "user", content: userPrompt }, - ], - ...(jsonMode ? { response_format: { type: "json_object" } } : {}), + const resp = await axios + .post( + "https://openrouter.ai/api/v1/chat/completions", + { + model, + messages: [ + { role: "system", content: systemPrompt }, + { role: "user", content: userPrompt }, + ], + ...(jsonMode ? { response_format: { type: "json_object" } } : {}), + }, + { + headers: { + Authorization: `Bearer ${apiKey}`, + "Content-Type": "application/json", }, - { - headers: { - Authorization: `Bearer ${apiKey}`, - "Content-Type": "application/json", - }, - timeout: 120000, - }, - ).catch(err => { - if (err.response) { - console.error("OpenRouter API Error:", JSON.stringify(err.response.data, null, 2)); - } - throw err; + timeout: 120000, + }, + ) + .catch((err) => { + if (err.response) { + console.error( + "OpenRouter API Error:", + JSON.stringify(err.response.data, null, 2), + ); + } + throw err; }); - const content = resp.data.choices?.[0]?.message?.content; - if (!content) { - throw new Error(`LLM returned no content. Model: ${model}`); - } + const content = resp.data.choices?.[0]?.message?.content; + if (!content) { + throw new Error(`LLM returned no content. Model: ${model}`); + } - let cost = 0; - const usage = resp.data.usage || {}; - if (usage.cost !== undefined) { - cost = usage.cost; - } else { - // Fallback estimation - cost = - (usage.prompt_tokens || 0) * (0.1 / 1_000_000) + - (usage.completion_tokens || 0) * (0.4 / 1_000_000); - } + let cost = 0; + const usage = resp.data.usage || {}; + if (usage.cost !== undefined) { + cost = usage.cost; + } else { + // Fallback estimation + cost = + (usage.prompt_tokens || 0) * (0.1 / 1_000_000) + + (usage.completion_tokens || 0) * (0.4 / 1_000_000); + } - return { - content, - usage: { - promptTokens: usage.prompt_tokens || 0, - completionTokens: usage.completion_tokens || 0, - cost, - }, - }; + return { + content, + usage: { + promptTokens: usage.prompt_tokens || 0, + completionTokens: usage.completion_tokens || 0, + cost, + }, + }; } /** * Send a request and parse the response as JSON. */ export async function llmJsonRequest( - options: LLMRequestOptions, + options: LLMRequestOptions, ): Promise<{ data: T; usage: LLMResponse["usage"] }> { - const response = await llmRequest({ ...options, jsonMode: true }); - const cleaned = cleanJson(response.content); + const response = await llmRequest({ ...options, jsonMode: true }); + const cleaned = cleanJson(response.content); - let parsed: T; - try { - parsed = JSON.parse(cleaned); - } catch (e) { - throw new Error( - `Failed to parse LLM JSON response: ${(e as Error).message}\nRaw: ${cleaned.substring(0, 500)}`, - ); - } + let parsed: T; + try { + parsed = JSON.parse(cleaned); + } catch (e) { + throw new Error( + `Failed to parse LLM JSON response: ${(e as Error).message}\nRaw: ${cleaned.substring(0, 500)}`, + ); + } - // Unwrap common LLM artifacts: {"0": {...}}, {"state": {...}}, etc. - const unwrapped = unwrapResponse(parsed); + // Unwrap common LLM artifacts: {"0": {...}}, {"state": {...}}, etc. + const unwrapped = unwrapResponse(parsed); - return { data: unwrapped as T, usage: response.usage }; + return { data: unwrapped as T, usage: response.usage }; } /** * Recursively unwrap common LLM wrapping patterns. */ function unwrapResponse(obj: any): any { - if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj; - const keys = Object.keys(obj); - if (keys.length === 1) { - const key = keys[0]; - if (key === "0" || key === "state" || key === "facts" || key === "result" || key === "data") { - return unwrapResponse(obj[key]); - } + if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj; + const keys = Object.keys(obj); + if (keys.length === 1) { + const key = keys[0]; + if ( + key === "0" || + key === "state" || + key === "facts" || + key === "result" || + key === "data" + ) { + return unwrapResponse(obj[key]); } - return obj; + } + return obj; } diff --git a/packages/concept-engine/src/pipeline.ts b/packages/concept-engine/src/pipeline.ts index 201a787..3ec052f 100644 --- a/packages/concept-engine/src/pipeline.ts +++ b/packages/concept-engine/src/pipeline.ts @@ -5,7 +5,6 @@ import * as fs from "node:fs/promises"; import * as path from "node:path"; -import { existsSync } from "node:fs"; import { crawlSite, clearCrawlCache } from "./scraper.js"; import { analyzeSite } from "./analyzer.js"; import { executeResearch } from "./steps/00b-research.js"; @@ -15,18 +14,17 @@ import { executeAudit } from "./steps/02-audit.js"; import { executeStrategize } from "./steps/03-strategize.js"; import { executeArchitect } from "./steps/04-architect.js"; import type { - PipelineConfig, - PipelineInput, - ConceptState, - ProjectConcept, - StepResult, - StepUsage, + PipelineConfig, + PipelineInput, + ConceptState, + ProjectConcept, + StepResult, } from "./types.js"; export interface PipelineCallbacks { - onStepStart?: (stepId: string, stepName: string) => void; - onStepComplete?: (stepId: string, result: StepResult) => void; - onStepError?: (stepId: string, error: string) => void; + onStepStart?: (stepId: string, stepName: string) => void; + onStepComplete?: (stepId: string, result: StepResult) => void; + onStepError?: (stepId: string, error: string) => void; } /** @@ -34,224 +32,265 @@ export interface PipelineCallbacks { * Runs conceptual steps sequentially and builds the ProjectConcept. */ export class ConceptPipeline { - private config: PipelineConfig; - private state: ConceptState; - private callbacks: PipelineCallbacks; + private config: PipelineConfig; + private state: ConceptState; + private callbacks: PipelineCallbacks; - constructor(config: PipelineConfig, callbacks: PipelineCallbacks = {}) { - this.config = config; - this.callbacks = callbacks; - this.state = this.createInitialState(); - } + constructor(config: PipelineConfig, callbacks: PipelineCallbacks = {}) { + this.config = config; + this.callbacks = callbacks; + this.state = this.createInitialState(); + } - private createInitialState(): ConceptState { - return { - briefing: "", + private createInitialState(): ConceptState { + return { + briefing: "", + usage: { + totalPromptTokens: 0, + totalCompletionTokens: 0, + totalCost: 0, + perStep: [], + }, + }; + } + + /** + * Run the full concept pipeline from scratch. + */ + async run(input: PipelineInput): Promise { + this.state.briefing = input.briefing; + this.state.url = input.url; + this.state.comments = input.comments; + + // Ensure output directories + await fs.mkdir(this.config.outputDir, { recursive: true }); + await fs.mkdir(this.config.crawlDir, { recursive: true }); + + // Step 0: Scrape & Analyze (deterministic) + if (input.url) { + if (input.clearCache) { + const domain = new URL(input.url).hostname; + await clearCrawlCache(this.config.crawlDir, domain); + } + await this.runStep( + "00-scrape", + "Scraping & Analyzing Website", + async () => { + const pages = await crawlSite(input.url!, { + zyteApiKey: this.config.zyteApiKey, + crawlDir: this.config.crawlDir, + }); + const domain = new URL(input.url!).hostname; + const siteProfile = analyzeSite(pages, domain); + this.state.siteProfile = siteProfile; + this.state.crawlDir = path.join( + this.config.crawlDir, + domain.replace(/\./g, "-"), + ); + + // Save site profile + await fs.writeFile( + path.join(this.state.crawlDir!, "_site_profile.json"), + JSON.stringify(siteProfile, null, 2), + ); + + return { + success: true, + data: siteProfile, usage: { - totalPromptTokens: 0, - totalCompletionTokens: 0, - totalCost: 0, - perStep: [], + step: "00-scrape", + model: "none", + promptTokens: 0, + completionTokens: 0, + cost: 0, + durationMs: 0, }, - }; + }; + }, + ); } - /** - * Run the full concept pipeline from scratch. - */ - async run(input: PipelineInput): Promise { - this.state.briefing = input.briefing; - this.state.url = input.url; - this.state.comments = input.comments; - - // Ensure output directories - await fs.mkdir(this.config.outputDir, { recursive: true }); - await fs.mkdir(this.config.crawlDir, { recursive: true }); - - // Step 0: Scrape & Analyze (deterministic) - if (input.url) { - if (input.clearCache) { - const domain = new URL(input.url).hostname; - await clearCrawlCache(this.config.crawlDir, domain); - } - await this.runStep("00-scrape", "Scraping & Analyzing Website", async () => { - const pages = await crawlSite(input.url!, { - zyteApiKey: this.config.zyteApiKey, - crawlDir: this.config.crawlDir, - }); - const domain = new URL(input.url!).hostname; - const siteProfile = analyzeSite(pages, domain); - this.state.siteProfile = siteProfile; - this.state.crawlDir = path.join(this.config.crawlDir, domain.replace(/\./g, "-")); - - // Save site profile - await fs.writeFile( - path.join(this.state.crawlDir!, "_site_profile.json"), - JSON.stringify(siteProfile, null, 2), - ); - - return { - success: true, - data: siteProfile, - usage: { step: "00-scrape", model: "none", promptTokens: 0, completionTokens: 0, cost: 0, durationMs: 0 }, - }; - }); + // Step 00a: Site Audit (DataForSEO) + await this.runStep( + "00a-site-audit", + "IST-Analysis (DataForSEO)", + async () => { + const result = await executeSiteAudit(this.state, this.config); + if (result.success && result.data) { + this.state.siteAudit = result.data; } + return result; + }, + ); - // Step 00a: Site Audit (DataForSEO) - await this.runStep("00a-site-audit", "IST-Analysis (DataForSEO)", async () => { - const result = await executeSiteAudit(this.state, this.config); - if (result.success && result.data) { - this.state.siteAudit = result.data; - } - return result; - }); - - // Step 00b: Research (real web data via journaling) - await this.runStep("00b-research", "Industry & Company Research", async () => { - const result = await executeResearch(this.state); - if (result.success && result.data) { - this.state.researchData = result.data; - } - return result; - }); - - // Step 1: Extract facts - await this.runStep("01-extract", "Extracting Facts from Briefing", async () => { - const result = await executeExtract(this.state, this.config); - if (result.success) this.state.facts = result.data; - return result; - }); - - // Step 2: Audit features - await this.runStep("02-audit", "Auditing Features (Skeptical Review)", async () => { - const result = await executeAudit(this.state, this.config); - if (result.success) this.state.auditedFacts = result.data; - return result; - }); - - // Step 3: Strategic analysis - await this.runStep("03-strategize", "Strategic Analysis", async () => { - const result = await executeStrategize(this.state, this.config); - if (result.success) { - this.state.briefingSummary = result.data.briefingSummary; - this.state.designVision = result.data.designVision; - } - return result; - }); - - // Step 4: Sitemap architecture - await this.runStep("04-architect", "Information Architecture", async () => { - const result = await executeArchitect(this.state, this.config); - if (result.success) { - this.state.sitemap = result.data.sitemap; - this.state.websiteTopic = result.data.websiteTopic; - } - return result; - }); - - const projectConcept = this.buildProjectConcept(); - await this.saveState(projectConcept); - - return projectConcept; - } - - /** - * Run a single step with callbacks and error handling. - */ - private async runStep( - stepId: string, - stepName: string, - executor: () => Promise, - ): Promise { - this.callbacks.onStepStart?.(stepId, stepName); - console.log(`\n📍 ${stepName}...`); - - try { - const result = await executor(); - if (result.usage) { - this.state.usage.perStep.push(result.usage); - this.state.usage.totalPromptTokens += result.usage.promptTokens; - this.state.usage.totalCompletionTokens += result.usage.completionTokens; - this.state.usage.totalCost += result.usage.cost; - } - - if (result.success) { - const cost = result.usage?.cost ? ` ($${result.usage.cost.toFixed(4)})` : ""; - const duration = result.usage?.durationMs ? ` [${(result.usage.durationMs / 1000).toFixed(1)}s]` : ""; - console.log(` ✅ ${stepName} complete${cost}${duration}`); - this.callbacks.onStepComplete?.(stepId, result); - } else { - console.error(` ❌ ${stepName} failed: ${result.error}`); - this.callbacks.onStepError?.(stepId, result.error || "Unknown error"); - throw new Error(result.error); - } - } catch (err) { - const errorMsg = (err as Error).message; - this.callbacks.onStepError?.(stepId, errorMsg); - throw err; + // Step 00b: Research (real web data via journaling) + await this.runStep( + "00b-research", + "Industry & Company Research", + async () => { + const result = await executeResearch(this.state); + if (result.success && result.data) { + this.state.researchData = result.data; } + return result; + }, + ); + + // Step 1: Extract facts + await this.runStep( + "01-extract", + "Extracting Facts from Briefing", + async () => { + const result = await executeExtract(this.state, this.config); + if (result.success) this.state.facts = result.data; + return result; + }, + ); + + // Step 2: Audit features + await this.runStep( + "02-audit", + "Auditing Features (Skeptical Review)", + async () => { + const result = await executeAudit(this.state, this.config); + if (result.success) this.state.auditedFacts = result.data; + return result; + }, + ); + + // Step 3: Strategic analysis + await this.runStep("03-strategize", "Strategic Analysis", async () => { + const result = await executeStrategize(this.state, this.config); + if (result.success) { + this.state.briefingSummary = result.data.briefingSummary; + this.state.designVision = result.data.designVision; + } + return result; + }); + + // Step 4: Sitemap architecture + await this.runStep("04-architect", "Information Architecture", async () => { + const result = await executeArchitect(this.state, this.config); + if (result.success) { + this.state.sitemap = result.data.sitemap; + this.state.websiteTopic = result.data.websiteTopic; + } + return result; + }); + + const projectConcept = this.buildProjectConcept(); + await this.saveState(projectConcept); + + return projectConcept; + } + + /** + * Run a single step with callbacks and error handling. + */ + private async runStep( + stepId: string, + stepName: string, + executor: () => Promise, + ): Promise { + this.callbacks.onStepStart?.(stepId, stepName); + console.log(`\n📍 ${stepName}...`); + + try { + const result = await executor(); + if (result.usage) { + this.state.usage.perStep.push(result.usage); + this.state.usage.totalPromptTokens += result.usage.promptTokens; + this.state.usage.totalCompletionTokens += result.usage.completionTokens; + this.state.usage.totalCost += result.usage.cost; + } + + if (result.success) { + const cost = result.usage?.cost + ? ` ($${result.usage.cost.toFixed(4)})` + : ""; + const duration = result.usage?.durationMs + ? ` [${(result.usage.durationMs / 1000).toFixed(1)}s]` + : ""; + console.log(` ✅ ${stepName} complete${cost}${duration}`); + this.callbacks.onStepComplete?.(stepId, result); + } else { + console.error(` ❌ ${stepName} failed: ${result.error}`); + this.callbacks.onStepError?.(stepId, result.error || "Unknown error"); + throw new Error(result.error); + } + } catch (err) { + const errorMsg = (err as Error).message; + this.callbacks.onStepError?.(stepId, errorMsg); + throw err; } + } - /** - * Build the final Concept object. - */ - private buildProjectConcept(): ProjectConcept { - return { - domain: this.state.siteProfile?.domain || "unknown", - timestamp: new Date().toISOString(), - briefing: this.state.briefing, - auditedFacts: this.state.auditedFacts || {}, - siteProfile: this.state.siteProfile, - siteAudit: this.state.siteAudit, - researchData: this.state.researchData, - strategy: { - briefingSummary: this.state.briefingSummary || "", - designVision: this.state.designVision || "", - }, - architecture: { - websiteTopic: this.state.websiteTopic || "", - sitemap: this.state.sitemap || [], - }, - usage: this.state.usage, - }; + /** + * Build the final Concept object. + */ + private buildProjectConcept(): ProjectConcept { + return { + domain: this.state.siteProfile?.domain || "unknown", + timestamp: new Date().toISOString(), + briefing: this.state.briefing, + auditedFacts: this.state.auditedFacts || {}, + siteProfile: this.state.siteProfile, + siteAudit: this.state.siteAudit, + researchData: this.state.researchData, + strategy: { + briefingSummary: this.state.briefingSummary || "", + designVision: this.state.designVision || "", + }, + architecture: { + websiteTopic: this.state.websiteTopic || "", + sitemap: this.state.sitemap || [], + }, + usage: this.state.usage, + }; + } + + /** + * Save the full concept generated state to disk. + */ + private async saveState(concept: ProjectConcept): Promise { + const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); + const companyName = this.state.auditedFacts?.companyName || "unknown"; + + const stateDir = path.join(this.config.outputDir, "concepts"); + await fs.mkdir(stateDir, { recursive: true }); + + const statePath = path.join(stateDir, `${companyName}_${timestamp}.json`); + await fs.writeFile(statePath, JSON.stringify(concept, null, 2)); + console.log(`\n📦 Saved Project Concept to: ${statePath}`); + + // Save debug trace + const debugPath = path.join( + stateDir, + `${companyName}_${timestamp}_debug.json`, + ); + await fs.writeFile(debugPath, JSON.stringify(this.state, null, 2)); + + // Print usage summary + console.log("\n──────────────────────────────────────────────"); + console.log("📊 PIPELINE USAGE SUMMARY"); + console.log("──────────────────────────────────────────────"); + for (const step of this.state.usage.perStep) { + if (step.cost > 0) { + console.log( + ` ${step.step}: ${step.model} — $${step.cost.toFixed(6)} (${(step.durationMs / 1000).toFixed(1)}s)`, + ); + } } + console.log("──────────────────────────────────────────────"); + console.log(` TOTAL: $${this.state.usage.totalCost.toFixed(6)}`); + console.log( + ` Tokens: ${(this.state.usage.totalPromptTokens + this.state.usage.totalCompletionTokens).toLocaleString()}`, + ); + console.log("──────────────────────────────────────────────\n"); + } - /** - * Save the full concept generated state to disk. - */ - private async saveState(concept: ProjectConcept): Promise { - const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); - const companyName = this.state.auditedFacts?.companyName || "unknown"; - - const stateDir = path.join(this.config.outputDir, "concepts"); - await fs.mkdir(stateDir, { recursive: true }); - - const statePath = path.join(stateDir, `${companyName}_${timestamp}.json`); - await fs.writeFile(statePath, JSON.stringify(concept, null, 2)); - console.log(`\n📦 Saved Project Concept to: ${statePath}`); - - // Save debug trace - const debugPath = path.join(stateDir, `${companyName}_${timestamp}_debug.json`); - await fs.writeFile(debugPath, JSON.stringify(this.state, null, 2)); - - // Print usage summary - console.log("\n──────────────────────────────────────────────"); - console.log("📊 PIPELINE USAGE SUMMARY"); - console.log("──────────────────────────────────────────────"); - for (const step of this.state.usage.perStep) { - if (step.cost > 0) { - console.log(` ${step.step}: ${step.model} — $${step.cost.toFixed(6)} (${(step.durationMs / 1000).toFixed(1)}s)`); - } - } - console.log("──────────────────────────────────────────────"); - console.log(` TOTAL: $${this.state.usage.totalCost.toFixed(6)}`); - console.log(` Tokens: ${(this.state.usage.totalPromptTokens + this.state.usage.totalCompletionTokens).toLocaleString()}`); - console.log("──────────────────────────────────────────────\n"); - } - - /** Get the current internal state (for CLI inspection). */ - getState(): ConceptState { - return this.state; - } + /** Get the current internal state (for CLI inspection). */ + getState(): ConceptState { + return this.state; + } } diff --git a/packages/concept-engine/src/scraper.ts b/packages/concept-engine/src/scraper.ts index ab49c9c..0c4cc70 100644 --- a/packages/concept-engine/src/scraper.ts +++ b/packages/concept-engine/src/scraper.ts @@ -10,268 +10,289 @@ import { existsSync } from "node:fs"; import type { CrawledPage, PageType } from "./types.js"; interface ScraperConfig { - zyteApiKey?: string; - crawlDir: string; - maxPages?: number; + zyteApiKey?: string; + crawlDir: string; + maxPages?: number; } /** * Classify a URL pathname into a page type. */ function classifyPage(pathname: string): PageType { - const p = pathname.toLowerCase(); - if (p === "/" || p === "" || p === "/index.html") return "home"; - if (p.includes("service") || p.includes("leistung") || p.includes("kompetenz")) - return "service"; - if (p.includes("about") || p.includes("ueber") || p.includes("über") || p.includes("unternehmen")) - return "about"; - if (p.includes("contact") || p.includes("kontakt")) return "contact"; - if (p.includes("job") || p.includes("karriere") || p.includes("career") || p.includes("human-resources")) - return "career"; - if (p.includes("portfolio") || p.includes("referenz") || p.includes("projekt") || p.includes("case-study")) - return "portfolio"; - if (p.includes("blog") || p.includes("news") || p.includes("aktuelles") || p.includes("magazin")) - return "blog"; - if (p.includes("legal") || p.includes("impressum") || p.includes("datenschutz") || p.includes("privacy") || p.includes("agb")) - return "legal"; - return "other"; + const p = pathname.toLowerCase(); + if (p === "/" || p === "" || p === "/index.html") return "home"; + if ( + p.includes("service") || + p.includes("leistung") || + p.includes("kompetenz") + ) + return "service"; + if ( + p.includes("about") || + p.includes("ueber") || + p.includes("über") || + p.includes("unternehmen") + ) + return "about"; + if (p.includes("contact") || p.includes("kontakt")) return "contact"; + if ( + p.includes("job") || + p.includes("karriere") || + p.includes("career") || + p.includes("human-resources") + ) + return "career"; + if ( + p.includes("portfolio") || + p.includes("referenz") || + p.includes("projekt") || + p.includes("case-study") + ) + return "portfolio"; + if ( + p.includes("blog") || + p.includes("news") || + p.includes("aktuelles") || + p.includes("magazin") + ) + return "blog"; + if ( + p.includes("legal") || + p.includes("impressum") || + p.includes("datenschutz") || + p.includes("privacy") || + p.includes("agb") + ) + return "legal"; + return "other"; } /** * Detect interactive features present on a page. */ function detectFeatures($: cheerio.CheerioAPI): string[] { - const features: string[] = []; + const features: string[] = []; - // Search - if ( - $('input[type="search"]').length > 0 || - $('form[role="search"]').length > 0 || - $(".search-form, .search-box, #search, .searchbar").length > 0 || - $('input[name="q"], input[name="s"], input[name="search"]').length > 0 - ) { - features.push("search"); - } + // Search + if ( + $('input[type="search"]').length > 0 || + $('form[role="search"]').length > 0 || + $(".search-form, .search-box, #search, .searchbar").length > 0 || + $('input[name="q"], input[name="s"], input[name="search"]').length > 0 + ) { + features.push("search"); + } - // Forms (beyond search) - const formCount = $("form").length; - const searchForms = $('form[role="search"], .search-form').length; - if (formCount > searchForms) { - features.push("forms"); - } + // Forms (beyond search) + const formCount = $("form").length; + const searchForms = $('form[role="search"], .search-form').length; + if (formCount > searchForms) { + features.push("forms"); + } - // Maps - if ( - $('iframe[src*="google.com/maps"], iframe[src*="openstreetmap"], .map-container, #map, [data-map]').length > 0 - ) { - features.push("maps"); - } + // Maps + if ( + $( + 'iframe[src*="google.com/maps"], iframe[src*="openstreetmap"], .map-container, #map, [data-map]', + ).length > 0 + ) { + features.push("maps"); + } - // Video - if ( - $("video, iframe[src*='youtube'], iframe[src*='vimeo'], .video-container").length > 0 - ) { - features.push("video"); - } + // Video + if ( + $("video, iframe[src*='youtube'], iframe[src*='vimeo'], .video-container") + .length > 0 + ) { + features.push("video"); + } - // Calendar / Events - if ($(".calendar, .event, [data-calendar]").length > 0) { - features.push("calendar"); - } + // Calendar / Events + if ($(".calendar, .event, [data-calendar]").length > 0) { + features.push("calendar"); + } - // Cookie consent - if ($(".cookie-banner, .cookie-consent, #cookie-notice, [data-cookie]").length > 0) { - features.push("cookie-consent"); - } + // Cookie consent + if ( + $(".cookie-banner, .cookie-consent, #cookie-notice, [data-cookie]").length > + 0 + ) { + features.push("cookie-consent"); + } - return features; + return features; } /** * Extract all internal links from a page. */ function extractInternalLinks($: cheerio.CheerioAPI, origin: string): string[] { - const links: string[] = []; - $("a[href]").each((_, el) => { - const href = $(el).attr("href"); - if (!href) return; - try { - const url = new URL(href, origin); - if (url.origin === origin) { - // Skip assets - if (/\.(pdf|zip|jpg|jpeg|png|svg|webp|gif|css|js|ico|woff|woff2|ttf|eot)$/i.test(url.pathname)) return; - // Skip anchors-only - if (url.pathname === "/" && url.hash) return; - links.push(url.pathname); - } - } catch { - // Invalid URL, skip - } - }); - return [...new Set(links)]; + const links: string[] = []; + $("a[href]").each((_, el) => { + const href = $(el).attr("href"); + if (!href) return; + try { + const url = new URL(href, origin); + if (url.origin === origin) { + // Skip assets + if ( + /\.(pdf|zip|jpg|jpeg|png|svg|webp|gif|css|js|ico|woff|woff2|ttf|eot)$/i.test( + url.pathname, + ) + ) + return; + // Skip anchors-only + if (url.pathname === "/" && url.hash) return; + links.push(url.pathname); + } + } catch { + // Invalid URL, skip + } + }); + return [...new Set(links)]; } /** * Extract all images from a page. */ function extractImages($: cheerio.CheerioAPI, origin: string): string[] { - const images: string[] = []; + const images: string[] = []; - // Regular img tags - $("img[src]").each((_, el) => { - const src = $(el).attr("src"); - if (src) images.push(src); - }); + // Regular img tags + $("img[src]").each((_, el) => { + const src = $(el).attr("src"); + if (src) images.push(src); + }); - // CSS background images (inline styles) - $("[style*='background-image']").each((_, el) => { - const style = $(el).attr("style"); - const match = style?.match(/url\(['"]?(.*?)['"]?\)/); - if (match && match[1]) { - images.push(match[1]); - } - }); - - // Resolve URLs to absolute - const absoluteImages: string[] = []; - for (const img of images) { - if (img.startsWith("data:image")) continue; // Skip inline base64 - try { - const url = new URL(img, origin); - // Ignore small tracking pixels or generic vectors - if (url.pathname.endsWith(".svg") && !url.pathname.includes("logo")) continue; - absoluteImages.push(url.href); - } catch { - // Invalid URL - } + // CSS background images (inline styles) + $("[style*='background-image']").each((_, el) => { + const style = $(el).attr("style"); + const match = style?.match(/url\(['"]?(.*?)['"]?\)/); + if (match && match[1]) { + images.push(match[1]); } + }); - return [...new Set(absoluteImages)]; -} - -/** - * Extract services/competencies from text content. - */ -function extractServices(text: string): string[] { - const services: string[] = []; - // Common pattern: bulleted or newline-separated service lists - const lines = text.split(/\n/).map((l) => l.trim()).filter((l) => l.length > 3 && l.length < 100); - for (const line of lines) { - // Skip generic boilerplate - if (/cookie|datenschutz|impressum|copyright|©/i.test(line)) continue; - if (/^(tel|fax|e-mail|mobil|web|http)/i.test(line)) continue; - services.push(line); + // Resolve URLs to absolute + const absoluteImages: string[] = []; + for (const img of images) { + if (img.startsWith("data:image")) continue; // Skip inline base64 + try { + const url = new URL(img, origin); + // Ignore small tracking pixels or generic vectors + if (url.pathname.endsWith(".svg") && !url.pathname.includes("logo")) + continue; + absoluteImages.push(url.href); + } catch { + // Invalid URL } - return services; + } + + return [...new Set(absoluteImages)]; } /** * Fetch a page via Zyte API with browser rendering. */ async function fetchWithZyte(url: string, apiKey: string): Promise { - try { - const auth = Buffer.from(`${apiKey}:`).toString("base64"); - const resp = await fetch("https://api.zyte.com/v1/extract", { - method: "POST", - headers: { - "Authorization": `Basic ${auth}`, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - url, - browserHtml: true, - }), - signal: AbortSignal.timeout(60000), - }); + const auth = Buffer.from(`${apiKey}:`).toString("base64"); + const resp = await fetch("https://api.zyte.com/v1/extract", { + method: "POST", + headers: { + Authorization: `Basic ${auth}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + url, + browserHtml: true, + }), + signal: AbortSignal.timeout(60000), + }); - if (!resp.ok) { - const errorText = await resp.text(); - console.error(` ❌ Zyte API error ${resp.status} for ${url}: ${errorText}`); - // Rate limited — wait and retry once - if (resp.status === 429) { - console.log(" ⏳ Rate limited, waiting 5s and retrying..."); - await new Promise((r) => setTimeout(r, 5000)); - return fetchWithZyte(url, apiKey); - } - throw new Error(`HTTP ${resp.status}: ${errorText}`); - } - - const data = await resp.json(); - const html = data.browserHtml || ""; - if (!html) { - console.warn(` ⚠️ Zyte returned empty browserHtml for ${url}`); - } - return html; - } catch (err: any) { - throw err; + if (!resp.ok) { + const errorText = await resp.text(); + console.error( + ` ❌ Zyte API error ${resp.status} for ${url}: ${errorText}`, + ); + // Rate limited — wait and retry once + if (resp.status === 429) { + console.log(" ⏳ Rate limited, waiting 5s and retrying..."); + await new Promise((r) => setTimeout(r, 5000)); + return fetchWithZyte(url, apiKey); } -} + throw new Error(`HTTP ${resp.status}: ${errorText}`); + } + const data = await resp.json(); + const html = data.browserHtml || ""; + if (!html) { + console.warn(` ⚠️ Zyte returned empty browserHtml for ${url}`); + } + return html; +} /** * Fetch a page via simple HTTP GET (fallback). */ async function fetchDirect(url: string): Promise { - try { - const resp = await fetch(url, { - headers: { - "User-Agent": - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", - }, - signal: AbortSignal.timeout(30000), - }); - if (!resp.ok) return ""; - return await resp.text(); - } catch { - return ""; - } + const resp = await fetch(url, { + headers: { + "User-Agent": + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36", + }, + signal: AbortSignal.timeout(30000), + }).catch(() => null); + + if (!resp || !resp.ok) return ""; + return await resp.text(); } /** * Parse an HTML string into a CrawledPage. */ function parsePage(html: string, url: string): CrawledPage { - const $ = cheerio.load(html); - const urlObj = new URL(url); + const $ = cheerio.load(html); + const urlObj = new URL(url); - const title = $("title").text().trim(); - const headings = $("h1, h2, h3") - .map((_, el) => $(el).text().trim()) - .get() - .filter((h) => h.length > 0); + const title = $("title").text().trim(); + const headings = $("h1, h2, h3") + .map((_, el) => $(el).text().trim()) + .get() + .filter((h) => h.length > 0); - const navItems = $("nav a") - .map((_, el) => $(el).text().trim()) - .get() - .filter((t) => t.length > 0 && t.length < 100); + const navItems = $("nav a") + .map((_, el) => $(el).text().trim()) + .get() + .filter((t) => t.length > 0 && t.length < 100); - const bodyText = $("body") - .text() - .replace(/\s+/g, " ") - .substring(0, 50000) - .trim(); + const bodyText = $("body") + .text() + .replace(/\s+/g, " ") + .substring(0, 50000) + .trim(); - const features = detectFeatures($); - const links = extractInternalLinks($, urlObj.origin); - const images = extractImages($, urlObj.origin); + const features = detectFeatures($); + const links = extractInternalLinks($, urlObj.origin); + const images = extractImages($, urlObj.origin); - const description = $('meta[name="description"]').attr("content") || undefined; - const ogTitle = $('meta[property="og:title"]').attr("content") || undefined; - const ogImage = $('meta[property="og:image"]').attr("content") || undefined; + const description = + $('meta[name="description"]').attr("content") || undefined; + const ogTitle = $('meta[property="og:title"]').attr("content") || undefined; + const ogImage = $('meta[property="og:image"]').attr("content") || undefined; - return { - url, - pathname: urlObj.pathname, - title, - html, - text: bodyText, - headings, - navItems, - features, - type: classifyPage(urlObj.pathname), - links, - images, - meta: { description, ogTitle, ogImage }, - }; + return { + url, + pathname: urlObj.pathname, + title, + html, + text: bodyText, + headings, + navItems, + features, + type: classifyPage(urlObj.pathname), + links, + images, + meta: { description, ogTitle, ogImage }, + }; } /** @@ -280,164 +301,178 @@ function parsePage(html: string, url: string): CrawledPage { * Returns an array of CrawledPage objects. */ export async function crawlSite( - targetUrl: string, - config: ScraperConfig, + targetUrl: string, + config: ScraperConfig, ): Promise { - const urlObj = new URL(targetUrl); - const origin = urlObj.origin; - const domain = urlObj.hostname; - const domainDir = path.join(config.crawlDir, domain.replace(/\./g, "-")); + const urlObj = new URL(targetUrl); + const origin = urlObj.origin; + const domain = urlObj.hostname; + const domainDir = path.join(config.crawlDir, domain.replace(/\./g, "-")); - // Check for existing crawl - const metaFile = path.join(domainDir, "_crawl_meta.json"); - if (existsSync(metaFile)) { - console.log(`📦 Found existing crawl for ${domain}. Loading from disk...`); - return loadCrawlFromDisk(domainDir); - } + // Check for existing crawl + const metaFile = path.join(domainDir, "_crawl_meta.json"); + if (existsSync(metaFile)) { + console.log(`📦 Found existing crawl for ${domain}. Loading from disk...`); + return loadCrawlFromDisk(domainDir); + } - console.log(`🔍 Crawling ${targetUrl} via ${config.zyteApiKey ? "Zyte API" : "direct HTTP"}...`); + console.log( + `🔍 Crawling ${targetUrl} via ${config.zyteApiKey ? "Zyte API" : "direct HTTP"}...`, + ); - // Ensure output dir - await fs.mkdir(domainDir, { recursive: true }); + // Ensure output dir + await fs.mkdir(domainDir, { recursive: true }); - const maxPages = config.maxPages || 30; - const visited = new Set(); - const queue: string[] = [targetUrl]; - const pages: CrawledPage[] = []; + const maxPages = config.maxPages || 30; + const visited = new Set(); + const queue: string[] = [targetUrl]; + const pages: CrawledPage[] = []; - while (queue.length > 0 && visited.size < maxPages) { - const url = queue.shift()!; - const urlPath = new URL(url).pathname; + while (queue.length > 0 && visited.size < maxPages) { + const url = queue.shift()!; + const urlPath = new URL(url).pathname; - if (visited.has(urlPath)) continue; - visited.add(urlPath); + if (visited.has(urlPath)) continue; + visited.add(urlPath); - try { - console.log(` ↳ Fetching ${url} (${visited.size}/${maxPages})...`); + try { + console.log(` ↳ Fetching ${url} (${visited.size}/${maxPages})...`); - let html: string; - if (config.zyteApiKey) { - html = await fetchWithZyte(url, config.zyteApiKey); - } else { - html = await fetchDirect(url); - } + let html: string; + if (config.zyteApiKey) { + html = await fetchWithZyte(url, config.zyteApiKey); + } else { + html = await fetchDirect(url); + } - if (!html || html.length < 100) { - console.warn(` ⚠️ Empty/tiny response for ${url}, skipping.`); - continue; - } + if (!html || html.length < 100) { + console.warn(` ⚠️ Empty/tiny response for ${url}, skipping.`); + continue; + } - const page = parsePage(html, url); - pages.push(page); + const page = parsePage(html, url); + pages.push(page); - // Save HTML + metadata to disk - const safeName = urlPath === "/" ? "index" : urlPath.replace(/\//g, "_").replace(/^_/, ""); - await fs.writeFile(path.join(domainDir, `${safeName}.html`), html); - await fs.writeFile( - path.join(domainDir, `${safeName}.meta.json`), - JSON.stringify( - { - url: page.url, - pathname: page.pathname, - title: page.title, - type: page.type, - headings: page.headings, - navItems: page.navItems, - features: page.features, - links: page.links, - images: page.images, - meta: page.meta, - }, - null, - 2, - ), - ); - - // Discover new links - for (const link of page.links) { - if (!visited.has(link)) { - const fullUrl = `${origin}${link}`; - queue.push(fullUrl); - } - } - } catch (err) { - console.warn(` ⚠️ Failed to fetch ${url}: ${(err as Error).message}`); - } - } - - // Save crawl metadata - await fs.writeFile( - metaFile, + // Save HTML + metadata to disk + const safeName = + urlPath === "/" + ? "index" + : urlPath.replace(/\//g, "_").replace(/^_/, ""); + await fs.writeFile(path.join(domainDir, `${safeName}.html`), html); + await fs.writeFile( + path.join(domainDir, `${safeName}.meta.json`), JSON.stringify( - { - domain, - crawledAt: new Date().toISOString(), - totalPages: pages.length, - urls: pages.map((p) => p.url), - }, - null, - 2, + { + url: page.url, + pathname: page.pathname, + title: page.title, + type: page.type, + headings: page.headings, + navItems: page.navItems, + features: page.features, + links: page.links, + images: page.images, + meta: page.meta, + }, + null, + 2, ), - ); + ); - console.log(`✅ Crawled ${pages.length} pages for ${domain}. Saved to ${domainDir}`); - return pages; + // Discover new links + for (const link of page.links) { + if (!visited.has(link)) { + const fullUrl = `${origin}${link}`; + queue.push(fullUrl); + } + } + } catch (err) { + console.warn(` ⚠️ Failed to fetch ${url}: ${(err as Error).message}`); + } + } + + // Save crawl metadata + await fs.writeFile( + metaFile, + JSON.stringify( + { + domain, + crawledAt: new Date().toISOString(), + totalPages: pages.length, + urls: pages.map((p) => p.url), + }, + null, + 2, + ), + ); + + console.log( + `✅ Crawled ${pages.length} pages for ${domain}. Saved to ${domainDir}`, + ); + return pages; } /** * Load a previously crawled site from disk. */ async function loadCrawlFromDisk(domainDir: string): Promise { - const files = await fs.readdir(domainDir); - const metaFiles = files.filter((f) => f.endsWith(".meta.json") && f !== "_crawl_meta.json"); + const files = await fs.readdir(domainDir); + const metaFiles = files.filter( + (f) => f.endsWith(".meta.json") && f !== "_crawl_meta.json", + ); - const pages: CrawledPage[] = []; - for (const metaFile of metaFiles) { - const baseName = metaFile.replace(".meta.json", ""); - const htmlFile = `${baseName}.html`; + const pages: CrawledPage[] = []; + for (const metaFile of metaFiles) { + const baseName = metaFile.replace(".meta.json", ""); + const htmlFile = `${baseName}.html`; - const meta = JSON.parse(await fs.readFile(path.join(domainDir, metaFile), "utf8")); - let html = ""; - if (files.includes(htmlFile)) { - html = await fs.readFile(path.join(domainDir, htmlFile), "utf8"); - } - - const text = html - ? cheerio - .load(html)("body") - .text() - .replace(/\s+/g, " ") - .substring(0, 50000) - .trim() - : ""; - - pages.push({ - url: meta.url, - pathname: meta.pathname, - title: meta.title, - html, - text, - headings: meta.headings || [], - navItems: meta.navItems || [], - features: meta.features || [], - type: meta.type || "other", - links: meta.links || [], - images: meta.images || [], - meta: meta.meta || {}, - }); + const meta = JSON.parse( + await fs.readFile(path.join(domainDir, metaFile), "utf8"), + ); + let html = ""; + if (files.includes(htmlFile)) { + html = await fs.readFile(path.join(domainDir, htmlFile), "utf8"); } - console.log(` 📂 Loaded ${pages.length} cached pages from disk.`); - return pages; + const text = html + ? cheerio + .load(html)("body") + .text() + .replace(/\s+/g, " ") + .substring(0, 50000) + .trim() + : ""; + + pages.push({ + url: meta.url, + pathname: meta.pathname, + title: meta.title, + html, + text, + headings: meta.headings || [], + navItems: meta.navItems || [], + features: meta.features || [], + type: meta.type || "other", + links: meta.links || [], + images: meta.images || [], + meta: meta.meta || {}, + }); + } + + console.log(` 📂 Loaded ${pages.length} cached pages from disk.`); + return pages; } /** * Delete a cached crawl to force re-crawl. */ -export async function clearCrawlCache(crawlDir: string, domain: string): Promise { - const domainDir = path.join(crawlDir, domain.replace(/\./g, "-")); - if (existsSync(domainDir)) { - await fs.rm(domainDir, { recursive: true, force: true }); - console.log(`🧹 Cleared crawl cache for ${domain}`); - } +export async function clearCrawlCache( + crawlDir: string, + domain: string, +): Promise { + const domainDir = path.join(crawlDir, domain.replace(/\./g, "-")); + if (existsSync(domainDir)) { + await fs.rm(domainDir, { recursive: true, force: true }); + console.log(`🧹 Cleared crawl cache for ${domain}`); + } } diff --git a/packages/content-engine/src/orchestrator.ts b/packages/content-engine/src/orchestrator.ts index f54df0d..59390f4 100644 --- a/packages/content-engine/src/orchestrator.ts +++ b/packages/content-engine/src/orchestrator.ts @@ -212,7 +212,11 @@ export class AiBlogPostOrchestrator { console.log(`✅ Saved optimized file to: ${finalPath}`); } - async generateSlug(content: string, title?: string, instructions?: string): Promise { + async generateSlug( + content: string, + title?: string, + instructions?: string, + ): Promise { const response = await this.openai.chat.completions.create({ model: "google/gemini-3-flash-preview", messages: [ @@ -223,21 +227,32 @@ Return ONLY a JSON object with a single string field "slug". Example: {"slug": "how-to-optimize-react-performance"} Rules: Use lowercase letters, numbers, and hyphens only. No special characters. Keep it concise (2-5 words).`, }, - { role: "user", content: `Title: ${title || "Unknown"}\n\nContent:\n${content.slice(0, 3000)}...${instructions ? `\n\nEDITOR INSTRUCTIONS:\nPlease strictly follow these instructions from the editor when generating the slug:\n${instructions}` : ""}` }, + { + role: "user", + content: `Title: ${title || "Unknown"}\n\nContent:\n${content.slice(0, 3000)}...${instructions ? `\n\nEDITOR INSTRUCTIONS:\nPlease strictly follow these instructions from the editor when generating the slug:\n${instructions}` : ""}`, + }, ], response_format: { type: "json_object" }, }); try { - const parsed = JSON.parse(response.choices[0].message.content || '{"slug": ""}'); - let slug = parsed.slug || "new-post"; - return slug.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""); + const parsed = JSON.parse( + response.choices[0].message.content || '{"slug": ""}', + ); + const slug = parsed.slug || "new-post"; + return slug + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, ""); } catch { return "new-post"; } } - public async generateVisualPrompt(content: string, instructions?: string): Promise { + public async generateVisualPrompt( + content: string, + instructions?: string, + ): Promise { const response = await this.openai.chat.completions.create({ model: this.model, messages: [ @@ -253,7 +268,10 @@ FOCUS: The core metaphor or technical concept of the article. Example output: "A complex network of glowing fiber optic nodes forming a recursive pyramid structure, technical blue lineart style."`, }, - { role: "user", content: `${content.slice(0, 5000)}${instructions ? `\n\nEDITOR INSTRUCTIONS:\nPlease strictly follow these instructions from the editor when generating the visual prompt:\n${instructions}` : ""}` }, + { + role: "user", + content: `${content.slice(0, 5000)}${instructions ? `\n\nEDITOR INSTRUCTIONS:\nPlease strictly follow these instructions from the editor when generating the visual prompt:\n${instructions}` : ""}`, + }, ], max_tokens: 100, }); @@ -329,7 +347,7 @@ Example output: "A complex network of glowing fiber optic nodes forming a recurs ); const realPosts = await this.researchAgent.fetchRealSocialPosts( task.content.slice(0, 500), - task.customSources + task.customSources, ); socialPosts.push(...realPosts); } diff --git a/packages/customer-manager/package.json b/packages/customer-manager/package.json deleted file mode 100644 index 43dc3a3..0000000 --- a/packages/customer-manager/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "customer-manager", - "description": "Custom High-Fidelity Management for Directus", - "icon": "extension", - "version": "1.8.21", - "type": "module", - "keywords": [ - "directus", - "directus-extension", - "directus-extension-module" - ], - "directus:extension": { - "type": "module", - "path": "dist/index.js", - "source": "src/index.ts", - "host": "app", - "name": "customer manager" - }, - "scripts": { - "build": "directus-extension build", - "dev": "directus-extension build -w" - }, - "dependencies": { - "@mintel/directus-extension-toolkit": "workspace:*" - }, - "devDependencies": { - "@directus/extensions-sdk": "11.0.2", - "vue": "^3.4.0" - }, - "repository": { - "type": "git", - "url": "https://git.infra.mintel.me/mmintel/at-mintel.git" - } -} diff --git a/packages/customer-manager/src/index.ts b/packages/customer-manager/src/index.ts deleted file mode 100644 index a05ac7e..0000000 --- a/packages/customer-manager/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineModule } from '@directus/extensions-sdk'; -import ModuleComponent from './module.vue'; - -export default defineModule({ - id: 'customer-manager', - name: 'Customer Manager', - icon: 'supervisor_account', - routes: [ - { - path: '', - component: ModuleComponent, - }, - ], -}); diff --git a/packages/customer-manager/src/module.vue b/packages/customer-manager/src/module.vue deleted file mode 100644 index 2f1b6eb..0000000 --- a/packages/customer-manager/src/module.vue +++ /dev/null @@ -1,538 +0,0 @@ - - - - - diff --git a/packages/directus-extension-toolkit/package.json b/packages/directus-extension-toolkit/package.json deleted file mode 100644 index 8eead03..0000000 --- a/packages/directus-extension-toolkit/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "@mintel/directus-extension-toolkit", - "version": "1.8.21", - "description": "Shared toolkit for Directus extensions in the Mintel ecosystem", - "type": "module", - "main": "./dist/index.js", - "module": "./dist/index.js", - "files": [ - "dist" - ], - "exports": { - ".": { - "import": "./dist/index.js" - } - }, - "scripts": { - "build": "vite build", - "dev": "vite build --watch" - }, - "devDependencies": { - "@directus/extensions-sdk": "11.0.2", - "@vitejs/plugin-vue": "^6.0.4", - "typescript": "^5.0.0", - "vite": "^5.0.0", - "vue": "^3.4.0" - }, - "peerDependencies": { - "@directus/extensions-sdk": "*", - "vue": "^3.4.0" - }, - "repository": { - "type": "git", - "url": "https://git.infra.mintel.me/mmintel/at-mintel.git" - } -} diff --git a/packages/directus-extension-toolkit/src/MintelManagerLayout.vue b/packages/directus-extension-toolkit/src/MintelManagerLayout.vue deleted file mode 100644 index e24a44e..0000000 --- a/packages/directus-extension-toolkit/src/MintelManagerLayout.vue +++ /dev/null @@ -1,102 +0,0 @@ - - - - - diff --git a/packages/directus-extension-toolkit/src/MintelSelect.vue b/packages/directus-extension-toolkit/src/MintelSelect.vue deleted file mode 100644 index 89df57f..0000000 --- a/packages/directus-extension-toolkit/src/MintelSelect.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - - - diff --git a/packages/directus-extension-toolkit/src/MintelStatCard.vue b/packages/directus-extension-toolkit/src/MintelStatCard.vue deleted file mode 100644 index 645aa71..0000000 --- a/packages/directus-extension-toolkit/src/MintelStatCard.vue +++ /dev/null @@ -1,84 +0,0 @@ - - - - - diff --git a/packages/directus-extension-toolkit/src/index.ts b/packages/directus-extension-toolkit/src/index.ts deleted file mode 100644 index 448d2a4..0000000 --- a/packages/directus-extension-toolkit/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default as MintelSelect } from './MintelSelect.vue'; -export { default as MintelManagerLayout } from './MintelManagerLayout.vue'; -export { default as MintelStatCard } from './MintelStatCard.vue'; diff --git a/packages/directus-extension-toolkit/vite.config.ts b/packages/directus-extension-toolkit/vite.config.ts deleted file mode 100644 index abd73c9..0000000 --- a/packages/directus-extension-toolkit/vite.config.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { defineConfig } from 'vite'; -import vue from '@vitejs/plugin-vue'; -import { resolve } from 'path'; - -export default defineConfig({ - plugins: [vue()], - build: { - lib: { - entry: resolve('src/index.ts'), - name: 'MintelDirectusToolkit', - fileName: 'index', - formats: ['es'] - }, - rollupOptions: { - external: ['vue', '@directus/extensions-sdk'], - output: { - globals: { - vue: 'Vue', - '@directus/extensions-sdk': 'DirectusExtensionsSDK' - } - } - } - } -}); diff --git a/packages/estimation-engine/src/_test_pipeline.ts b/packages/estimation-engine/src/_test_pipeline.ts index 07a6b1e..f7e389c 100644 --- a/packages/estimation-engine/src/_test_pipeline.ts +++ b/packages/estimation-engine/src/_test_pipeline.ts @@ -1,40 +1,62 @@ -import { config as dotenvConfig } from 'dotenv'; -import * as path from 'node:path'; -import * as fs from 'node:fs/promises'; -import { EstimationPipeline } from './pipeline.js'; +import { config as dotenvConfig } from "dotenv"; +import * as path from "node:path"; +import * as fs from "node:fs/promises"; +import { EstimationPipeline } from "./pipeline.js"; -dotenvConfig({ path: path.resolve(process.cwd(), '../../.env') }); +dotenvConfig({ path: path.resolve(process.cwd(), "../../.env") }); const briefing = await fs.readFile( - path.resolve(process.cwd(), '../../data/briefings/etib.txt'), - 'utf8', + path.resolve(process.cwd(), "../../data/briefings/etib.txt"), + "utf8", ); console.log(`Briefing loaded: ${briefing.length} chars`); const pipeline = new EstimationPipeline( - { - openrouterKey: process.env.OPENROUTER_API_KEY || '', - zyteApiKey: process.env.ZYTE_API_KEY, - outputDir: path.resolve(process.cwd(), '../../out/estimations'), - crawlDir: path.resolve(process.cwd(), '../../data/crawls'), - }, - { - onStepStart: (id, name) => console.log(`[CB] Starting: ${id}`), - onStepComplete: (id) => console.log(`[CB] Done: ${id}`), - onStepError: (id, err) => console.error(`[CB] Error in ${id}: ${err}`), - }, + { + openrouterKey: process.env.OPENROUTER_API_KEY || "", + zyteApiKey: process.env.ZYTE_API_KEY, + outputDir: path.resolve(process.cwd(), "../../out/estimations"), + crawlDir: path.resolve(process.cwd(), "../../data/crawls"), + }, + { + onStepStart: (id, _name) => console.log(`[CB] Starting: ${id}`), + onStepComplete: (id) => console.log(`[CB] Done: ${id}`), + onStepError: (id, err) => console.error(`[CB] Error in ${id}: ${err}`), + }, ); try { - const result = await pipeline.run({ - briefing, - url: 'https://www.e-tib.com', - }); + const result = await pipeline.run({ + concept: { + strategy: { + briefingSummary: briefing, + projectGoals: [], + targetAudience: [], + coreMessage: "", + designVision: "", + uniqueValueProposition: "", + competitorAnalysis: "", + }, + architecture: { + sitemap: [], + recommendedTechStack: [], + integrations: [], + websiteTopic: "", + dataModels: [], + }, + auditedFacts: { + companyName: "E-TIB", + }, + } as any, + }); - console.log('\n✨ Pipeline complete!'); - console.log('Validation:', result.validationResult?.passed ? 'PASSED' : 'FAILED'); + console.log("\n✨ Pipeline complete!"); + console.log( + "Validation:", + result.validationResult?.passed ? "PASSED" : "FAILED", + ); } catch (err: any) { - console.error('\n❌ Pipeline failed:', err.message); - console.error(err.stack); + console.error("\n❌ Pipeline failed:", err.message); + console.error(err.stack); } diff --git a/packages/estimation-engine/src/cli.ts b/packages/estimation-engine/src/cli.ts index 54fb55a..4a8a4ec 100644 --- a/packages/estimation-engine/src/cli.ts +++ b/packages/estimation-engine/src/cli.ts @@ -18,61 +18,64 @@ dotenvConfig({ path: path.resolve(process.cwd(), ".env") }); const program = new Command(); program - .name("estimate") - .description("AI-powered project estimation engine") - .version("1.0.0"); + .name("estimate") + .description("AI-powered project estimation engine") + .version("1.0.0"); program - .command("run") - .description("Run the financial estimation pipeline from a concept file") - .argument("", "Path to the ProjectConcept JSON file") - .option("--budget ", "Budget constraint (e.g. '15.000 €')") - .option("--output ", "Output directory", "../../out/estimations") - .action(async (conceptFile: string, options: any) => { - const openrouterKey = process.env.OPENROUTER_API_KEY || process.env.OPENROUTER_KEY; - if (!openrouterKey) { - console.error("❌ OPENROUTER_API_KEY not found in environment."); - process.exit(1); - } + .command("run") + .description("Run the financial estimation pipeline from a concept file") + .argument("", "Path to the ProjectConcept JSON file") + .option("--budget ", "Budget constraint (e.g. '15.000 €')") + .option("--output ", "Output directory", "../../out/estimations") + .action(async (conceptFile: string, options: any) => { + const openrouterKey = + process.env.OPENROUTER_API_KEY || process.env.OPENROUTER_KEY; + if (!openrouterKey) { + console.error("❌ OPENROUTER_API_KEY not found in environment."); + process.exit(1); + } - const filePath = path.resolve(process.cwd(), conceptFile); - if (!existsSync(filePath)) { - console.error(`❌ Concept file not found: ${filePath}`); - process.exit(1); - } + const filePath = path.resolve(process.cwd(), conceptFile); + if (!existsSync(filePath)) { + console.error(`❌ Concept file not found: ${filePath}`); + process.exit(1); + } - console.log(`📄 Loading concept from: ${filePath}`); - const rawConcept = await fs.readFile(filePath, "utf8"); - const concept = JSON.parse(rawConcept) as ProjectConcept; + console.log(`📄 Loading concept from: ${filePath}`); + const rawConcept = await fs.readFile(filePath, "utf8"); + const concept = JSON.parse(rawConcept) as ProjectConcept; - const pipeline = new EstimationPipeline( - { - openrouterKey, - outputDir: path.resolve(process.cwd(), options.output), - crawlDir: "" // No longer needed here - }, - { - onStepStart: (id, name) => { }, - onStepComplete: (id, result) => { }, - }, + const pipeline = new EstimationPipeline( + { + openrouterKey, + outputDir: path.resolve(process.cwd(), options.output), + crawlDir: "", // No longer needed here + }, + { + onStepStart: (_id, _name) => {}, + onStepComplete: (_id, _result) => {}, + }, + ); + + try { + const result = await pipeline.run({ + concept, + budget: options.budget, + }); + + console.log("\n✨ Estimation complete!"); + + if (result.validationResult && !result.validationResult.passed) { + console.log( + `\n⚠️ ${result.validationResult.errors.length} validation issues found.`, ); - - try { - const result = await pipeline.run({ - concept, - budget: options.budget, - }); - - console.log("\n✨ Estimation complete!"); - - if (result.validationResult && !result.validationResult.passed) { - console.log(`\n⚠️ ${result.validationResult.errors.length} validation issues found.`); - console.log(" Review the output JSON and re-run problematic steps."); - } - } catch (err) { - console.error(`\n❌ Pipeline failed: ${(err as Error).message}`); - process.exit(1); - } - }); + console.log(" Review the output JSON and re-run problematic steps."); + } + } catch (err) { + console.error(`\n❌ Pipeline failed: ${(err as Error).message}`); + process.exit(1); + } + }); program.parse(); diff --git a/packages/estimation-engine/src/llm-client.ts b/packages/estimation-engine/src/llm-client.ts index 37a606b..d611872 100644 --- a/packages/estimation-engine/src/llm-client.ts +++ b/packages/estimation-engine/src/llm-client.ts @@ -5,20 +5,20 @@ import axios from "axios"; interface LLMRequestOptions { - model: string; - systemPrompt: string; - userPrompt: string; - jsonMode?: boolean; - apiKey: string; + model: string; + systemPrompt: string; + userPrompt: string; + jsonMode?: boolean; + apiKey: string; } interface LLMResponse { - content: string; - usage: { - promptTokens: number; - completionTokens: number; - cost: number; - }; + content: string; + usage: { + promptTokens: number; + completionTokens: number; + cost: number; + }; } /** @@ -26,103 +26,107 @@ interface LLMResponse { * Handles markdown fences, control chars, trailing commas. */ export function cleanJson(str: string): string { - let cleaned = str.replace(/```json\n?|```/g, "").trim(); - cleaned = cleaned.replace( - /[\u0000-\u0009\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, - " ", - ); - cleaned = cleaned.replace(/,\s*([\]}])/g, "$1"); - return cleaned; + let cleaned = str.replace(/```json\n?|```/g, "").trim(); + // eslint-disable-next-line no-control-regex + cleaned = cleaned.replace(/[\x00-\x1f\x7f-\x9f]/gi, " "); + cleaned = cleaned.replace(/,\s*([\]}])/g, "$1"); + return cleaned; } /** * Send a request to an LLM via OpenRouter. */ -export async function llmRequest(options: LLMRequestOptions): Promise { - const { model, systemPrompt, userPrompt, jsonMode = true, apiKey } = options; +export async function llmRequest( + options: LLMRequestOptions, +): Promise { + const { model, systemPrompt, userPrompt, jsonMode = true, apiKey } = options; - const startTime = Date.now(); + const resp = await axios.post( + "https://openrouter.ai/api/v1/chat/completions", + { + model, + messages: [ + { role: "system", content: systemPrompt }, + { role: "user", content: userPrompt }, + ], + ...(jsonMode ? { response_format: { type: "json_object" } } : {}), + }, + { + headers: { + Authorization: `Bearer ${apiKey}`, + "Content-Type": "application/json", + }, + timeout: 120000, + }, + ); - const resp = await axios.post( - "https://openrouter.ai/api/v1/chat/completions", - { - model, - messages: [ - { role: "system", content: systemPrompt }, - { role: "user", content: userPrompt }, - ], - ...(jsonMode ? { response_format: { type: "json_object" } } : {}), - }, - { - headers: { - Authorization: `Bearer ${apiKey}`, - "Content-Type": "application/json", - }, - timeout: 120000, - }, - ); + const content = resp.data.choices?.[0]?.message?.content; + if (!content) { + throw new Error(`LLM returned no content. Model: ${model}`); + } - const content = resp.data.choices?.[0]?.message?.content; - if (!content) { - throw new Error(`LLM returned no content. Model: ${model}`); - } + let cost = 0; + const usage = resp.data.usage || {}; + if (usage.cost !== undefined) { + cost = usage.cost; + } else { + // Fallback estimation + cost = + (usage.prompt_tokens || 0) * (0.1 / 1_000_000) + + (usage.completion_tokens || 0) * (0.4 / 1_000_000); + } - let cost = 0; - const usage = resp.data.usage || {}; - if (usage.cost !== undefined) { - cost = usage.cost; - } else { - // Fallback estimation - cost = - (usage.prompt_tokens || 0) * (0.1 / 1_000_000) + - (usage.completion_tokens || 0) * (0.4 / 1_000_000); - } - - return { - content, - usage: { - promptTokens: usage.prompt_tokens || 0, - completionTokens: usage.completion_tokens || 0, - cost, - }, - }; + return { + content, + usage: { + promptTokens: usage.prompt_tokens || 0, + completionTokens: usage.completion_tokens || 0, + cost, + }, + }; } /** * Send a request and parse the response as JSON. */ export async function llmJsonRequest( - options: LLMRequestOptions, + options: LLMRequestOptions, ): Promise<{ data: T; usage: LLMResponse["usage"] }> { - const response = await llmRequest({ ...options, jsonMode: true }); - const cleaned = cleanJson(response.content); + const response = await llmRequest({ ...options, jsonMode: true }); + const cleaned = cleanJson(response.content); - let parsed: T; - try { - parsed = JSON.parse(cleaned); - } catch (e) { - throw new Error( - `Failed to parse LLM JSON response: ${(e as Error).message}\nRaw: ${cleaned.substring(0, 500)}`, - ); - } + let parsed: T; + try { + parsed = JSON.parse(cleaned); + } catch (e) { + throw new Error( + `Failed to parse LLM JSON response: ${(e as Error).message}\nRaw: ${cleaned.substring(0, 500)}`, + ); + } - // Unwrap common LLM artifacts: {"0": {...}}, {"state": {...}}, etc. - const unwrapped = unwrapResponse(parsed); + // Unwrap common LLM artifacts: {"0": {...}}, {"state": {...}}, etc. + const unwrapped = unwrapResponse(parsed); - return { data: unwrapped as T, usage: response.usage }; + return { data: unwrapped as T, usage: response.usage }; } /** * Recursively unwrap common LLM wrapping patterns. */ function unwrapResponse(obj: any): any { - if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj; - const keys = Object.keys(obj); - if (keys.length === 1) { - const key = keys[0]; - if (key === "0" || key === "state" || key === "facts" || key === "result" || key === "data") { - return unwrapResponse(obj[key]); - } + if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj; + const keys = Object.keys(obj); + if (keys.length === 1) { + const key = keys[0]; + if ( + key === "0" || + key === "state" || + key === "facts" || + key === "result" || + key === "data" + ) { + return unwrapResponse(obj[key]); } - return obj; + } + return obj; } diff --git a/packages/estimation-engine/src/pipeline.ts b/packages/estimation-engine/src/pipeline.ts index 321c418..65e61ab 100644 --- a/packages/estimation-engine/src/pipeline.ts +++ b/packages/estimation-engine/src/pipeline.ts @@ -5,22 +5,20 @@ import * as fs from "node:fs/promises"; import * as path from "node:path"; -import { existsSync } from "node:fs"; import { validateEstimation } from "./validators.js"; import { executeSynthesize } from "./steps/05-synthesize.js"; import { executeCritique } from "./steps/06-critique.js"; import type { - PipelineConfig, - PipelineInput, - EstimationState, - StepResult, - StepUsage, + PipelineConfig, + PipelineInput, + EstimationState, + StepResult, } from "./types.js"; export interface PipelineCallbacks { - onStepStart?: (stepId: string, stepName: string) => void; - onStepComplete?: (stepId: string, result: StepResult) => void; - onStepError?: (stepId: string, error: string) => void; + onStepStart?: (stepId: string, stepName: string) => void; + onStepComplete?: (stepId: string, result: StepResult) => void; + onStepError?: (stepId: string, error: string) => void; } /** @@ -28,201 +26,231 @@ export interface PipelineCallbacks { * Runs steps sequentially, persists state between steps, supports re-entry. */ export class EstimationPipeline { - private config: PipelineConfig; - private state: EstimationState; - private callbacks: PipelineCallbacks; + private config: PipelineConfig; + private state: EstimationState; + private callbacks: PipelineCallbacks; - constructor(config: PipelineConfig, callbacks: PipelineCallbacks = {}) { - this.config = config; - this.callbacks = callbacks; - this.state = this.createInitialState(); - } + constructor(config: PipelineConfig, callbacks: PipelineCallbacks = {}) { + this.config = config; + this.callbacks = callbacks; + this.state = this.createInitialState(); + } - private createInitialState(): EstimationState { - return { - concept: null as any, // Will be set in run() - usage: { - totalPromptTokens: 0, - totalCompletionTokens: 0, - totalCost: 0, - perStep: [], - }, - }; - } + private createInitialState(): EstimationState { + return { + concept: null as any, // Will be set in run() + usage: { + totalPromptTokens: 0, + totalCompletionTokens: 0, + totalCost: 0, + perStep: [], + }, + }; + } - /** - * Run the full estimation pipeline from a completed project concept. - */ - async run(input: PipelineInput): Promise { - this.state.concept = input.concept; - this.state.budget = input.budget; + /** + * Run the full estimation pipeline from a completed project concept. + */ + async run(input: PipelineInput): Promise { + this.state.concept = input.concept; + this.state.budget = input.budget; - // Ensure output directories - await fs.mkdir(this.config.outputDir, { recursive: true }); + // Ensure output directories + await fs.mkdir(this.config.outputDir, { recursive: true }); - // Step 5: Position synthesis - await this.runStep("05-synthesize", "Position Descriptions", async () => { - const result = await executeSynthesize(this.state, this.config); - if (result.success) this.state.positionDescriptions = result.data; - return result; - }); + // Step 5: Position synthesis + await this.runStep("05-synthesize", "Position Descriptions", async () => { + const result = await executeSynthesize(this.state, this.config); + if (result.success) this.state.positionDescriptions = result.data; + return result; + }); - // Step 6: Quality critique - await this.runStep("06-critique", "Quality Gate (Industrial Critic)", async () => { - const result = await executeCritique(this.state, this.config); - if (result.success) { - this.state.critiquePassed = result.data.passed; - this.state.critiqueErrors = result.data.errors?.map((e: any) => `${e.field}: ${e.issue}`) || []; + // Step 6: Quality critique + await this.runStep( + "06-critique", + "Quality Gate (Industrial Critic)", + async () => { + const result = await executeCritique(this.state, this.config); + if (result.success) { + this.state.critiquePassed = result.data.passed; + this.state.critiqueErrors = + result.data.errors?.map((e: any) => `${e.field}: ${e.issue}`) || []; - // Apply corrections - if (result.data.corrections) { - const corrections = result.data.corrections; - // Note: We only correct the positionDescriptions since briefing/design/sitemap are locked in the concept phase. - // If the critique suggests changes to those, it should be a warning or failure. - if (corrections.positionDescriptions) { - this.state.positionDescriptions = { - ...this.state.positionDescriptions, - ...corrections.positionDescriptions, - }; - } - } + // Apply corrections + if (result.data.corrections) { + const corrections = result.data.corrections; + // Note: We only correct the positionDescriptions since briefing/design/sitemap are locked in the concept phase. + // If the critique suggests changes to those, it should be a warning or failure. + if (corrections.positionDescriptions) { + this.state.positionDescriptions = { + ...this.state.positionDescriptions, + ...corrections.positionDescriptions, + }; } - return result; - }); - - // Step 7: Deterministic validation - await this.runStep("07-validate", "Deterministic Validation", async () => { - // Build the merged form state first - this.state.formState = this.buildFormState(); - const validationResult = validateEstimation(this.state); - this.state.validationResult = validationResult; - - if (!validationResult.passed) { - console.log("\n⚠️ Validation Issues:"); - for (const error of validationResult.errors) { - console.log(` ❌ [${error.code}] ${error.message}`); - } - } - if (validationResult.warnings.length > 0) { - console.log("\n⚡ Warnings:"); - for (const warning of validationResult.warnings) { - console.log(` ⚡ [${warning.code}] ${warning.message}`); - if (warning.suggestion) console.log(` → ${warning.suggestion}`); - } - } - - return { - success: true, - data: validationResult, - usage: { step: "07-validate", model: "none", promptTokens: 0, completionTokens: 0, cost: 0, durationMs: 0 }, - }; - }); - - // Save final state - await this.saveState(); - - return this.state; - } - - /** - * Run a single step with callbacks and error handling. - */ - private async runStep( - stepId: string, - stepName: string, - executor: () => Promise, - ): Promise { - this.callbacks.onStepStart?.(stepId, stepName); - console.log(`\n📍 ${stepName}...`); - - try { - const result = await executor(); - if (result.usage) { - this.state.usage.perStep.push(result.usage); - this.state.usage.totalPromptTokens += result.usage.promptTokens; - this.state.usage.totalCompletionTokens += result.usage.completionTokens; - this.state.usage.totalCost += result.usage.cost; - } - - if (result.success) { - const cost = result.usage?.cost ? ` ($${result.usage.cost.toFixed(4)})` : ""; - const duration = result.usage?.durationMs ? ` [${(result.usage.durationMs / 1000).toFixed(1)}s]` : ""; - console.log(` ✅ ${stepName} complete${cost}${duration}`); - this.callbacks.onStepComplete?.(stepId, result); - } else { - console.error(` ❌ ${stepName} failed: ${result.error}`); - this.callbacks.onStepError?.(stepId, result.error || "Unknown error"); - throw new Error(result.error); - } - } catch (err) { - const errorMsg = (err as Error).message; - this.callbacks.onStepError?.(stepId, errorMsg); - throw err; + } } - } + return result; + }, + ); - /** - * Build the final FormState compatible with @mintel/pdf. - */ - private buildFormState(): Record { - const facts = this.state.concept.auditedFacts || {}; - return { - projectType: "website", - ...facts, - briefingSummary: this.state.concept.strategy.briefingSummary || "", - designVision: this.state.concept.strategy.designVision || "", - sitemap: this.state.concept.architecture.sitemap || [], - positionDescriptions: this.state.positionDescriptions || {}, - websiteTopic: this.state.concept.architecture.websiteTopic || facts.websiteTopic || "", - statusQuo: facts.isRelaunch ? "Relaunch" : "Neuentwicklung", - name: facts.personName || "", - email: facts.email || "", - }; - } + // Step 7: Deterministic validation + await this.runStep("07-validate", "Deterministic Validation", async () => { + // Build the merged form state first + this.state.formState = this.buildFormState(); + const validationResult = validateEstimation(this.state); + this.state.validationResult = validationResult; - /** - * Save the full state to disk for later re-use. - */ - private async saveState(): Promise { - const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); - const companyName = this.state.concept.auditedFacts?.companyName || "unknown"; - - // Save full state - const stateDir = path.join(this.config.outputDir, "json"); - await fs.mkdir(stateDir, { recursive: true }); - - const statePath = path.join(stateDir, `${companyName}_${timestamp}.json`); - await fs.writeFile(statePath, JSON.stringify(this.state.formState, null, 2)); - console.log(`\n📦 Saved state to: ${statePath}`); - - // Save full pipeline state (for debugging / re-entry) - const debugPath = path.join(stateDir, `${companyName}_${timestamp}_debug.json`); - await fs.writeFile(debugPath, JSON.stringify(this.state, null, 2)); - - // Print usage summary - console.log("\n──────────────────────────────────────────────"); - console.log("📊 PIPELINE USAGE SUMMARY"); - console.log("──────────────────────────────────────────────"); - for (const step of this.state.usage.perStep) { - if (step.cost > 0) { - console.log(` ${step.step}: ${step.model} — $${step.cost.toFixed(6)} (${(step.durationMs / 1000).toFixed(1)}s)`); - } + if (!validationResult.passed) { + console.log("\n⚠️ Validation Issues:"); + for (const error of validationResult.errors) { + console.log(` ❌ [${error.code}] ${error.message}`); } - console.log("──────────────────────────────────────────────"); - console.log(` TOTAL: $${this.state.usage.totalCost.toFixed(6)}`); - console.log(` Tokens: ${(this.state.usage.totalPromptTokens + this.state.usage.totalCompletionTokens).toLocaleString()}`); - console.log("──────────────────────────────────────────────\n"); - } + } + if (validationResult.warnings.length > 0) { + console.log("\n⚡ Warnings:"); + for (const warning of validationResult.warnings) { + console.log(` ⚡ [${warning.code}] ${warning.message}`); + if (warning.suggestion) console.log(` → ${warning.suggestion}`); + } + } - /** Get the current state (for CLI inspection). */ - getState(): EstimationState { - return this.state; - } + return { + success: true, + data: validationResult, + usage: { + step: "07-validate", + model: "none", + promptTokens: 0, + completionTokens: 0, + cost: 0, + durationMs: 0, + }, + }; + }); - /** Load a saved state from JSON. */ - async loadState(jsonPath: string): Promise { - const raw = await fs.readFile(jsonPath, "utf8"); - const formState = JSON.parse(raw); - this.state.formState = formState; + // Save final state + await this.saveState(); + + return this.state; + } + + /** + * Run a single step with callbacks and error handling. + */ + private async runStep( + stepId: string, + stepName: string, + executor: () => Promise, + ): Promise { + this.callbacks.onStepStart?.(stepId, stepName); + console.log(`\n📍 ${stepName}...`); + + try { + const result = await executor(); + if (result.usage) { + this.state.usage.perStep.push(result.usage); + this.state.usage.totalPromptTokens += result.usage.promptTokens; + this.state.usage.totalCompletionTokens += result.usage.completionTokens; + this.state.usage.totalCost += result.usage.cost; + } + + if (result.success) { + const cost = result.usage?.cost + ? ` ($${result.usage.cost.toFixed(4)})` + : ""; + const duration = result.usage?.durationMs + ? ` [${(result.usage.durationMs / 1000).toFixed(1)}s]` + : ""; + console.log(` ✅ ${stepName} complete${cost}${duration}`); + this.callbacks.onStepComplete?.(stepId, result); + } else { + console.error(` ❌ ${stepName} failed: ${result.error}`); + this.callbacks.onStepError?.(stepId, result.error || "Unknown error"); + throw new Error(result.error); + } + } catch (err) { + const errorMsg = (err as Error).message; + this.callbacks.onStepError?.(stepId, errorMsg); + throw err; } + } + + /** + * Build the final FormState compatible with @mintel/pdf. + */ + private buildFormState(): Record { + const facts = this.state.concept.auditedFacts || {}; + return { + projectType: "website", + ...facts, + briefingSummary: this.state.concept.strategy.briefingSummary || "", + designVision: this.state.concept.strategy.designVision || "", + sitemap: this.state.concept.architecture.sitemap || [], + positionDescriptions: this.state.positionDescriptions || {}, + websiteTopic: + this.state.concept.architecture.websiteTopic || + facts.websiteTopic || + "", + statusQuo: facts.isRelaunch ? "Relaunch" : "Neuentwicklung", + name: facts.personName || "", + email: facts.email || "", + }; + } + + /** + * Save the full state to disk for later re-use. + */ + private async saveState(): Promise { + const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); + const companyName = + this.state.concept.auditedFacts?.companyName || "unknown"; + + // Save full state + const stateDir = path.join(this.config.outputDir, "json"); + await fs.mkdir(stateDir, { recursive: true }); + + const statePath = path.join(stateDir, `${companyName}_${timestamp}.json`); + await fs.writeFile( + statePath, + JSON.stringify(this.state.formState, null, 2), + ); + console.log(`\n📦 Saved state to: ${statePath}`); + + // Save full pipeline state (for debugging / re-entry) + const debugPath = path.join( + stateDir, + `${companyName}_${timestamp}_debug.json`, + ); + await fs.writeFile(debugPath, JSON.stringify(this.state, null, 2)); + + // Print usage summary + console.log("\n──────────────────────────────────────────────"); + console.log("📊 PIPELINE USAGE SUMMARY"); + console.log("──────────────────────────────────────────────"); + for (const step of this.state.usage.perStep) { + if (step.cost > 0) { + console.log( + ` ${step.step}: ${step.model} — $${step.cost.toFixed(6)} (${(step.durationMs / 1000).toFixed(1)}s)`, + ); + } + } + console.log("──────────────────────────────────────────────"); + console.log(` TOTAL: $${this.state.usage.totalCost.toFixed(6)}`); + console.log( + ` Tokens: ${(this.state.usage.totalPromptTokens + this.state.usage.totalCompletionTokens).toLocaleString()}`, + ); + console.log("──────────────────────────────────────────────\n"); + } + + /** Get the current state (for CLI inspection). */ + getState(): EstimationState { + return this.state; + } + + /** Load a saved state from JSON. */ + async loadState(jsonPath: string): Promise { + const raw = await fs.readFile(jsonPath, "utf8"); + const formState = JSON.parse(raw); + this.state.formState = formState; + } } diff --git a/packages/estimation-engine/src/types.ts b/packages/estimation-engine/src/types.ts index 526c716..7089dff 100644 --- a/packages/estimation-engine/src/types.ts +++ b/packages/estimation-engine/src/types.ts @@ -2,112 +2,112 @@ // @mintel/estimation-engine — Core Type Definitions // ============================================================================ -import type { ProjectConcept, SitemapCategory } from "@mintel/concept-engine"; +import type { ProjectConcept } from "@mintel/concept-engine"; /** Configuration for the estimation pipeline */ export interface PipelineConfig { - openrouterKey: string; - zyteApiKey?: string; - outputDir: string; - crawlDir: string; - modelsOverride?: Partial; + openrouterKey: string; + zyteApiKey?: string; + outputDir: string; + crawlDir: string; + modelsOverride?: Partial; } /** Model routing configuration */ export interface ModelConfig { - flash: string; - pro: string; - opus: string; + flash: string; + pro: string; + opus: string; } export const DEFAULT_MODELS: ModelConfig = { - flash: "google/gemini-3-flash-preview", - pro: "google/gemini-3.1-pro-preview", - opus: "anthropic/claude-opus-4-6", + flash: "google/gemini-3-flash-preview", + pro: "google/gemini-3.1-pro-preview", + opus: "anthropic/claude-opus-4-6", }; /** Input for the estimation pipeline */ export interface PipelineInput { - concept: ProjectConcept; - budget?: string; + concept: ProjectConcept; + budget?: string; } /** State that flows through all pipeline steps */ export interface EstimationState { - // Input - concept: ProjectConcept; - budget?: string; + // Input + concept: ProjectConcept; + budget?: string; - // Step 5 output: Position Synthesis - positionDescriptions?: Record; + // Step 5 output: Position Synthesis + positionDescriptions?: Record; - // Step 6 output: Critique - critiquePassed?: boolean; - critiqueErrors?: string[]; + // Step 6 output: Critique + critiquePassed?: boolean; + critiqueErrors?: string[]; - // Step 7 output: Validation - validationResult?: ValidationResult; + // Step 7 output: Validation + validationResult?: ValidationResult; - // Final merged form state for PDF generation - formState?: Record; + // Final merged form state for PDF generation + formState?: Record; - // Cost tracking - usage: UsageStats; + // Cost tracking + usage: UsageStats; } export interface UsageStats { - totalPromptTokens: number; - totalCompletionTokens: number; - totalCost: number; - perStep: StepUsage[]; + totalPromptTokens: number; + totalCompletionTokens: number; + totalCost: number; + perStep: StepUsage[]; } export interface StepUsage { - step: string; - model: string; - promptTokens: number; - completionTokens: number; - cost: number; - durationMs: number; + step: string; + model: string; + promptTokens: number; + completionTokens: number; + cost: number; + durationMs: number; } /** Result of a single pipeline step */ export interface StepResult { - success: boolean; - data?: T; - error?: string; - usage?: StepUsage; + success: boolean; + data?: T; + error?: string; + usage?: StepUsage; } /** Validation result from the deterministic validator */ export interface ValidationResult { - passed: boolean; - errors: ValidationError[]; - warnings: ValidationWarning[]; + passed: boolean; + errors: ValidationError[]; + warnings: ValidationWarning[]; } export interface ValidationError { - code: string; - message: string; - field?: string; - expected?: any; - actual?: any; + code: string; + message: string; + field?: string; + expected?: any; + actual?: any; } export interface ValidationWarning { - code: string; - message: string; - suggestion?: string; + code: string; + message: string; + suggestion?: string; } /** Step definition for the pipeline */ export interface PipelineStep { - id: string; - name: string; - description: string; - model: "flash" | "pro" | "opus" | "none"; - execute: ( - state: EstimationState, - config: PipelineConfig, - ) => Promise; + id: string; + name: string; + description: string; + model: "flash" | "pro" | "opus" | "none"; + execute: ( + state: EstimationState, + config: PipelineConfig, + ) => Promise; } diff --git a/packages/estimation-engine/src/validators.ts b/packages/estimation-engine/src/validators.ts index 716d5d3..4ab6897 100644 --- a/packages/estimation-engine/src/validators.ts +++ b/packages/estimation-engine/src/validators.ts @@ -3,53 +3,67 @@ // Catches all the issues reported by the user programmatically. // ============================================================================ -import type { EstimationState, ValidationResult, ValidationError, ValidationWarning } from "./types.js"; +import type { + EstimationState, + ValidationResult, + ValidationError, + ValidationWarning, +} from "./types.js"; /** * Run all deterministic validation checks on the final estimation state. */ export function validateEstimation(state: EstimationState): ValidationResult { - const errors: ValidationError[] = []; - const warnings: ValidationWarning[] = []; - - if (!state.formState) { - return { passed: false, errors: [{ code: "NO_FORM_STATE", message: "No form state available for validation." }], warnings: [] }; - } - - const fs = state.formState; - - // 1. PAGE COUNT PARITY - validatePageCountParity(fs, errors); - - // 2. SORGLOS-BETRIEB IN SUMMARY - validateSorglosBetrieb(fs, errors, warnings); - - // 3. NO VIDEOS AS PAGES - validateNoVideosAsPages(fs, errors); - - // 4. EXTERNAL DOMAINS NOT AS PAGES - validateExternalDomains(fs, state.concept?.siteProfile, errors); - - // 5. SERVICE COVERAGE - validateServiceCoverage(fs, state.concept?.siteProfile, warnings); - - // 6. EXISTING FEATURE DETECTION - validateExistingFeatures(fs, state.concept?.siteProfile, warnings); - - // 7. MULTILANG LABEL CORRECTNESS - validateMultilangLabeling(fs, errors); - - // 8. INITIAL-PFLEGE UNITS - validateInitialPflegeUnits(fs, warnings); - - // 9. SITEMAP vs PAGE LIST CONSISTENCY - validateSitemapConsistency(fs, errors); + const errors: ValidationError[] = []; + const warnings: ValidationWarning[] = []; + if (!state.formState) { return { - passed: errors.length === 0, - errors, - warnings, + passed: false, + errors: [ + { + code: "NO_FORM_STATE", + message: "No form state available for validation.", + }, + ], + warnings: [], }; + } + + const fs = state.formState; + + // 1. PAGE COUNT PARITY + validatePageCountParity(fs, errors); + + // 2. SORGLOS-BETRIEB IN SUMMARY + validateSorglosBetrieb(fs, errors, warnings); + + // 3. NO VIDEOS AS PAGES + validateNoVideosAsPages(fs, errors); + + // 4. EXTERNAL DOMAINS NOT AS PAGES + validateExternalDomains(fs, state.concept?.siteProfile, errors); + + // 5. SERVICE COVERAGE + validateServiceCoverage(fs, state.concept?.siteProfile, warnings); + + // 6. EXISTING FEATURE DETECTION + validateExistingFeatures(fs, state.concept?.siteProfile, warnings); + + // 7. MULTILANG LABEL CORRECTNESS + validateMultilangLabeling(fs, errors); + + // 8. INITIAL-PFLEGE UNITS + validateInitialPflegeUnits(fs, warnings); + + // 9. SITEMAP vs PAGE LIST CONSISTENCY + validateSitemapConsistency(fs, errors); + + return { + passed: errors.length === 0, + errors, + warnings, + }; } /** @@ -63,57 +77,62 @@ export function validateEstimation(state: EstimationState): ValidationResult { * Instead, we verify that the position description text lists the right count. */ function validatePageCountParity( - fs: Record, - errors: ValidationError[], + fs: Record, + errors: ValidationError[], ): void { - // Count pages listed in the sitemap (the source of truth) - let sitemapPageCount = 0; - if (Array.isArray(fs.sitemap)) { - for (const cat of fs.sitemap) { - sitemapPageCount += (cat.pages || []).length; - } + // Count pages listed in the sitemap (the source of truth) + let sitemapPageCount = 0; + if (Array.isArray(fs.sitemap)) { + for (const cat of fs.sitemap) { + sitemapPageCount += (cat.pages || []).length; } - if (sitemapPageCount === 0) return; + } + if (sitemapPageCount === 0) return; - // Extract page names mentioned in the "Individuelle Seiten" position description - const positions = fs.positionDescriptions || {}; - const pagesDesc = positions["Individuelle Seiten"] || positions["2. Individuelle Seiten"] || ""; - if (!pagesDesc) return; + // Extract page names mentioned in the "Individuelle Seiten" position description + const positions = fs.positionDescriptions || {}; + const pagesDesc = + positions["Individuelle Seiten"] || + positions["2. Individuelle Seiten"] || + ""; + if (!pagesDesc) return; - const descStr = typeof pagesDesc === "string" ? pagesDesc : ""; + const descStr = typeof pagesDesc === "string" ? pagesDesc : ""; - // Count distinct page names mentioned (split by comma) - // We avoid splitting by "&" or "und" because actual page names like - // "Wartung & Störungsdienst" or "Genehmigungs- und Ausführungsplanung" contain them. - const afterColon = descStr.includes(":") ? descStr.split(":").slice(1).join(":") : descStr; - const segments = afterColon - .split(/,/) - .map((s: string) => s.replace(/\.$/, "").trim()) - .filter((s: string) => s.length > 2); + // Count distinct page names mentioned (split by comma) + // We avoid splitting by "&" or "und" because actual page names like + // "Wartung & Störungsdienst" or "Genehmigungs- und Ausführungsplanung" contain them. + const afterColon = descStr.includes(":") + ? descStr.split(":").slice(1).join(":") + : descStr; + const segments = afterColon + .split(/,/) + .map((s: string) => s.replace(/\.$/, "").trim()) + .filter((s: string) => s.length > 2); - // Handle consolidated references like "Leistungen (6 Unterseiten)" or "(inkl. Messen)" - let mentionedCount = 0; - for (const seg of segments) { - const subPageMatch = seg.match(/\((\d+)\s+(?:Unter)?[Ss]eiten?\)/); - if (subPageMatch) { - mentionedCount += parseInt(subPageMatch[1], 10); - } else if (seg.match(/\(inkl\.\s+/)) { - // "Unternehmen (inkl. Messen)" = 2 pages - mentionedCount += 2; - } else { - mentionedCount += 1; - } + // Handle consolidated references like "Leistungen (6 Unterseiten)" or "(inkl. Messen)" + let mentionedCount = 0; + for (const seg of segments) { + const subPageMatch = seg.match(/\((\d+)\s+(?:Unter)?[Ss]eiten?\)/); + if (subPageMatch) { + mentionedCount += parseInt(subPageMatch[1], 10); + } else if (seg.match(/\(inkl\.\s+/)) { + // "Unternehmen (inkl. Messen)" = 2 pages + mentionedCount += 2; + } else { + mentionedCount += 1; } + } - if (mentionedCount > 0 && Math.abs(mentionedCount - sitemapPageCount) > 2) { - errors.push({ - code: "PAGE_COUNT_MISMATCH", - message: `Seiten-Beschreibung nennt ~${mentionedCount} Seiten, aber ${sitemapPageCount} Seiten in der Sitemap.`, - field: "positionDescriptions.Individuelle Seiten", - expected: sitemapPageCount, - actual: mentionedCount, - }); - } + if (mentionedCount > 0 && Math.abs(mentionedCount - sitemapPageCount) > 2) { + errors.push({ + code: "PAGE_COUNT_MISMATCH", + message: `Seiten-Beschreibung nennt ~${mentionedCount} Seiten, aber ${sitemapPageCount} Seiten in der Sitemap.`, + field: "positionDescriptions.Individuelle Seiten", + expected: sitemapPageCount, + actual: mentionedCount, + }); + } } /** @@ -121,25 +140,25 @@ function validatePageCountParity( * "Zusammenfassung der Schätzung hat Sorglos-Betrieb nicht miteingenommen" */ function validateSorglosBetrieb( - fs: Record, - errors: ValidationError[], - warnings: ValidationWarning[], + fs: Record, + errors: ValidationError[], + _warnings: ValidationWarning[], ): void { - const positions = fs.positionDescriptions || {}; - const hasPosition = Object.keys(positions).some( - (k) => - k.toLowerCase().includes("sorglos") || - k.toLowerCase().includes("betrieb") || - k.toLowerCase().includes("pflege"), - ); + const positions = fs.positionDescriptions || {}; + const hasPosition = Object.keys(positions).some( + (k) => + k.toLowerCase().includes("sorglos") || + k.toLowerCase().includes("betrieb") || + k.toLowerCase().includes("pflege"), + ); - if (!hasPosition) { - errors.push({ - code: "MISSING_SORGLOS_BETRIEB", - message: "Der Sorglos-Betrieb fehlt in den Position-Beschreibungen.", - field: "positionDescriptions", - }); - } + if (!hasPosition) { + errors.push({ + code: "MISSING_SORGLOS_BETRIEB", + message: "Der Sorglos-Betrieb fehlt in den Position-Beschreibungen.", + field: "positionDescriptions", + }); + } } /** @@ -147,27 +166,33 @@ function validateSorglosBetrieb( * "Er hat Videos als eigene Seite aufgenommen" */ function validateNoVideosAsPages( - fs: Record, - errors: ValidationError[], + fs: Record, + errors: ValidationError[], ): void { - const allPages = [...(fs.selectedPages || []), ...(fs.otherPages || [])]; - const sitemapPages = Array.isArray(fs.sitemap) - ? fs.sitemap.flatMap((cat: any) => (cat.pages || []).map((p: any) => p.title)) - : []; + const allPages = [...(fs.selectedPages || []), ...(fs.otherPages || [])]; + const sitemapPages = Array.isArray(fs.sitemap) + ? fs.sitemap.flatMap((cat: any) => + (cat.pages || []).map((p: any) => p.title), + ) + : []; - const allPageNames = [...allPages, ...sitemapPages]; - const videoKeywords = ["video", "film", "messefilm", "imagefilm", "clip"]; + const allPageNames = [...allPages, ...sitemapPages]; + const videoKeywords = ["video", "film", "messefilm", "imagefilm", "clip"]; - for (const pageName of allPageNames) { - const lower = (typeof pageName === "string" ? pageName : "").toLowerCase(); - if (videoKeywords.some((kw) => lower.includes(kw) && !lower.includes("leistung"))) { - errors.push({ - code: "VIDEO_AS_PAGE", - message: `"${pageName}" ist ein Video-Asset, keine eigene Seite.`, - field: "sitemap", - }); - } + for (const pageName of allPageNames) { + const lower = (typeof pageName === "string" ? pageName : "").toLowerCase(); + if ( + videoKeywords.some( + (kw) => lower.includes(kw) && !lower.includes("leistung"), + ) + ) { + errors.push({ + code: "VIDEO_AS_PAGE", + message: `"${pageName}" ist ein Video-Asset, keine eigene Seite.`, + field: "sitemap", + }); } + } } /** @@ -175,32 +200,40 @@ function validateNoVideosAsPages( * "er hat ingenieursgesellschaft als seite integriert, die haben aber eine eigene website" */ function validateExternalDomains( - fs: Record, - siteProfile: any, - errors: ValidationError[], + fs: Record, + siteProfile: any, + errors: ValidationError[], ): void { - if (!siteProfile?.externalDomains?.length) return; + if (!siteProfile?.externalDomains?.length) return; - const sitemapPages = Array.isArray(fs.sitemap) - ? fs.sitemap.flatMap((cat: any) => (cat.pages || []).map((p: any) => p.title || "")) - : []; + const sitemapPages = Array.isArray(fs.sitemap) + ? fs.sitemap.flatMap((cat: any) => + (cat.pages || []).map((p: any) => p.title || ""), + ) + : []; - for (const extDomain of siteProfile.externalDomains) { - // Extract base name (e.g. "etib-ing" from "etib-ing.com") - const baseName = extDomain.replace(/^www\./, "").split(".")[0].toLowerCase(); + for (const extDomain of siteProfile.externalDomains) { + // Extract base name (e.g. "etib-ing" from "etib-ing.com") + const baseName = extDomain + .replace(/^www\./, "") + .split(".")[0] + .toLowerCase(); - for (const pageTitle of sitemapPages) { - const lower = pageTitle.toLowerCase(); - // Check if the page title references the external company - if (lower.includes(baseName) || (lower.includes("ingenieur") && extDomain.includes("ing"))) { - errors.push({ - code: "EXTERNAL_DOMAIN_AS_PAGE", - message: `"${pageTitle}" hat eine eigene Website (${extDomain}) und darf nicht als Unterseite vorgeschlagen werden.`, - field: "sitemap", - }); - } - } + for (const pageTitle of sitemapPages) { + const lower = pageTitle.toLowerCase(); + // Check if the page title references the external company + if ( + lower.includes(baseName) || + (lower.includes("ingenieur") && extDomain.includes("ing")) + ) { + errors.push({ + code: "EXTERNAL_DOMAIN_AS_PAGE", + message: `"${pageTitle}" hat eine eigene Website (${extDomain}) und darf nicht als Unterseite vorgeschlagen werden.`, + field: "sitemap", + }); + } } + } } /** @@ -208,30 +241,30 @@ function validateExternalDomains( * "er hat leistungen ausgelassen die ganz klar auf der kompetenz seite genannt werden" */ function validateServiceCoverage( - fs: Record, - siteProfile: any, - warnings: ValidationWarning[], + fs: Record, + siteProfile: any, + warnings: ValidationWarning[], ): void { - if (!siteProfile?.services?.length) return; + if (!siteProfile?.services?.length) return; - const allContent = JSON.stringify(fs).toLowerCase(); + const allContent = JSON.stringify(fs).toLowerCase(); - for (const service of siteProfile.services) { - const keywords = service - .toLowerCase() - .split(/[\s,&-]+/) - .filter((w: string) => w.length > 4); + for (const service of siteProfile.services) { + const keywords = service + .toLowerCase() + .split(/[\s,&-]+/) + .filter((w: string) => w.length > 4); - const isCovered = keywords.some((kw: string) => allContent.includes(kw)); + const isCovered = keywords.some((kw: string) => allContent.includes(kw)); - if (!isCovered && service.length > 5) { - warnings.push({ - code: "MISSING_SERVICE", - message: `Bestehende Leistung "${service}" ist nicht in der Schätzung berücksichtigt.`, - suggestion: `Prüfen ob "${service}" im Briefing gewünscht ist und ggf. in die Seitenstruktur aufnehmen.`, - }); - } + if (!isCovered && service.length > 5) { + warnings.push({ + code: "MISSING_SERVICE", + message: `Bestehende Leistung "${service}" ist nicht in der Schätzung berücksichtigt.`, + suggestion: `Prüfen ob "${service}" im Briefing gewünscht ist und ggf. in die Seitenstruktur aufnehmen.`, + }); } + } } /** @@ -239,32 +272,32 @@ function validateServiceCoverage( * "er hat die suchfunktion nicht bemerkt, die gibts schon auf der seite" */ function validateExistingFeatures( - fs: Record, - siteProfile: any, - warnings: ValidationWarning[], + fs: Record, + siteProfile: any, + warnings: ValidationWarning[], ): void { - if (!siteProfile?.existingFeatures?.length) return; + if (!siteProfile?.existingFeatures?.length) return; - const functions = fs.functions || []; - const features = fs.features || []; - const allSelected = [...functions, ...features]; + const functions = fs.functions || []; + const features = fs.features || []; + const allSelected = [...functions, ...features]; - for (const existingFeature of siteProfile.existingFeatures) { - if (existingFeature === "cookie-consent") continue; // Standard, don't flag - if (existingFeature === "video") continue; // Usually an asset, not a feature + for (const existingFeature of siteProfile.existingFeatures) { + if (existingFeature === "cookie-consent") continue; // Standard, don't flag + if (existingFeature === "video") continue; // Usually an asset, not a feature - const isMapped = allSelected.some( - (f: string) => f.toLowerCase() === existingFeature.toLowerCase(), - ); + const isMapped = allSelected.some( + (f: string) => f.toLowerCase() === existingFeature.toLowerCase(), + ); - if (!isMapped) { - warnings.push({ - code: "EXISTING_FEATURE_IGNORED", - message: `Die bestehende Suchfunktion/Feature "${existingFeature}" wurde auf der aktuellen Website erkannt, aber nicht in der Schätzung berücksichtigt.`, - suggestion: `"${existingFeature}" als Function oder Feature aufnehmen, da es bereits existiert und der Kunde es erwartet.`, - }); - } + if (!isMapped) { + warnings.push({ + code: "EXISTING_FEATURE_IGNORED", + message: `Die bestehende Suchfunktion/Feature "${existingFeature}" wurde auf der aktuellen Website erkannt, aber nicht in der Schätzung berücksichtigt.`, + suggestion: `"${existingFeature}" als Function oder Feature aufnehmen, da es bereits existiert und der Kunde es erwartet.`, + }); } + } } /** @@ -272,27 +305,30 @@ function validateExistingFeatures( * "die +20% beziehen sich nicht auf API" */ function validateMultilangLabeling( - fs: Record, - errors: ValidationError[], + fs: Record, + errors: ValidationError[], ): void { - const positions = fs.positionDescriptions || {}; + const positions = fs.positionDescriptions || {}; - for (const [key, desc] of Object.entries(positions)) { - if (key.toLowerCase().includes("api") || key.toLowerCase().includes("schnittstelle")) { - const descStr = typeof desc === "string" ? desc : ""; - if ( - descStr.toLowerCase().includes("mehrsprach") || - descStr.toLowerCase().includes("multilang") || - descStr.toLowerCase().includes("20%") - ) { - errors.push({ - code: "MULTILANG_WRONG_POSITION", - message: `Mehrsprachigkeit (+20%) ist unter "${key}" eingeordnet, gehört aber nicht zu API/Schnittstellen.`, - field: key, - }); - } - } + for (const [key, desc] of Object.entries(positions)) { + if ( + key.toLowerCase().includes("api") || + key.toLowerCase().includes("schnittstelle") + ) { + const descStr = typeof desc === "string" ? desc : ""; + if ( + descStr.toLowerCase().includes("mehrsprach") || + descStr.toLowerCase().includes("multilang") || + descStr.toLowerCase().includes("20%") + ) { + errors.push({ + code: "MULTILANG_WRONG_POSITION", + message: `Mehrsprachigkeit (+20%) ist unter "${key}" eingeordnet, gehört aber nicht zu API/Schnittstellen.`, + field: key, + }); + } } + } } /** @@ -300,81 +336,101 @@ function validateMultilangLabeling( * "Initialpflege => 100€/Stk => damit sind keine Seiten sondern Datensätze" */ function validateInitialPflegeUnits( - fs: Record, - warnings: ValidationWarning[], + fs: Record, + warnings: ValidationWarning[], ): void { - const positions = fs.positionDescriptions || {}; + const positions = fs.positionDescriptions || {}; - for (const [key, desc] of Object.entries(positions)) { - if (key.toLowerCase().includes("pflege") || key.toLowerCase().includes("initial")) { - const descStr = typeof desc === "string" ? desc : ""; - if (descStr.toLowerCase().includes("seiten") && !descStr.toLowerCase().includes("datensätz")) { - warnings.push({ - code: "INITIALPFLEGE_WRONG_UNIT", - message: `"${key}" spricht von "Seiten", aber gemeint sind Datensätze (z.B. Produkte, Referenzen).`, - suggestion: `Beschreibung auf "Datensätze" statt "Seiten" ändern.`, - }); - } - } + for (const [key, desc] of Object.entries(positions)) { + if ( + key.toLowerCase().includes("pflege") || + key.toLowerCase().includes("initial") + ) { + const descStr = typeof desc === "string" ? desc : ""; + if ( + descStr.toLowerCase().includes("seiten") && + !descStr.toLowerCase().includes("datensätz") + ) { + warnings.push({ + code: "INITIALPFLEGE_WRONG_UNIT", + message: `"${key}" spricht von "Seiten", aber gemeint sind Datensätze (z.B. Produkte, Referenzen).`, + suggestion: `Beschreibung auf "Datensätze" statt "Seiten" ändern.`, + }); + } } + } } /** * 9. Position descriptions must match calculated quantities. */ +/** + * 9. Position descriptions must match calculated quantities. + */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars function validatePositionDescriptionsMath( - fs: Record, - errors: ValidationError[], + fs: Record, + errors: ValidationError[], ): void { - const positions = fs.positionDescriptions || {}; + const positions = fs.positionDescriptions || {}; - // Check pages description mentions correct count - const pagesDesc = positions["Individuelle Seiten"] || positions["2. Individuelle Seiten"] || ""; - if (pagesDesc) { - // Use the sitemap as the authoritative source of truth for page count - let sitemapPageCount = 0; - if (Array.isArray(fs.sitemap)) { - for (const cat of fs.sitemap) { - sitemapPageCount += (cat.pages || []).length; - } - } - - // Count how many page names are mentioned in the description - const descStr = typeof pagesDesc === "string" ? pagesDesc : ""; - const mentionedPages = descStr.split(/,|und|&/).filter((s: string) => s.trim().length > 2); - - if (sitemapPageCount > 0 && mentionedPages.length > 0 && Math.abs(mentionedPages.length - sitemapPageCount) > 2) { - errors.push({ - code: "PAGES_DESC_COUNT_MISMATCH", - message: `Seiten-Beschreibung nennt ~${mentionedPages.length} Seiten, aber ${sitemapPageCount} in der Sitemap.`, - field: "positionDescriptions.Individuelle Seiten", - expected: sitemapPageCount, - actual: mentionedPages.length, - }); - } + // Check pages description mentions correct count + const pagesDesc = + positions["Individuelle Seiten"] || + positions["2. Individuelle Seiten"] || + ""; + if (pagesDesc) { + // Use the sitemap as the authoritative source of truth for page count + let sitemapPageCount = 0; + if (Array.isArray(fs.sitemap)) { + for (const cat of fs.sitemap) { + sitemapPageCount += (cat.pages || []).length; + } } + + // Count how many page names are mentioned in the description + const descStr = typeof pagesDesc === "string" ? pagesDesc : ""; + const mentionedPages = descStr + .split(/,|und|&/) + .filter((s: string) => s.trim().length > 2); + + if ( + sitemapPageCount > 0 && + mentionedPages.length > 0 && + Math.abs(mentionedPages.length - sitemapPageCount) > 2 + ) { + errors.push({ + code: "PAGES_DESC_COUNT_MISMATCH", + message: `Seiten-Beschreibung nennt ~${mentionedPages.length} Seiten, aber ${sitemapPageCount} in der Sitemap.`, + field: "positionDescriptions.Individuelle Seiten", + expected: sitemapPageCount, + actual: mentionedPages.length, + }); + } + } } /** * 10. Sitemap categories should be consistent with selected pages/features. */ function validateSitemapConsistency( - fs: Record, - errors: ValidationError[], + fs: Record, + errors: ValidationError[], ): void { - if (!Array.isArray(fs.sitemap)) return; + if (!Array.isArray(fs.sitemap)) return; - const sitemapTitles = fs.sitemap - .flatMap((cat: any) => (cat.pages || []).map((p: any) => (p.title || "").toLowerCase())); + const sitemapTitles = fs.sitemap.flatMap((cat: any) => + (cat.pages || []).map((p: any) => (p.title || "").toLowerCase()), + ); - // Check for "Verwaltung" page (hallucinated management page) - for (const title of sitemapTitles) { - if (title.includes("verwaltung") && !title.includes("inhalt")) { - errors.push({ - code: "HALLUCINATED_MANAGEMENT_PAGE", - message: `"Verwaltung" als Seite ist vermutlich halluziniert. Verwaltung ist typischerweise eine interne Funktion, keine öffentliche Webseite.`, - field: "sitemap", - }); - } + // Check for "Verwaltung" page (hallucinated management page) + for (const title of sitemapTitles) { + if (title.includes("verwaltung") && !title.includes("inhalt")) { + errors.push({ + code: "HALLUCINATED_MANAGEMENT_PAGE", + message: `"Verwaltung" als Seite ist vermutlich halluziniert. Verwaltung ist typischerweise eine interne Funktion, keine öffentliche Webseite.`, + field: "sitemap", + }); } + } } diff --git a/packages/feedback-commander/package.json b/packages/feedback-commander/package.json deleted file mode 100644 index ad9cf87..0000000 --- a/packages/feedback-commander/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "feedback-commander", - "description": "Custom High-Fidelity Management for Directus", - "icon": "extension", - "version": "1.8.21", - "type": "module", - "keywords": [ - "directus", - "directus-extension", - "directus-extension-module" - ], - "directus:extension": { - "type": "module", - "path": "dist/index.js", - "source": "src/index.ts", - "host": "app", - "name": "feedback commander" - }, - "scripts": { - "build": "directus-extension build", - "dev": "directus-extension build -w" - }, - "devDependencies": { - "@directus/extensions-sdk": "11.0.2", - "vue": "^3.4.0" - }, - "repository": { - "type": "git", - "url": "https://git.infra.mintel.me/mmintel/at-mintel.git" - } -} diff --git a/packages/feedback-commander/src/index.ts b/packages/feedback-commander/src/index.ts deleted file mode 100644 index 9854e50..0000000 --- a/packages/feedback-commander/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineModule } from '@directus/extensions-sdk'; -import ModuleComponent from './module.vue'; - -export default defineModule({ - id: 'feedback-commander', - name: 'Feedback Commander', - icon: 'view_kanban', - routes: [ - { - path: '', - component: ModuleComponent, - }, - ], -}); diff --git a/packages/feedback-commander/src/module.vue b/packages/feedback-commander/src/module.vue deleted file mode 100644 index 1d2ee4f..0000000 --- a/packages/feedback-commander/src/module.vue +++ /dev/null @@ -1,731 +0,0 @@ - - - - - diff --git a/packages/image-processor/package.json b/packages/image-processor/package.json index 604e5f0..6f47bd1 100644 --- a/packages/image-processor/package.json +++ b/packages/image-processor/package.json @@ -19,6 +19,7 @@ }, "dependencies": { "@tensorflow/tfjs": "^4.22.0", + "@tensorflow/tfjs-backend-wasm": "^4.22.0", "@vladmandic/face-api": "^1.7.15", "canvas": "^3.2.1", "sharp": "^0.33.2" diff --git a/packages/image-processor/src/processor.ts b/packages/image-processor/src/processor.ts index 163b6aa..6a1f230 100644 --- a/packages/image-processor/src/processor.ts +++ b/packages/image-processor/src/processor.ts @@ -3,7 +3,6 @@ import { Canvas, Image, ImageData } from "canvas"; // Use the ESM no-bundle build to avoid the default Node entrypoint // which hardcodes require('@tensorflow/tfjs-node') and crashes in Docker. // This build uses pure @tensorflow/tfjs (JS-only, no native C++ bindings). -// @ts-ignore - direct path import has no type declarations import * as faceapi from "@vladmandic/face-api/dist/face-api.esm-nobundle.js"; import * as tf from "@tensorflow/tfjs"; import path from "path"; diff --git a/packages/image-processor/tsup.config.ts b/packages/image-processor/tsup.config.ts index 0f0a310..df7f6c2 100644 --- a/packages/image-processor/tsup.config.ts +++ b/packages/image-processor/tsup.config.ts @@ -1,19 +1,17 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["src/index.ts"], - format: ["esm"], - dts: true, - clean: true, - // Bundle face-api and tensorflow inline (they're pure JS). - // Keep sharp and canvas external (they have native C++ bindings). - noExternal: [ - "@vladmandic/face-api", - "@tensorflow/tfjs", - "@tensorflow/tfjs-backend-wasm" - ], - external: [ - "sharp", - "canvas" - ], + entry: ["src/index.ts"], + format: ["esm"], + dts: true, + clean: true, + // Bundle face-api and tensorflow inline (they're pure JS). + // Keep sharp and canvas external (they have native C++ bindings). + noExternal: ["@vladmandic/face-api", "@tensorflow/tfjs"], + external: [ + "sharp", + "canvas", + "@tensorflow/tfjs-backend-wasm", + "@tensorflow/tfjs-backend-wasm/dist/index.js", + ], }); diff --git a/packages/infra/package.json b/packages/infra/package.json index 5270644..aa77023 100644 --- a/packages/infra/package.json +++ b/packages/infra/package.json @@ -11,7 +11,6 @@ "templates" ], "devDependencies": { - "@directus/sdk": "^21.0.0", "@mintel/next-utils": "workspace:*", "@mintel/tsconfig": "workspace:*", "typescript": "^5.0.0" diff --git a/packages/infra/templates/website/scripts/setup-directus.ts b/packages/infra/templates/website/scripts/setup-directus.ts deleted file mode 100644 index f37e081..0000000 --- a/packages/infra/templates/website/scripts/setup-directus.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - createMintelDirectusClient, - ensureDirectusAuthenticated, -} from "@mintel/next-utils"; -import { updateSettings } from "@directus/sdk"; - -const client = createMintelDirectusClient(); - -async function setupBranding() { - const prjName = process.env.PROJECT_NAME || "Mintel Project"; - const prjColor = process.env.PROJECT_COLOR || "#82ed20"; - - console.log(`🎨 Setup Directus Branding for ${prjName}...`); - await ensureDirectusAuthenticated(client); - - const cssInjection = ` - -
-

MINTEL INFRASTRUCTURE ENGINE

-

${prjName.toUpperCase()} RELIABILITY.

-
- `; - - try { - await client.request( - updateSettings({ - project_name: prjName, - project_color: prjColor, - public_note: cssInjection, - theme_light_overrides: { - primary: prjColor, - borderRadius: "16px", - navigationBackground: "#000c24", - navigationForeground: "#ffffff", - }, - } as any), - ); - console.log("✨ Branding applied!"); - } catch (error) { - console.error("❌ Error setting up branding:", error); - } -} - -setupBranding(); diff --git a/packages/infra/templates/website/src/lib/directus.ts b/packages/infra/templates/website/src/lib/directus.ts deleted file mode 100644 index 18177f3..0000000 --- a/packages/infra/templates/website/src/lib/directus.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { - createMintelDirectusClient, - ensureDirectusAuthenticated, -} from "@mintel/next-utils"; - -const client = createMintelDirectusClient(process.env.DIRECTUS_URL); - -export async function ensureAuthenticated() { - await ensureDirectusAuthenticated(client); -} - -export default client; diff --git a/packages/journaling/src/clients/data-commons.ts b/packages/journaling/src/clients/data-commons.ts index 4945775..748c726 100644 --- a/packages/journaling/src/clients/data-commons.ts +++ b/packages/journaling/src/clients/data-commons.ts @@ -42,7 +42,7 @@ export class DataCommonsClient { /** * Search for entities (places, etc.) */ - async resolveEntity(name: string): Promise { + async resolveEntity(_name: string): Promise { // Search API or simple mapping for now. // DC doesn't have a simple "search" endpoint in v2 public API easily accessible without key sometimes? // Let's rely on LLM to provide DCIDs for now, or implement a naive search if needed. diff --git a/packages/journaling/src/clients/trends.ts b/packages/journaling/src/clients/trends.ts index 0a0da72..cbb7cd4 100644 --- a/packages/journaling/src/clients/trends.ts +++ b/packages/journaling/src/clients/trends.ts @@ -67,7 +67,7 @@ Rules: async getRelatedQueries( keyword: string, - geo: string = "DE", + _geo: string = "DE", ): Promise { // Simple mock to avoid API calls return [ diff --git a/packages/next-feedback/package.json b/packages/next-feedback/package.json index 3d07bf8..e4af3ba 100644 --- a/packages/next-feedback/package.json +++ b/packages/next-feedback/package.json @@ -26,7 +26,6 @@ "lint": "eslint src/" }, "dependencies": { - "@directus/sdk": "^21.0.0", "@medv/finder": "^4.0.2", "clsx": "^2.1.1", "framer-motion": "^11.5.4", diff --git a/packages/next-feedback/src/handlers/index.ts b/packages/next-feedback/src/handlers/index.ts index 19d9850..d6c1a91 100644 --- a/packages/next-feedback/src/handlers/index.ts +++ b/packages/next-feedback/src/handlers/index.ts @@ -1,105 +1,24 @@ import { NextRequest, NextResponse } from "next/server"; -import { - createDirectus, - rest, - staticToken, - createItem, - readItems, -} from "@directus/sdk"; export interface CMSConfig { url: string; token: string; } -export function createCMSClient(config: CMSConfig) { - return createDirectus(config.url) - .with(staticToken(config.token)) - .with(rest()); -} - export async function handleFeedbackRequest( req: NextRequest, - config: CMSConfig, + _config: CMSConfig, ) { - const client = createCMSClient(config); - + // Feedback functionality has been disabled as Directus was removed if (req.method === "GET") { - try { - const items = await client.request( - readItems("visual_feedback", { - fields: ["*", { comments: ["*"] }], - sort: ["-date_created"], - }), - ); - return NextResponse.json(items); - } catch (error: any) { - return NextResponse.json({ error: error.message }, { status: 500 }); - } + return NextResponse.json([]); } if (req.method === "POST") { - try { - const body = await req.json(); - const { action, screenshot_base64, ...data } = body; - - if (action === "reply") { - const reply = await client.request( - createItem("visual_feedback_comments", { - feedback_id: data.feedbackId, - user_name: data.userName, - text: data.text, - }), - ); - return NextResponse.json(reply); - } - - let screenshotId = null; - - if (screenshot_base64) { - try { - const base64Data = screenshot_base64.split(";base64,").pop(); - const buffer = Buffer.from(base64Data, "base64"); - const formData = new FormData(); - const blob = new Blob([buffer], { type: "image/png" }); - formData.append("file", blob, `feedback-${Date.now()}.png`); - - const fileRes = await fetch(`${config.url}/files`, { - method: "POST", - headers: { Authorization: `Bearer ${config.token}` }, - body: formData, - }); - - if (fileRes.ok) { - const fileData = await fileRes.json(); - screenshotId = fileData.data.id; - } - } catch (e) { - console.error("Failed to upload screenshot:", e); - } - } - - const feedback = await client.request( - createItem("visual_feedback", { - project: data.project || req.headers.get("host") || "unknown", - url: data.url, - selector: data.selector, - x: data.x, - y: data.y, - type: data.type, - text: data.text, - user_name: data.userName, - user_identity: data.userIdentity, - status: "open", - screenshot: screenshotId, - company: data.companyId, - }), - ); - - return NextResponse.json(feedback); - } catch (error: any) { - return NextResponse.json({ error: error.message }, { status: 500 }); - } + return NextResponse.json( + { error: "Feedback system disabled" }, + { status: 501 }, + ); } return NextResponse.json({ error: "Method not allowed" }, { status: 405 }); diff --git a/packages/next-utils/package.json b/packages/next-utils/package.json index 588e93d..4e411bf 100644 --- a/packages/next-utils/package.json +++ b/packages/next-utils/package.json @@ -15,7 +15,6 @@ "test": "vitest run" }, "dependencies": { - "@directus/sdk": "^21.0.0", "next": "16.1.6", "next-intl": "^4.8.2", "zod": "^3.0.0" diff --git a/packages/next-utils/src/directus.ts b/packages/next-utils/src/directus.ts deleted file mode 100644 index da90169..0000000 --- a/packages/next-utils/src/directus.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { - createDirectus, - rest, - authentication, - DirectusClient, - RestClient, - AuthenticationClient, -} from "@directus/sdk"; - -export type MintelDirectusClient = - DirectusClient & RestClient & AuthenticationClient; - -/** - * Creates a Directus client configured with Mintel standards. - * Automatically handles internal vs. external URLs based on environment. - */ -export function createMintelDirectusClient( - url?: string, -): MintelDirectusClient { - const isServer = typeof window === "undefined"; - - // 1. If an explicit URL is provided, use it. - if (url) { - return createDirectus(url).with(rest()).with(authentication()); - } - - // 2. On server: Prioritize INTERNAL_DIRECTUS_URL, fallback to DIRECTUS_URL - if (isServer) { - const directusUrl = - process.env.INTERNAL_DIRECTUS_URL || - process.env.DIRECTUS_URL || - "http://localhost:8055"; - return createDirectus(directusUrl) - .with(rest()) - .with(authentication()); - } - - // 3. In browser: Use a proxy path if we are on a different origin, - // or use the current origin if no DIRECTUS_URL is set. - const proxyPath = "/api/directus"; // Standard Mintel proxy path - const browserUrl = - typeof window !== "undefined" - ? `${window.location.origin}${proxyPath}` - : proxyPath; - - return createDirectus(browserUrl).with(rest()).with(authentication()); -} - -/** - * Ensures the client is authenticated using either a static token or admin credentials - */ -export async function ensureDirectusAuthenticated( - client: MintelDirectusClient, -) { - const token = process.env.DIRECTUS_API_TOKEN || process.env.DIRECTUS_TOKEN; - const email = process.env.DIRECTUS_ADMIN_EMAIL; - const password = process.env.DIRECTUS_ADMIN_PASSWORD; - - if (token) { - client.setToken(token); - return; - } - - if (email && password) { - try { - await client.login({ email, password }); - } catch (e) { - console.error("Failed to authenticate with Directus:", e); - throw e; - } - } -} diff --git a/packages/next-utils/src/index.ts b/packages/next-utils/src/index.ts index 744b5eb..cf7bf7e 100644 --- a/packages/next-utils/src/index.ts +++ b/packages/next-utils/src/index.ts @@ -34,4 +34,3 @@ export * from "./lang"; export * from "./i18n"; export * from "./env"; -export * from "./directus"; diff --git a/packages/pdf-library/package.json b/packages/pdf-library/package.json index 537d3bd..8b18357 100644 --- a/packages/pdf-library/package.json +++ b/packages/pdf-library/package.json @@ -22,7 +22,6 @@ "dev": "node build.mjs --watch" }, "devDependencies": { - "@directus/extensions-sdk": "11.0.2", "esbuild": "^0.25.0", "typescript": "^5.6.3" }, diff --git a/packages/people-manager/package.json b/packages/people-manager/package.json deleted file mode 100644 index 775c16d..0000000 --- a/packages/people-manager/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "people-manager", - "description": "Custom High-Fidelity Management for Directus", - "icon": "extension", - "version": "1.8.21", - "type": "module", - "keywords": [ - "directus", - "directus-extension", - "directus-extension-module" - ], - "directus:extension": { - "type": "module", - "path": "dist/index.js", - "source": "src/index.ts", - "host": "app", - "name": "people manager" - }, - "scripts": { - "build": "directus-extension build", - "dev": "directus-extension build -w" - }, - "dependencies": { - "@mintel/directus-extension-toolkit": "workspace:*" - }, - "devDependencies": { - "@directus/extensions-sdk": "11.0.2", - "vue": "^3.4.0" - }, - "repository": { - "type": "git", - "url": "https://git.infra.mintel.me/mmintel/at-mintel.git" - } -} diff --git a/packages/people-manager/src/index.ts b/packages/people-manager/src/index.ts deleted file mode 100644 index 3fdb9dd..0000000 --- a/packages/people-manager/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineModule } from '@directus/extensions-sdk'; -import ModuleComponent from './module.vue'; - -export default defineModule({ - id: 'people-manager', - name: 'People Manager', - icon: 'person', - routes: [ - { - path: '', - component: ModuleComponent, - }, - ], -}); diff --git a/packages/people-manager/src/module.vue b/packages/people-manager/src/module.vue deleted file mode 100644 index 27a68dc..0000000 --- a/packages/people-manager/src/module.vue +++ /dev/null @@ -1,317 +0,0 @@ - - - - - diff --git a/packages/unified-dashboard/package.json b/packages/unified-dashboard/package.json deleted file mode 100644 index 51b0f38..0000000 --- a/packages/unified-dashboard/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "unified-dashboard", - "description": "Custom High-Fidelity Management for Directus", - "icon": "extension", - "version": "1.8.21", - "type": "module", - "keywords": [ - "directus", - "directus-extension", - "directus-extension-module" - ], - "directus:extension": { - "type": "module", - "path": "dist/index.js", - "source": "src/index.ts", - "host": "app", - "name": "unified dashboard" - }, - "scripts": { - "build": "directus-extension build", - "dev": "directus-extension build -w" - }, - "devDependencies": { - "@directus/extensions-sdk": "11.0.2", - "vue": "^3.4.0" - }, - "repository": { - "type": "git", - "url": "https://git.infra.mintel.me/mmintel/at-mintel.git" - } -} diff --git a/packages/unified-dashboard/src/index.ts b/packages/unified-dashboard/src/index.ts deleted file mode 100644 index a0d38da..0000000 --- a/packages/unified-dashboard/src/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineModule } from '@directus/extensions-sdk'; -import ModuleComponent from './module.vue'; - -export default defineModule({ - id: 'unified-dashboard', - name: 'Overview', - icon: 'dashboard', - routes: [ - { - path: '', - component: ModuleComponent, - }, - ], -}); diff --git a/packages/unified-dashboard/src/module.vue b/packages/unified-dashboard/src/module.vue deleted file mode 100644 index da94379..0000000 --- a/packages/unified-dashboard/src/module.vue +++ /dev/null @@ -1,146 +0,0 @@ - - - - - diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 936f976..e5e1ec4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,6 +143,9 @@ importers: '@sentry/nextjs': specifier: 10.38.0 version: 10.38.0(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(next@16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react@19.2.4)(webpack@5.105.0) + '@tensorflow/tfjs-backend-wasm': + specifier: ^4.22.0 + version: 4.22.0(@tensorflow/tfjs-core@4.22.0) next: specifier: 16.1.6 version: 16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) @@ -178,47 +181,6 @@ importers: specifier: ^5.0.0 version: 5.9.3 - packages/acquisition: - dependencies: - jquery: - specifier: ^3.7.1 - version: 3.7.1 - react: - specifier: ^19.2.4 - version: 19.2.4 - react-dom: - specifier: ^19.2.4 - version: 19.2.4(react@19.2.4) - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - '@mintel/mail': - specifier: workspace:* - version: link:../mail - '@mintel/pdf': - specifier: workspace:* - version: link:../pdf-library - esbuild: - specifier: ^0.25.0 - version: 0.25.12 - typescript: - specifier: ^5.6.3 - version: 5.9.3 - - packages/acquisition-manager: - dependencies: - '@mintel/directus-extension-toolkit': - specifier: workspace:* - version: link:../directus-extension-toolkit - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - vue: - specifier: ^3.4.0 - version: 3.5.28(typescript@5.9.3) - packages/cli: dependencies: chalk: @@ -275,21 +237,6 @@ importers: specifier: ^5.6.3 version: 5.9.3 - packages/cms-infra: {} - - packages/company-manager: - dependencies: - '@mintel/directus-extension-toolkit': - specifier: workspace:* - version: link:../directus-extension-toolkit - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - vue: - specifier: ^3.4.0 - version: 3.5.28(typescript@5.9.3) - packages/concept-engine: dependencies: '@crawlee/cheerio': @@ -331,7 +278,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.0.5 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) packages/content-engine: dependencies: @@ -367,37 +314,6 @@ importers: specifier: ^5.0.0 version: 5.9.3 - packages/customer-manager: - dependencies: - '@mintel/directus-extension-toolkit': - specifier: workspace:* - version: link:../directus-extension-toolkit - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - vue: - specifier: ^3.4.0 - version: 3.5.28(typescript@5.9.3) - - packages/directus-extension-toolkit: - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - '@vitejs/plugin-vue': - specifier: ^6.0.4 - version: 6.0.4(vite@5.4.21(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0))(vue@3.5.28(typescript@5.9.3)) - typescript: - specifier: ^5.0.0 - version: 5.9.3 - vite: - specifier: ^5.0.0 - version: 5.4.21(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) - vue: - specifier: ^3.4.0 - version: 3.5.28(typescript@5.9.3) - packages/eslint-config: dependencies: '@eslint/eslintrc': @@ -480,15 +396,6 @@ importers: specifier: ^5.0.0 version: 5.9.3 - packages/feedback-commander: - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - vue: - specifier: ^3.4.0 - version: 3.5.28(typescript@5.9.3) - packages/gatekeeper: dependencies: '@mintel/next-utils': @@ -561,6 +468,9 @@ importers: '@tensorflow/tfjs': specifier: ^4.22.0 version: 4.22.0(seedrandom@3.0.5) + '@tensorflow/tfjs-backend-wasm': + specifier: ^4.22.0 + version: 4.22.0(@tensorflow/tfjs-core@4.22.0) '@vladmandic/face-api': specifier: ^1.7.15 version: 1.7.15 @@ -589,9 +499,6 @@ importers: packages/infra: devDependencies: - '@directus/sdk': - specifier: ^21.0.0 - version: 21.1.0 '@mintel/next-utils': specifier: workspace:* version: link:../next-utils @@ -665,7 +572,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.0.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) packages/meme-generator: dependencies: @@ -700,9 +607,6 @@ importers: packages/next-feedback: dependencies: - '@directus/sdk': - specifier: ^21.0.0 - version: 21.1.0 '@medv/finder': specifier: ^4.0.2 version: 4.0.2 @@ -798,9 +702,6 @@ importers: packages/next-utils: dependencies: - '@directus/sdk': - specifier: ^21.0.0 - version: 21.1.0 next: specifier: 16.1.6 version: 16.1.6(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3) @@ -846,7 +747,7 @@ importers: version: 5.9.3 vitest: specifier: ^2.0.0 - version: 2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) + version: 2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) packages/page-audit: dependencies: @@ -909,9 +810,6 @@ importers: specifier: ^19.2.4 version: 19.2.4(react@19.2.4) devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) esbuild: specifier: ^0.25.0 version: 0.25.12 @@ -919,19 +817,6 @@ importers: specifier: ^5.6.3 version: 5.9.3 - packages/people-manager: - dependencies: - '@mintel/directus-extension-toolkit': - specifier: workspace:* - version: link:../directus-extension-toolkit - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - vue: - specifier: ^3.4.0 - version: 3.5.28(typescript@5.9.3) - packages/thumbnail-generator: dependencies: replicate: @@ -956,15 +841,6 @@ importers: packages/tsconfig: {} - packages/unified-dashboard: - devDependencies: - '@directus/extensions-sdk': - specifier: 11.0.2 - version: 11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3) - vue: - specifier: ^3.4.0 - version: 3.5.28(typescript@5.9.3) - packages: '@acemir/cssom@0.9.31': @@ -1388,72 +1264,6 @@ packages: resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} engines: {node: '>=20.19.0'} - '@directus/composables@10.1.12': - resolution: {integrity: sha512-yoFuzaPLEYTq1NMkAtIrWL0c7sBEuMWnSzVyLw9iuhCnF5w565L0sroCs+7fw8E+IXKBVPXKBs51drKhKdN9Ng==} - peerDependencies: - vue: ^3.4 - - '@directus/constants@11.0.3': - resolution: {integrity: sha512-+Pd7V6VZ/HzPwWDfVzfOMNzLW2dYMeMUpQvOOfvyvDyxnTsd7/31Gqs1DSL13DdBdvqgh+3Ho8Ai/Zn1GvQYcg==} - - '@directus/extensions-sdk@11.0.2': - resolution: {integrity: sha512-tEPSKEBakO4/APd1wFa1yrY9OEGG1VAnsZg/Bqi//A4sLgPBLzjBe/8559Ez5cG5nDxNVXismz34DFq7eDVjgg==} - engines: {node: '>=12.20.0'} - hasBin: true - - '@directus/extensions@1.0.2': - resolution: {integrity: sha512-deTLqktWjK7eR+7QRdejhtBIqKwLHZflwiFzrD3RquA9olzA6WKzt8wY7vr421IyLV1Lv7DxTI83+2f5UutzFw==} - peerDependencies: - knex: '3' - pino: '8' - vue: ^3.4 - vue-router: '4' - peerDependenciesMeta: - knex: - optional: true - pino: - optional: true - vue: - optional: true - vue-router: - optional: true - - '@directus/schema@11.0.1': - resolution: {integrity: sha512-I8YaZcFdzY1Livv3fW2L0GTBan+MGIYancj9GM/AoZpfeI5PjCecqASna/ijD/WVwDlUUvx6b7aJcQ1OLXBDug==} - - '@directus/sdk@21.1.0': - resolution: {integrity: sha512-Ig8zZAQDbc7QMIM54N+x71C04lni9MN9yalNAezjDjFdNknTJzupDY7V5cb+kOJL8GsqDE9Bg8xq8xCmkDVs5A==} - engines: {node: '>=22'} - - '@directus/system-data@1.0.2': - resolution: {integrity: sha512-PweDAwTz4zImEGJnhoaX8apOCvcAfE0aGQrCSk+3cf1sLso0ShNlcDvUymtVfrqOXy0qT9sLa833bpJVaXF5ng==} - - '@directus/themes@0.3.6': - resolution: {integrity: sha512-69LkviIMLG1/ne0p4lawwvE8KcEe/Xlg19kXUr5tHqkdr27Z4FpSd3fk17ESqhW402JkcPe8OSjxZvFmi1IMRA==} - peerDependencies: - '@unhead/vue': '1' - pinia: '2' - vue: ^3.4 - - '@directus/types@11.0.8': - resolution: {integrity: sha512-JJrfuzzUlr/gE6o+Mn/Wapg1xikRBiievDJi7Q6RJusv+97AyT6yAkgJpEhuYUtAQcW0+qwbw/su+TbL/x7jvA==} - peerDependencies: - knex: '3' - vue: ^3.4 - peerDependenciesMeta: - knex: - optional: true - vue: - optional: true - - '@directus/utils@11.0.7': - resolution: {integrity: sha512-NJIO8mPnNMLhYlZ6VrmgY5iTqS0VZnRFPohB/rQMRIIQeAf5P3QKtEGYwrxXoLFUyWgZsX84RMCW/YP5H3kpYA==} - peerDependencies: - vue: ^3.4 - peerDependenciesMeta: - vue: - optional: true - '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -1481,18 +1291,6 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.17.19': - resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm64@0.18.20': - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} @@ -1511,18 +1309,6 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm@0.17.19': - resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-arm@0.18.20': - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} @@ -1541,18 +1327,6 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-x64@0.17.19': - resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.18.20': - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} @@ -1571,18 +1345,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.17.19': - resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.18.20': - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} @@ -1601,18 +1363,6 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.17.19': - resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/darwin-x64@0.18.20': - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} @@ -1631,18 +1381,6 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.17.19': - resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-arm64@0.18.20': - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} @@ -1661,18 +1399,6 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.17.19': - resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.18.20': - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} @@ -1691,18 +1417,6 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.17.19': - resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm64@0.18.20': - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} @@ -1721,18 +1435,6 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.17.19': - resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-arm@0.18.20': - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} @@ -1751,18 +1453,6 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.17.19': - resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.18.20': - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} @@ -1781,18 +1471,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.17.19': - resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.18.20': - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} @@ -1811,18 +1489,6 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.17.19': - resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.18.20': - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} @@ -1841,18 +1507,6 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.17.19': - resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.18.20': - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} @@ -1871,18 +1525,6 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.17.19': - resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.18.20': - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} @@ -1901,18 +1543,6 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.17.19': - resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.18.20': - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} @@ -1931,18 +1561,6 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.17.19': - resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.18.20': - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} @@ -1973,18 +1591,6 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.17.19': - resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.18.20': - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} @@ -2015,18 +1621,6 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.17.19': - resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.18.20': - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} @@ -2057,18 +1651,6 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.17.19': - resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.18.20': - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} @@ -2087,18 +1669,6 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.17.19': - resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.18.20': - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} @@ -2117,18 +1687,6 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.17.19': - resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.18.20': - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} @@ -2147,18 +1705,6 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.17.19': - resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.18.20': - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} @@ -2254,12 +1800,6 @@ packages: '@formatjs/intl-localematcher@0.8.1': resolution: {integrity: sha512-xwEuwQFdtSq1UKtQnyTZWC+eHdv7Uygoa+H2k/9uzBVQjDyp9r20LNDNKedWXll7FssT3GRHvqsdJGYSUWqYFA==} - '@hapi/hoek@9.3.0': - resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} - - '@hapi/topo@5.1.0': - resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -3101,15 +2641,6 @@ packages: '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} - '@rollup/plugin-commonjs@25.0.7': - resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/plugin-commonjs@28.0.1': resolution: {integrity: sha512-+tNWdlWKbpB3WgBN7ijjYkq9X5uhjmcvyjEght4NmH5fAU++zfQzAJ6wumLS+dNcvwEZhKx2Z+skY8m7v0wGSA==} engines: {node: '>=16.0.0 || 14 >= 14.17'} @@ -3119,55 +2650,6 @@ packages: rollup: optional: true - '@rollup/plugin-json@6.1.0': - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-node-resolve@15.2.3': - resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-replace@5.0.5': - resolution: {integrity: sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-terser@0.4.4': - resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-virtual@3.0.2': - resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/pluginutils@4.2.1': - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - '@rollup/pluginutils@5.3.0': resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} @@ -3454,18 +2936,6 @@ packages: peerDependencies: webpack: '>=4.40.0' - '@sideway/address@4.1.5': - resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} - - '@sideway/formula@3.0.1': - resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} - - '@sideway/pinpoint@2.0.0': - resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} - - '@sinclair/typebox@0.32.15': - resolution: {integrity: sha512-5Lrwo7VOiWEBJBhHmqNmf3TPB9ll8gcEshvYJyAIJyCZ2PF48MFOtiDHJNj8+FsNcqImaQYmxVkKBCBlyAa/wg==} - '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} @@ -3573,6 +3043,11 @@ packages: peerDependencies: '@tensorflow/tfjs-core': 4.22.0 + '@tensorflow/tfjs-backend-wasm@4.22.0': + resolution: {integrity: sha512-/IYhReRIp4jg/wYW0OwbbJZG8ON87mbz0PgkiP3CdcACRSvUN0h8rvC0O3YcDtkTQtFWF/tcXq/KlVDyV49wmA==} + peerDependencies: + '@tensorflow/tfjs-core': 4.22.0 + '@tensorflow/tfjs-backend-webgl@4.22.0': resolution: {integrity: sha512-H535XtZWnWgNwSzv538czjVlbJebDl5QTMOth4RXr2p/kJ1qSIXE0vZvEtO+5EC9b00SvhplECny2yDewQb/Yg==} engines: {yarn: '>= 1.3.2'} @@ -3633,10 +3108,6 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@trysound/sax@0.2.0': - resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} - engines: {node: '>=10.13.0'} - '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -3655,9 +3126,6 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - '@types/body-parser@1.19.6': - resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} - '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -3667,16 +3135,15 @@ packages: '@types/content-type@1.1.9': resolution: {integrity: sha512-Hq9IMnfekuOCsEmYl4QX2HBrT+XsfXiupfrLLY8Dcf3Puf4BkBOxSbWYTITSOQAhJoYPBez+b4MJRpIYL65z8A==} - '@types/cssnano@5.1.3': - resolution: {integrity: sha512-BahAZSSvuFXyhgJiwQgsfsNlStE9K/ULGL+YEzK4mmL2Vf02Pjl2yZs+KmbkAg3MxkC9WwMuFwuwnwvrg7CqvQ==} - deprecated: This is a stub types definition. cssnano provides its own type definitions, so you do not need this installed. - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/emscripten@0.0.34': + resolution: {integrity: sha512-QSb9ojDincskc+uKMI0KXp8e1NALFINCrMlp8VGKGcTSxeEyRTTKyjWw75NYrCZHUsVEEEpr1tYHpbtaC++/sQ==} + '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -3686,24 +3153,12 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/express-serve-static-core@4.19.8': - resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} - - '@types/express@4.17.21': - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - '@types/geojson@7946.0.14': - resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==} - '@types/http-cache-semantics@4.2.0': resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} - '@types/http-errors@2.0.5': - resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} - '@types/jsdom@21.1.7': resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} @@ -3746,9 +3201,6 @@ packages: '@types/offscreencanvas@2019.7.3': resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} - '@types/parse-json@4.0.2': - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/pg-pool@2.0.7': resolution: {integrity: sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==} @@ -3761,12 +3213,6 @@ packages: '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/qs@6.14.0': - resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} - - '@types/range-parser@1.2.7': - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: @@ -3778,21 +3224,12 @@ packages: '@types/react@19.2.13': resolution: {integrity: sha512-KkiJeU6VbYbUOp5ITMIc7kBfqlYkKA5KhEHVrGMmUUMt7NeaZg65ojdPk+FtNrBAOXNVM5QM72jnADjM+XVRAQ==} - '@types/resolve@1.20.2': - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/sax@1.2.7': resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} '@types/seedrandom@2.4.34': resolution: {integrity: sha512-ytDiArvrn/3Xk6/vtylys5tlY6eo7Ane0hvcx++TKo6RxQXuVfW0AF/oeWqAj9dN29SyhtawuXstgmPlwNcv/A==} - '@types/send@1.2.1': - resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} - - '@types/serve-static@2.2.0': - resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} - '@types/tedious@4.0.14': resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} @@ -3864,20 +3301,6 @@ packages: resolution: {integrity: sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@unhead/dom@1.11.20': - resolution: {integrity: sha512-jgfGYdOH+xHJF/j8gudjsYu3oIjFyXhCWcgKaw3vQnT616gSqyqnGQGOItL+BQtQZACKNISwIfx5PuOtztMKLA==} - - '@unhead/schema@1.11.20': - resolution: {integrity: sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA==} - - '@unhead/shared@1.11.20': - resolution: {integrity: sha512-1MOrBkGgkUXS+sOKz/DBh4U20DNoITlJwpmvSInxEUNhghSNb56S0RnaHRq0iHkhrO/cDgz2zvfdlRpoPLGI3w==} - - '@unhead/vue@1.11.20': - resolution: {integrity: sha512-sqQaLbwqY9TvLEGeq8Fd7+F2TIuV3nZ5ihVISHjWpAM3y7DwNWRU7NmT9+yYT+2/jw1Vjwdkv5/HvDnvCLrgmg==} - peerDependencies: - vue: '>=2.7 || >=3' - '@unrs/resolver-binding-android-arm-eabi@1.11.1': resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} cpu: [arm] @@ -3979,20 +3402,6 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - '@vitejs/plugin-vue@4.6.2': - resolution: {integrity: sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.0.0 || ^5.0.0 - vue: ^3.2.25 - - '@vitejs/plugin-vue@6.0.4': - resolution: {integrity: sha512-uM5iXipgYIn13UUQCZNdWkYk+sysBeA97d5mHsAoAt1u/wpN3+zxOmsVJWosuzX+IMGRzeYUNytztrYznboIkQ==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - vue: ^3.2.25 - '@vitest/expect@2.1.9': resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} @@ -4093,67 +3502,6 @@ packages: resolution: {integrity: sha512-WDMmK3CfNLo8jylWqMoQgf4nIst3M0fzx1dnac96wv/dvMTN4DxC/Pq1DGtduDk1lktCamQ3MIDXFnvrdHTXDw==} engines: {node: '>=14.0.0'} - '@vue/compiler-core@3.4.21': - resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==} - - '@vue/compiler-core@3.5.28': - resolution: {integrity: sha512-kviccYxTgoE8n6OCw96BNdYlBg2GOWfBuOW4Vqwrt7mSKWKwFVvI8egdTltqRgITGPsTFYtKYfxIG8ptX2PJHQ==} - - '@vue/compiler-dom@3.4.21': - resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==} - - '@vue/compiler-dom@3.5.28': - resolution: {integrity: sha512-/1ZepxAb159jKR1btkefDP+J2xuWL5V3WtleRmxaT+K2Aqiek/Ab/+Ebrw2pPj0sdHO8ViAyyJWfhXXOP/+LQA==} - - '@vue/compiler-sfc@3.4.21': - resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==} - - '@vue/compiler-sfc@3.5.28': - resolution: {integrity: sha512-6TnKMiNkd6u6VeVDhZn/07KhEZuBSn43Wd2No5zaP5s3xm8IqFTHBj84HJah4UepSUJTro5SoqqlOY22FKY96g==} - - '@vue/compiler-ssr@3.4.21': - resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==} - - '@vue/compiler-ssr@3.5.28': - resolution: {integrity: sha512-JCq//9w1qmC6UGLWJX7RXzrGpKkroubey/ZFqTpvEIDJEKGgntuDMqkuWiZvzTzTA5h2qZvFBFHY7fAAa9475g==} - - '@vue/devtools-api@6.6.4': - resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} - - '@vue/reactivity@3.4.21': - resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==} - - '@vue/reactivity@3.5.28': - resolution: {integrity: sha512-gr5hEsxvn+RNyu9/9o1WtdYdwDjg5FgjUSBEkZWqgTKlo/fvwZ2+8W6AfKsc9YN2k/+iHYdS9vZYAhpi10kNaw==} - - '@vue/runtime-core@3.4.21': - resolution: {integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==} - - '@vue/runtime-core@3.5.28': - resolution: {integrity: sha512-POVHTdbgnrBBIpnbYU4y7pOMNlPn2QVxVzkvEA2pEgvzbelQq4ZOUxbp2oiyo+BOtiYlm8Q44wShHJoBvDPAjQ==} - - '@vue/runtime-dom@3.4.21': - resolution: {integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==} - - '@vue/runtime-dom@3.5.28': - resolution: {integrity: sha512-4SXxSF8SXYMuhAIkT+eBRqOkWEfPu6nhccrzrkioA6l0boiq7sp18HCOov9qWJA5HML61kW8p/cB4MmBiG9dSA==} - - '@vue/server-renderer@3.4.21': - resolution: {integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==} - peerDependencies: - vue: 3.4.21 - - '@vue/server-renderer@3.5.28': - resolution: {integrity: sha512-pf+5ECKGj8fX95bNincbzJ6yp6nyzuLDhYZCeFxUNp8EBrQpPpQaLX3nNCp49+UbgbPun3CeVE+5CXVV1Xydfg==} - peerDependencies: - vue: 3.5.28 - - '@vue/shared@3.4.21': - resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} - - '@vue/shared@3.5.28': - resolution: {integrity: sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==} - '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -4427,9 +3775,6 @@ packages: axios@1.13.5: resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} - axios@1.6.7: - resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} - axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -4466,9 +3811,6 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - bl@5.1.0: - resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -4502,10 +3844,6 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - bundle-require@5.1.0: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4552,9 +3890,6 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - caniuse-api@3.0.0: - resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001769: resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} @@ -4578,10 +3913,6 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - chalk@5.6.2: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} @@ -4705,12 +4036,6 @@ packages: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} - colord@2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - - colorette@2.0.19: - resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} - colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -4718,10 +4043,6 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - commander@11.1.0: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} @@ -4745,10 +4066,6 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -4804,10 +4121,6 @@ packages: cosmiconfig: '>=9' typescript: '>=5' - cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -4840,25 +4153,12 @@ packages: crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} - css-declaration-sorter@6.4.1: - resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} - engines: {node: ^10 || ^12 || >=14} - peerDependencies: - postcss: ^8.0.9 - css-line-break@2.1.0: resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} - css-select@4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} - css-tree@1.1.3: - resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} - engines: {node: '>=8.0.0'} - css-tree@3.1.0: resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -4875,28 +4175,6 @@ packages: engines: {node: '>=4'} hasBin: true - cssnano-preset-default@5.2.14: - resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - cssnano-utils@3.1.0: - resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - cssnano@5.1.15: - resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - csso@4.2.0: - resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} - engines: {node: '>=8.0.0'} - cssom@0.5.0: resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} @@ -4941,9 +4219,6 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - date-fns@3.6.0: - resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} - dateformat@4.6.3: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} @@ -4955,15 +4230,6 @@ packages: supports-color: optional: true - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -4973,17 +4239,9 @@ packages: supports-color: optional: true - decamelize@6.0.0: - resolution: {integrity: sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - decompress-response@10.0.0: resolution: {integrity: sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q==} engines: {node: '>=20'} @@ -5060,26 +4318,16 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-serializer@1.4.1: - resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - domhandler@4.3.1: - resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} - engines: {node: '>= 4'} - domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - domutils@2.8.0: - resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} @@ -5142,9 +4390,6 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} - entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -5209,16 +4454,6 @@ packages: es-toolkit@1.44.0: resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} - esbuild@0.17.19: - resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} - engines: {node: '>=12'} - hasBin: true - - esbuild@0.18.20: - resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} - engines: {node: '>=12'} - hasBin: true - esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -5350,10 +4585,6 @@ packages: jiti: optional: true - esm@3.2.25: - resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} - engines: {node: '>=6'} - espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5396,9 +4627,6 @@ packages: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - eventemitter3@5.0.4: resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} @@ -5406,10 +4634,6 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - execa@7.2.0: - resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -5512,10 +4736,6 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - find-my-way@8.2.2: resolution: {integrity: sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==} engines: {node: '>=14'} @@ -5551,11 +4771,6 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flat@6.0.1: - resolution: {integrity: sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==} - engines: {node: '>=18'} - hasBin: true - flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} @@ -5624,14 +4839,6 @@ packages: fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - - fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - fs-extra@11.3.3: resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} engines: {node: '>=14.14'} @@ -5644,9 +4851,6 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -5690,18 +4894,10 @@ packages: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} - get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - get-stream@9.0.1: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} @@ -5713,9 +4909,6 @@ packages: get-tsconfig@4.13.6: resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} - getopts@2.3.0: - resolution: {integrity: sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==} - git-raw-commits@4.0.0: resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} engines: {node: '>=16'} @@ -5740,11 +4933,6 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} @@ -5835,9 +5023,6 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hookable@5.5.3: - resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} - hsl-to-hex@1.0.0: resolution: {integrity: sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==} @@ -5895,10 +5080,6 @@ packages: resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} hasBin: true - human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -5922,12 +5103,6 @@ packages: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} - icss-utils@5.1.0: - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - icu-minify@4.8.2: resolution: {integrity: sha512-LHBQV+skKkjZSPd590pZ7ZAHftUgda3eFjeuNwA8/15L8T8loCNBktKQyTlkodAU86KovFXeg/9WntlAo5wA5A==} @@ -5976,10 +5151,6 @@ packages: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} engines: {node: '>=12'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -6036,10 +5207,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - interpret@2.2.0: - resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} - engines: {node: '>= 0.10'} - intl-messageformat@11.1.2: resolution: {integrity: sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg==} @@ -6080,10 +5247,6 @@ packages: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - is-bun-module@2.0.0: resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} @@ -6140,17 +5303,10 @@ packages: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} - is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} - is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} - is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} @@ -6189,10 +5345,6 @@ packages: resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} engines: {node: '>= 0.4'} - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-stream@4.0.1: resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} engines: {node: '>=18'} @@ -6217,10 +5369,6 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} - is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - is-unicode-supported@2.1.0: resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} engines: {node: '>=18'} @@ -6272,9 +5420,6 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true - joi@17.12.2: - resolution: {integrity: sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==} - joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -6292,10 +5437,6 @@ packages: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true @@ -6350,9 +5491,6 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-parser@3.3.1: - resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} - jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -6373,34 +5511,6 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - knex@3.1.0: - resolution: {integrity: sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==} - engines: {node: '>=16'} - hasBin: true - peerDependencies: - better-sqlite3: '*' - mysql: '*' - mysql2: '*' - pg: '*' - pg-native: '*' - sqlite3: '*' - tedious: '*' - peerDependenciesMeta: - better-sqlite3: - optional: true - mysql: - optional: true - mysql2: - optional: true - pg: - optional: true - pg-native: - optional: true - sqlite3: - optional: true - tedious: - optional: true - language-subtag-registry@0.3.23: resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} @@ -6488,10 +5598,6 @@ packages: resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} engines: {node: '>= 12.0.0'} - lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} @@ -6536,9 +5642,6 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash-es@4.17.21: - resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} - lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} @@ -6549,9 +5652,6 @@ packages: lodash.kebabcase@4.1.1: resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -6564,9 +5664,6 @@ packages: lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - lodash.upperfirst@4.3.1: resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} @@ -6577,10 +5674,6 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-symbols@5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} - log-update@6.1.0: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} @@ -6647,9 +5740,6 @@ packages: peerDependencies: react: ^18.0 || ^19.0 - mdn-data@2.0.14: - resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} - mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} @@ -6675,10 +5765,6 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - micromustache@8.0.3: - resolution: {integrity: sha512-SXjrEPuYNtWq0reR9LR2nHdzdQx/3re9HPcDGjm00L7hi2RsH5KMRBhYEBvPdyQC51RW/2TznjwX/sQLPPyHNw==} - engines: {node: '>=8'} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -6691,10 +5777,6 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -6714,10 +5796,6 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -6767,9 +5845,6 @@ packages: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -6792,11 +5867,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@5.0.6: - resolution: {integrity: sha512-rRq0eMHoGZxlvaFOUdK1Ev83Bd1IgzzR+WJ3IbDJ7QOSdAxYjlurSPqFs9s4lJg29RT6nPwizFtJhQS6V5xgiA==} - engines: {node: ^18 || >=20} - hasBin: true - napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} @@ -6889,18 +5959,10 @@ packages: normalize-svg-path@1.1.0: resolution: {integrity: sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==} - normalize-url@6.1.0: - resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} - engines: {node: '>=10'} - normalize-url@8.1.1: resolution: {integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==} engines: {node: '>=14.16'} - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -6957,10 +6019,6 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} @@ -6985,10 +6043,6 @@ packages: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} - ora@6.3.1: - resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -7016,10 +6070,6 @@ packages: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} - p-finally@1.0.0: - resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} - engines: {node: '>=4'} - p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -7040,14 +6090,6 @@ packages: resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} engines: {node: '>=6'} - p-queue@6.6.2: - resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} - engines: {node: '>=8'} - - p-timeout@3.2.0: - resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} - engines: {node: '>=8'} - p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -7058,9 +6100,6 @@ packages: package-manager-detector@0.2.11: resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} - packrup@0.1.2: - resolution: {integrity: sha512-ZcKU7zrr5GlonoS9cxxrb5HVswGnyj6jQvwFBa6p5VFw7G71VAHcUKL5wyZSU/ECtPM/9gacWxy2KFQKt1gMNA==} - pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} @@ -7109,10 +6148,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -7140,9 +6175,6 @@ packages: peberminta@0.9.0: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} - pg-connection-string@2.6.2: - resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==} - pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} @@ -7178,15 +6210,6 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - pinia@2.3.1: - resolution: {integrity: sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==} - peerDependencies: - typescript: '>=4.4.4' - vue: ^2.7.0 || ^3.5.11 - peerDependenciesMeta: - typescript: - optional: true - pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} @@ -7236,47 +6259,6 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss-calc@8.2.4: - resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} - peerDependencies: - postcss: ^8.2.2 - - postcss-colormin@5.3.1: - resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-convert-values@5.1.3: - resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-comments@5.1.2: - resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-duplicates@5.1.0: - resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-empty@5.1.1: - resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-discard-overridden@5.1.0: - resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - postcss-import@15.1.0: resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} @@ -7307,144 +6289,12 @@ packages: yaml: optional: true - postcss-merge-longhand@5.1.7: - resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-merge-rules@5.1.4: - resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-font-values@5.1.0: - resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-gradients@5.1.1: - resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-params@5.1.4: - resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-minify-selectors@5.2.1: - resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-modules-extract-imports@3.1.0: - resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - postcss-modules-local-by-default@4.2.0: - resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - postcss-modules-scope@3.2.1: - resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - - postcss-modules-values@4.0.0: - resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - postcss-nested@6.2.0: resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 - postcss-normalize-charset@5.1.0: - resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-display-values@5.1.0: - resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-positions@5.1.1: - resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-repeat-style@5.1.1: - resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-string@5.1.0: - resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-timing-functions@5.1.0: - resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-unicode@5.1.1: - resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-url@5.1.0: - resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-normalize-whitespace@5.1.1: - resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-ordered-values@5.1.3: - resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-reduce-initial@5.1.2: - resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-reduce-transforms@5.1.0: - resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - postcss-selector-parser@6.0.10: resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} engines: {node: '>=4'} @@ -7453,22 +6303,6 @@ packages: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} - postcss-selector-parser@7.1.1: - resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} - engines: {node: '>=4'} - - postcss-svgo@5.1.0: - resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - - postcss-unique-selectors@5.1.1: - resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -7574,10 +6408,6 @@ packages: quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} - query-string@7.1.3: - resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} - engines: {node: '>=6'} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -7661,10 +6491,6 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} - rechoir@0.8.0: - resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} - engines: {node: '>= 10.13.0'} - redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -7761,24 +6587,6 @@ packages: resolution: {integrity: sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==} engines: {node: '>=10.0.0'} - rollup-plugin-esbuild@5.0.0: - resolution: {integrity: sha512-1cRIOHAPh8WQgdQQyyvFdeOdxuiyk+zB5zJ5+YOwrZP4cJ0MT3Fs48pQxrZeyZHcn+klFherytILVfE4aYrneg==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - peerDependencies: - esbuild: '>=0.10.1' - rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 - - rollup-plugin-styles@4.0.0: - resolution: {integrity: sha512-A2K2sao84OsTmDxXG83JTCdXWrmgvQkkI38XDat46rdtpGMRm9tSYqeCdlwwGDJF4kKIafhV1mUidqu8MxUGig==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - peerDependencies: - rollup: ^2.63.0 - - rollup@3.29.4: - resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - rollup@4.57.1: resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -7965,9 +6773,6 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - smob@1.5.0: - resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} - socks-proxy-agent@8.0.5: resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} engines: {node: '>= 14'} @@ -7997,10 +6802,6 @@ packages: spawndamnit@3.0.1: resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} - split-on-first@1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} - split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -8014,10 +6815,6 @@ packages: stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} - stable@0.1.8: - resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} - deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' - stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -8032,10 +6829,6 @@ packages: std-env@3.10.0: resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} - stdin-discarder@0.1.0: - resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -8049,10 +6842,6 @@ packages: stream-json@1.9.1: resolution: {integrity: sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==} - strict-uri-encode@2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} - string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -8119,10 +6908,6 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -8159,12 +6944,6 @@ packages: babel-plugin-macros: optional: true - stylehacks@5.1.1: - resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} - engines: {node: ^10 || ^12 || >=14.0} - peerDependencies: - postcss: ^8.2.15 - sucrase@3.35.1: resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} engines: {node: '>=16 || 14 >=14.17'} @@ -8189,11 +6968,6 @@ packages: svg-arc-to-cubic-bezier@3.2.0: resolution: {integrity: sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==} - svgo@2.8.0: - resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} - engines: {node: '>=10.13.0'} - hasBin: true - symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -8216,10 +6990,6 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} - tarn@3.0.2: - resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} - engines: {node: '>=8.0.0'} - term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -8265,10 +7035,6 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tildify@2.0.0: - resolution: {integrity: sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==} - engines: {node: '>=8'} - tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} @@ -8488,9 +7254,6 @@ packages: resolution: {integrity: sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==} engines: {node: '>=20.18.1'} - unhead@1.11.20: - resolution: {integrity: sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==} - unicode-properties@1.4.1: resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} @@ -8553,34 +7316,6 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@4.5.2: - resolution: {integrity: sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - vite@5.4.21: resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -8739,33 +7474,6 @@ packages: jsdom: optional: true - vue-demi@0.14.10: - resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} - engines: {node: '>=12'} - hasBin: true - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - - vue@3.4.21: - resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - vue@3.5.28: - resolution: {integrity: sha512-BRdrNfeoccSoIZeIhyPBfvWSLFP4q8J3u8Ju8Ug5vu3LdD+yTM13Sg4sKtljxozbnuMu1NB1X5HBHRYUzFocKg==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -8920,10 +7628,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - yaml@2.8.2: resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} engines: {node: '>= 14.6'} @@ -8955,18 +7659,12 @@ packages: yoga-layout@3.2.1: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} - zhead@2.2.4: - resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} - zod-validation-error@4.0.2: resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} engines: {node: '>=18.0.0'} peerDependencies: zod: ^3.25.0 || ^4.0.0 - zod@3.22.4: - resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} - zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -9691,243 +8389,6 @@ snapshots: '@csstools/css-tokenizer@4.0.0': {} - '@directus/composables@10.1.12(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@directus/constants': 11.0.3 - '@directus/utils': 11.0.7(vue@3.4.21(typescript@5.9.3)) - axios: 1.6.7 - lodash-es: 4.17.21 - nanoid: 5.0.6 - vue: 3.4.21(typescript@5.9.3) - transitivePeerDependencies: - - debug - - '@directus/constants@11.0.3': {} - - '@directus/extensions-sdk@11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)': - dependencies: - '@directus/composables': 10.1.12(vue@3.4.21(typescript@5.9.3)) - '@directus/constants': 11.0.3 - '@directus/extensions': 1.0.2(@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3)))(knex@3.1.0)(pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)))(pino@10.3.1)(vue@3.4.21(typescript@5.9.3)) - '@directus/themes': 0.3.6(@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3)))(pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)))(vue@3.4.21(typescript@5.9.3)) - '@directus/types': 11.0.8(knex@3.1.0)(vue@3.4.21(typescript@5.9.3)) - '@directus/utils': 11.0.7(vue@3.4.21(typescript@5.9.3)) - '@rollup/plugin-commonjs': 25.0.7(rollup@3.29.4) - '@rollup/plugin-json': 6.1.0(rollup@3.29.4) - '@rollup/plugin-node-resolve': 15.2.3(rollup@3.29.4) - '@rollup/plugin-replace': 5.0.5(rollup@3.29.4) - '@rollup/plugin-terser': 0.4.4(rollup@3.29.4) - '@rollup/plugin-virtual': 3.0.2(rollup@3.29.4) - '@vitejs/plugin-vue': 4.6.2(vite@4.5.2(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0))(vue@3.4.21(typescript@5.9.3)) - chalk: 5.3.0 - commander: 10.0.1 - esbuild: 0.17.19 - execa: 7.2.0 - fs-extra: 11.2.0 - inquirer: 9.2.16 - ora: 6.3.1 - rollup: 3.29.4 - rollup-plugin-esbuild: 5.0.0(esbuild@0.17.19)(rollup@3.29.4) - rollup-plugin-styles: 4.0.0(rollup@3.29.4) - vite: 4.5.2(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) - vue: 3.4.21(typescript@5.9.3) - transitivePeerDependencies: - - '@types/node' - - '@unhead/vue' - - better-sqlite3 - - debug - - knex - - less - - lightningcss - - mysql - - mysql2 - - pg - - pg-native - - pinia - - pino - - sass - - sqlite3 - - stylus - - sugarss - - supports-color - - tedious - - terser - - typescript - - vue-router - - '@directus/extensions-sdk@11.0.2(@types/node@22.19.10)(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(lightningcss@1.30.2)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)': - dependencies: - '@directus/composables': 10.1.12(vue@3.4.21(typescript@5.9.3)) - '@directus/constants': 11.0.3 - '@directus/extensions': 1.0.2(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(vue@3.4.21(typescript@5.9.3)) - '@directus/themes': 0.3.6(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(vue@3.4.21(typescript@5.9.3)) - '@directus/types': 11.0.8(knex@3.1.0)(vue@3.4.21(typescript@5.9.3)) - '@directus/utils': 11.0.7(vue@3.4.21(typescript@5.9.3)) - '@rollup/plugin-commonjs': 25.0.7(rollup@3.29.4) - '@rollup/plugin-json': 6.1.0(rollup@3.29.4) - '@rollup/plugin-node-resolve': 15.2.3(rollup@3.29.4) - '@rollup/plugin-replace': 5.0.5(rollup@3.29.4) - '@rollup/plugin-terser': 0.4.4(rollup@3.29.4) - '@rollup/plugin-virtual': 3.0.2(rollup@3.29.4) - '@vitejs/plugin-vue': 4.6.2(vite@4.5.2(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0))(vue@3.4.21(typescript@5.9.3)) - chalk: 5.3.0 - commander: 10.0.1 - esbuild: 0.17.19 - execa: 7.2.0 - fs-extra: 11.2.0 - inquirer: 9.2.16 - ora: 6.3.1 - rollup: 3.29.4 - rollup-plugin-esbuild: 5.0.0(esbuild@0.17.19)(rollup@3.29.4) - rollup-plugin-styles: 4.0.0(rollup@3.29.4) - vite: 4.5.2(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) - vue: 3.4.21(typescript@5.9.3) - transitivePeerDependencies: - - '@types/node' - - '@unhead/vue' - - better-sqlite3 - - debug - - knex - - less - - lightningcss - - mysql - - mysql2 - - pg - - pg-native - - pinia - - pino - - sass - - sqlite3 - - stylus - - sugarss - - supports-color - - tedious - - terser - - typescript - - vue-router - - '@directus/extensions@1.0.2(@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3)))(knex@3.1.0)(pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)))(pino@10.3.1)(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@directus/constants': 11.0.3 - '@directus/themes': 0.3.6(@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3)))(pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)))(vue@3.4.21(typescript@5.9.3)) - '@directus/types': 11.0.8(knex@3.1.0)(vue@3.4.21(typescript@5.9.3)) - '@directus/utils': 11.0.7(vue@3.4.21(typescript@5.9.3)) - '@types/express': 4.17.21 - fs-extra: 11.2.0 - lodash-es: 4.17.21 - zod: 3.22.4 - optionalDependencies: - knex: 3.1.0 - pino: 10.3.1 - vue: 3.4.21(typescript@5.9.3) - transitivePeerDependencies: - - '@unhead/vue' - - better-sqlite3 - - mysql - - mysql2 - - pg - - pg-native - - pinia - - sqlite3 - - supports-color - - tedious - - '@directus/extensions@1.0.2(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(knex@3.1.0)(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(pino@10.3.1)(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@directus/constants': 11.0.3 - '@directus/themes': 0.3.6(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(vue@3.4.21(typescript@5.9.3)) - '@directus/types': 11.0.8(knex@3.1.0)(vue@3.4.21(typescript@5.9.3)) - '@directus/utils': 11.0.7(vue@3.4.21(typescript@5.9.3)) - '@types/express': 4.17.21 - fs-extra: 11.2.0 - lodash-es: 4.17.21 - zod: 3.22.4 - optionalDependencies: - knex: 3.1.0 - pino: 10.3.1 - vue: 3.4.21(typescript@5.9.3) - transitivePeerDependencies: - - '@unhead/vue' - - better-sqlite3 - - mysql - - mysql2 - - pg - - pg-native - - pinia - - sqlite3 - - supports-color - - tedious - - '@directus/schema@11.0.1': - dependencies: - knex: 3.1.0 - transitivePeerDependencies: - - better-sqlite3 - - mysql - - mysql2 - - pg - - pg-native - - sqlite3 - - supports-color - - tedious - - '@directus/sdk@21.1.0': {} - - '@directus/system-data@1.0.2': {} - - '@directus/themes@0.3.6(@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3)))(pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)))(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@directus/utils': 11.0.7(vue@3.4.21(typescript@5.9.3)) - '@sinclair/typebox': 0.32.15 - '@unhead/vue': 1.11.20(vue@3.4.21(typescript@5.9.3)) - decamelize: 6.0.0 - flat: 6.0.1 - lodash-es: 4.17.21 - pinia: 2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)) - vue: 3.4.21(typescript@5.9.3) - - '@directus/themes@0.3.6(@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3)))(pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)))(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@directus/utils': 11.0.7(vue@3.4.21(typescript@5.9.3)) - '@sinclair/typebox': 0.32.15 - '@unhead/vue': 1.11.20(vue@3.5.28(typescript@5.9.3)) - decamelize: 6.0.0 - flat: 6.0.1 - lodash-es: 4.17.21 - pinia: 2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)) - vue: 3.4.21(typescript@5.9.3) - - '@directus/types@11.0.8(knex@3.1.0)(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@directus/constants': 11.0.3 - '@directus/schema': 11.0.1 - '@types/geojson': 7946.0.14 - optionalDependencies: - knex: 3.1.0 - vue: 3.4.21(typescript@5.9.3) - transitivePeerDependencies: - - better-sqlite3 - - mysql - - mysql2 - - pg - - pg-native - - sqlite3 - - supports-color - - tedious - - '@directus/utils@11.0.7(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@directus/constants': 11.0.3 - '@directus/system-data': 1.0.2 - date-fns: 3.6.0 - fs-extra: 11.2.0 - joi: 17.12.2 - js-yaml: 4.1.0 - lodash-es: 4.17.21 - micromustache: 8.0.3 - optionalDependencies: - vue: 3.4.21(typescript@5.9.3) - '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -9953,12 +8414,6 @@ snapshots: '@esbuild/aix-ppc64@0.27.3': optional: true - '@esbuild/android-arm64@0.17.19': - optional: true - - '@esbuild/android-arm64@0.18.20': - optional: true - '@esbuild/android-arm64@0.21.5': optional: true @@ -9968,12 +8423,6 @@ snapshots: '@esbuild/android-arm64@0.27.3': optional: true - '@esbuild/android-arm@0.17.19': - optional: true - - '@esbuild/android-arm@0.18.20': - optional: true - '@esbuild/android-arm@0.21.5': optional: true @@ -9983,12 +8432,6 @@ snapshots: '@esbuild/android-arm@0.27.3': optional: true - '@esbuild/android-x64@0.17.19': - optional: true - - '@esbuild/android-x64@0.18.20': - optional: true - '@esbuild/android-x64@0.21.5': optional: true @@ -9998,12 +8441,6 @@ snapshots: '@esbuild/android-x64@0.27.3': optional: true - '@esbuild/darwin-arm64@0.17.19': - optional: true - - '@esbuild/darwin-arm64@0.18.20': - optional: true - '@esbuild/darwin-arm64@0.21.5': optional: true @@ -10013,12 +8450,6 @@ snapshots: '@esbuild/darwin-arm64@0.27.3': optional: true - '@esbuild/darwin-x64@0.17.19': - optional: true - - '@esbuild/darwin-x64@0.18.20': - optional: true - '@esbuild/darwin-x64@0.21.5': optional: true @@ -10028,12 +8459,6 @@ snapshots: '@esbuild/darwin-x64@0.27.3': optional: true - '@esbuild/freebsd-arm64@0.17.19': - optional: true - - '@esbuild/freebsd-arm64@0.18.20': - optional: true - '@esbuild/freebsd-arm64@0.21.5': optional: true @@ -10043,12 +8468,6 @@ snapshots: '@esbuild/freebsd-arm64@0.27.3': optional: true - '@esbuild/freebsd-x64@0.17.19': - optional: true - - '@esbuild/freebsd-x64@0.18.20': - optional: true - '@esbuild/freebsd-x64@0.21.5': optional: true @@ -10058,12 +8477,6 @@ snapshots: '@esbuild/freebsd-x64@0.27.3': optional: true - '@esbuild/linux-arm64@0.17.19': - optional: true - - '@esbuild/linux-arm64@0.18.20': - optional: true - '@esbuild/linux-arm64@0.21.5': optional: true @@ -10073,12 +8486,6 @@ snapshots: '@esbuild/linux-arm64@0.27.3': optional: true - '@esbuild/linux-arm@0.17.19': - optional: true - - '@esbuild/linux-arm@0.18.20': - optional: true - '@esbuild/linux-arm@0.21.5': optional: true @@ -10088,12 +8495,6 @@ snapshots: '@esbuild/linux-arm@0.27.3': optional: true - '@esbuild/linux-ia32@0.17.19': - optional: true - - '@esbuild/linux-ia32@0.18.20': - optional: true - '@esbuild/linux-ia32@0.21.5': optional: true @@ -10103,12 +8504,6 @@ snapshots: '@esbuild/linux-ia32@0.27.3': optional: true - '@esbuild/linux-loong64@0.17.19': - optional: true - - '@esbuild/linux-loong64@0.18.20': - optional: true - '@esbuild/linux-loong64@0.21.5': optional: true @@ -10118,12 +8513,6 @@ snapshots: '@esbuild/linux-loong64@0.27.3': optional: true - '@esbuild/linux-mips64el@0.17.19': - optional: true - - '@esbuild/linux-mips64el@0.18.20': - optional: true - '@esbuild/linux-mips64el@0.21.5': optional: true @@ -10133,12 +8522,6 @@ snapshots: '@esbuild/linux-mips64el@0.27.3': optional: true - '@esbuild/linux-ppc64@0.17.19': - optional: true - - '@esbuild/linux-ppc64@0.18.20': - optional: true - '@esbuild/linux-ppc64@0.21.5': optional: true @@ -10148,12 +8531,6 @@ snapshots: '@esbuild/linux-ppc64@0.27.3': optional: true - '@esbuild/linux-riscv64@0.17.19': - optional: true - - '@esbuild/linux-riscv64@0.18.20': - optional: true - '@esbuild/linux-riscv64@0.21.5': optional: true @@ -10163,12 +8540,6 @@ snapshots: '@esbuild/linux-riscv64@0.27.3': optional: true - '@esbuild/linux-s390x@0.17.19': - optional: true - - '@esbuild/linux-s390x@0.18.20': - optional: true - '@esbuild/linux-s390x@0.21.5': optional: true @@ -10178,12 +8549,6 @@ snapshots: '@esbuild/linux-s390x@0.27.3': optional: true - '@esbuild/linux-x64@0.17.19': - optional: true - - '@esbuild/linux-x64@0.18.20': - optional: true - '@esbuild/linux-x64@0.21.5': optional: true @@ -10199,12 +8564,6 @@ snapshots: '@esbuild/netbsd-arm64@0.27.3': optional: true - '@esbuild/netbsd-x64@0.17.19': - optional: true - - '@esbuild/netbsd-x64@0.18.20': - optional: true - '@esbuild/netbsd-x64@0.21.5': optional: true @@ -10220,12 +8579,6 @@ snapshots: '@esbuild/openbsd-arm64@0.27.3': optional: true - '@esbuild/openbsd-x64@0.17.19': - optional: true - - '@esbuild/openbsd-x64@0.18.20': - optional: true - '@esbuild/openbsd-x64@0.21.5': optional: true @@ -10241,12 +8594,6 @@ snapshots: '@esbuild/openharmony-arm64@0.27.3': optional: true - '@esbuild/sunos-x64@0.17.19': - optional: true - - '@esbuild/sunos-x64@0.18.20': - optional: true - '@esbuild/sunos-x64@0.21.5': optional: true @@ -10256,12 +8603,6 @@ snapshots: '@esbuild/sunos-x64@0.27.3': optional: true - '@esbuild/win32-arm64@0.17.19': - optional: true - - '@esbuild/win32-arm64@0.18.20': - optional: true - '@esbuild/win32-arm64@0.21.5': optional: true @@ -10271,12 +8612,6 @@ snapshots: '@esbuild/win32-arm64@0.27.3': optional: true - '@esbuild/win32-ia32@0.17.19': - optional: true - - '@esbuild/win32-ia32@0.18.20': - optional: true - '@esbuild/win32-ia32@0.21.5': optional: true @@ -10286,12 +8621,6 @@ snapshots: '@esbuild/win32-ia32@0.27.3': optional: true - '@esbuild/win32-x64@0.17.19': - optional: true - - '@esbuild/win32-x64@0.18.20': - optional: true - '@esbuild/win32-x64@0.21.5': optional: true @@ -10396,12 +8725,6 @@ snapshots: '@formatjs/fast-memoize': 3.1.0 tslib: 2.8.1 - '@hapi/hoek@9.3.0': {} - - '@hapi/topo@5.1.0': - dependencies: - '@hapi/hoek': 9.3.0 - '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -11247,17 +9570,6 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.2': {} - '@rollup/plugin-commonjs@25.0.7(rollup@3.29.4)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@3.29.4) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.30.21 - optionalDependencies: - rollup: 3.29.4 - '@rollup/plugin-commonjs@28.0.1(rollup@4.57.1)': dependencies: '@rollup/pluginutils': 5.3.0(rollup@4.57.1) @@ -11270,55 +9582,6 @@ snapshots: optionalDependencies: rollup: 4.57.1 - '@rollup/plugin-json@6.1.0(rollup@3.29.4)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@3.29.4) - optionalDependencies: - rollup: 3.29.4 - - '@rollup/plugin-node-resolve@15.2.3(rollup@3.29.4)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@3.29.4) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-builtin-module: 3.2.1 - is-module: 1.0.0 - resolve: 1.22.11 - optionalDependencies: - rollup: 3.29.4 - - '@rollup/plugin-replace@5.0.5(rollup@3.29.4)': - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@3.29.4) - magic-string: 0.30.21 - optionalDependencies: - rollup: 3.29.4 - - '@rollup/plugin-terser@0.4.4(rollup@3.29.4)': - dependencies: - serialize-javascript: 6.0.2 - smob: 1.5.0 - terser: 5.46.0 - optionalDependencies: - rollup: 3.29.4 - - '@rollup/plugin-virtual@3.0.2(rollup@3.29.4)': - optionalDependencies: - rollup: 3.29.4 - - '@rollup/pluginutils@4.2.1': - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - - '@rollup/pluginutils@5.3.0(rollup@3.29.4)': - dependencies: - '@types/estree': 1.0.8 - estree-walker: 2.0.2 - picomatch: 4.0.3 - optionalDependencies: - rollup: 3.29.4 - '@rollup/pluginutils@5.3.0(rollup@4.57.1)': dependencies: '@types/estree': 1.0.8 @@ -11655,16 +9918,6 @@ snapshots: - encoding - supports-color - '@sideway/address@4.1.5': - dependencies: - '@hapi/hoek': 9.3.0 - - '@sideway/formula@3.0.1': {} - - '@sideway/pinpoint@2.0.0': {} - - '@sinclair/typebox@0.32.15': {} - '@sindresorhus/is@4.6.0': {} '@sindresorhus/is@5.6.0': {} @@ -11745,6 +9998,12 @@ snapshots: '@types/seedrandom': 2.4.34 seedrandom: 3.0.5 + '@tensorflow/tfjs-backend-wasm@4.22.0(@tensorflow/tfjs-core@4.22.0)': + dependencies: + '@tensorflow/tfjs-backend-cpu': 4.22.0(@tensorflow/tfjs-core@4.22.0) + '@tensorflow/tfjs-core': 4.22.0 + '@types/emscripten': 0.0.34 + '@tensorflow/tfjs-backend-webgl@4.22.0(@tensorflow/tfjs-core@4.22.0)': dependencies: '@tensorflow/tfjs-backend-cpu': 4.22.0(@tensorflow/tfjs-core@4.22.0) @@ -11840,8 +10099,6 @@ snapshots: '@tokenizer/token@0.3.0': {} - '@trysound/sax@0.2.0': {} - '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -11870,11 +10127,6 @@ snapshots: dependencies: '@babel/types': 7.29.0 - '@types/body-parser@1.19.6': - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.19.33 - '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 @@ -11886,12 +10138,6 @@ snapshots: '@types/content-type@1.1.9': {} - '@types/cssnano@5.1.3(postcss@8.5.6)': - dependencies: - cssnano: 5.1.15(postcss@8.5.6) - transitivePeerDependencies: - - postcss - '@types/debug@4.1.12': dependencies: '@types/ms': 2.1.0 @@ -11899,6 +10145,8 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/emscripten@0.0.34': {} + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -11911,31 +10159,13 @@ snapshots: '@types/estree@1.0.8': {} - '@types/express-serve-static-core@4.19.8': - dependencies: - '@types/node': 20.19.33 - '@types/qs': 6.14.0 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 - - '@types/express@4.17.21': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 4.19.8 - '@types/qs': 6.14.0 - '@types/serve-static': 2.2.0 - '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 '@types/node': 20.19.33 - '@types/geojson@7946.0.14': {} - '@types/http-cache-semantics@4.2.0': {} - '@types/http-errors@2.0.5': {} - '@types/jsdom@21.1.7': dependencies: '@types/node': 20.19.33 @@ -11982,8 +10212,6 @@ snapshots: '@types/offscreencanvas@2019.7.3': {} - '@types/parse-json@4.0.2': {} - '@types/pg-pool@2.0.7': dependencies: '@types/pg': 8.15.6 @@ -12001,10 +10229,6 @@ snapshots: '@types/prop-types@15.7.15': {} - '@types/qs@6.14.0': {} - - '@types/range-parser@1.2.7': {} - '@types/react-dom@19.2.3(@types/react@19.2.13)': dependencies: '@types/react': 19.2.13 @@ -12018,23 +10242,12 @@ snapshots: dependencies: csstype: 3.2.3 - '@types/resolve@1.20.2': {} - '@types/sax@1.2.7': dependencies: '@types/node': 20.19.33 '@types/seedrandom@2.4.34': {} - '@types/send@1.2.1': - dependencies: - '@types/node': 20.19.33 - - '@types/serve-static@2.2.0': - dependencies: - '@types/http-errors': 2.0.5 - '@types/node': 20.19.33 - '@types/tedious@4.0.14': dependencies: '@types/node': 20.19.33 @@ -12138,37 +10351,6 @@ snapshots: '@typescript-eslint/types': 8.55.0 eslint-visitor-keys: 4.2.1 - '@unhead/dom@1.11.20': - dependencies: - '@unhead/schema': 1.11.20 - '@unhead/shared': 1.11.20 - - '@unhead/schema@1.11.20': - dependencies: - hookable: 5.5.3 - zhead: 2.2.4 - - '@unhead/shared@1.11.20': - dependencies: - '@unhead/schema': 1.11.20 - packrup: 0.1.2 - - '@unhead/vue@1.11.20(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@unhead/schema': 1.11.20 - '@unhead/shared': 1.11.20 - hookable: 5.5.3 - unhead: 1.11.20 - vue: 3.4.21(typescript@5.9.3) - - '@unhead/vue@1.11.20(vue@3.5.28(typescript@5.9.3))': - dependencies: - '@unhead/schema': 1.11.20 - '@unhead/shared': 1.11.20 - hookable: 5.5.3 - unhead: 1.11.20 - vue: 3.5.28(typescript@5.9.3) - '@unrs/resolver-binding-android-arm-eabi@1.11.1': optional: true @@ -12240,17 +10422,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@4.6.2(vite@4.5.2(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0))(vue@3.4.21(typescript@5.9.3))': - dependencies: - vite: 4.5.2(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) - vue: 3.4.21(typescript@5.9.3) - - '@vitejs/plugin-vue@6.0.4(vite@5.4.21(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0))(vue@3.5.28(typescript@5.9.3))': - dependencies: - '@rolldown/pluginutils': 1.0.0-rc.2 - vite: 5.4.21(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0) - vue: 3.5.28(typescript@5.9.3) - '@vitest/expect@2.1.9': dependencies: '@vitest/spy': 2.1.9 @@ -12396,115 +10567,6 @@ snapshots: '@vladmandic/face-api@1.7.15': {} - '@vue/compiler-core@3.4.21': - dependencies: - '@babel/parser': 7.29.0 - '@vue/shared': 3.4.21 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.1 - - '@vue/compiler-core@3.5.28': - dependencies: - '@babel/parser': 7.29.0 - '@vue/shared': 3.5.28 - entities: 7.0.1 - estree-walker: 2.0.2 - source-map-js: 1.2.1 - - '@vue/compiler-dom@3.4.21': - dependencies: - '@vue/compiler-core': 3.4.21 - '@vue/shared': 3.4.21 - - '@vue/compiler-dom@3.5.28': - dependencies: - '@vue/compiler-core': 3.5.28 - '@vue/shared': 3.5.28 - - '@vue/compiler-sfc@3.4.21': - dependencies: - '@babel/parser': 7.29.0 - '@vue/compiler-core': 3.4.21 - '@vue/compiler-dom': 3.4.21 - '@vue/compiler-ssr': 3.4.21 - '@vue/shared': 3.4.21 - estree-walker: 2.0.2 - magic-string: 0.30.21 - postcss: 8.5.6 - source-map-js: 1.2.1 - - '@vue/compiler-sfc@3.5.28': - dependencies: - '@babel/parser': 7.29.0 - '@vue/compiler-core': 3.5.28 - '@vue/compiler-dom': 3.5.28 - '@vue/compiler-ssr': 3.5.28 - '@vue/shared': 3.5.28 - estree-walker: 2.0.2 - magic-string: 0.30.21 - postcss: 8.5.6 - source-map-js: 1.2.1 - - '@vue/compiler-ssr@3.4.21': - dependencies: - '@vue/compiler-dom': 3.4.21 - '@vue/shared': 3.4.21 - - '@vue/compiler-ssr@3.5.28': - dependencies: - '@vue/compiler-dom': 3.5.28 - '@vue/shared': 3.5.28 - - '@vue/devtools-api@6.6.4': {} - - '@vue/reactivity@3.4.21': - dependencies: - '@vue/shared': 3.4.21 - - '@vue/reactivity@3.5.28': - dependencies: - '@vue/shared': 3.5.28 - - '@vue/runtime-core@3.4.21': - dependencies: - '@vue/reactivity': 3.4.21 - '@vue/shared': 3.4.21 - - '@vue/runtime-core@3.5.28': - dependencies: - '@vue/reactivity': 3.5.28 - '@vue/shared': 3.5.28 - - '@vue/runtime-dom@3.4.21': - dependencies: - '@vue/runtime-core': 3.4.21 - '@vue/shared': 3.4.21 - csstype: 3.2.3 - - '@vue/runtime-dom@3.5.28': - dependencies: - '@vue/reactivity': 3.5.28 - '@vue/runtime-core': 3.5.28 - '@vue/shared': 3.5.28 - csstype: 3.2.3 - - '@vue/server-renderer@3.4.21(vue@3.4.21(typescript@5.9.3))': - dependencies: - '@vue/compiler-ssr': 3.4.21 - '@vue/shared': 3.4.21 - vue: 3.4.21(typescript@5.9.3) - - '@vue/server-renderer@3.5.28(vue@3.5.28(typescript@5.9.3))': - dependencies: - '@vue/compiler-ssr': 3.5.28 - '@vue/shared': 3.5.28 - vue: 3.5.28(typescript@5.9.3) - - '@vue/shared@3.4.21': {} - - '@vue/shared@3.5.28': {} - '@webassemblyjs/ast@1.14.1': dependencies: '@webassemblyjs/helper-numbers': 1.13.2 @@ -12808,14 +10870,6 @@ snapshots: transitivePeerDependencies: - debug - axios@1.6.7: - dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.5 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - axobject-query@4.1.0: {} balanced-match@1.0.2: {} @@ -12844,12 +10898,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - bl@5.1.0: - dependencies: - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 3.6.2 - boolbase@1.0.0: {} brace-expansion@1.1.12: @@ -12892,8 +10940,7 @@ snapshots: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - - builtin-modules@3.3.0: {} + optional: true bundle-require@5.1.0(esbuild@0.27.3): dependencies: @@ -12939,13 +10986,6 @@ snapshots: camelcase-css@2.0.1: {} - caniuse-api@3.0.0: - dependencies: - browserslist: 4.28.1 - caniuse-lite: 1.0.30001769 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001769: {} canvas@3.2.1: @@ -12976,8 +11016,6 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.3.0: {} - chalk@5.6.2: {} chardet@0.7.0: {} @@ -13113,18 +11151,12 @@ snapshots: color-convert: 2.0.1 color-string: 1.9.1 - colord@2.9.3: {} - - colorette@2.0.19: {} - colorette@2.0.20: {} combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 - commander@10.0.1: {} - commander@11.1.0: {} commander@12.1.0: {} @@ -13137,8 +11169,6 @@ snapshots: commander@4.1.1: {} - commander@7.2.0: {} - commondir@1.0.1: {} compare-func@2.0.0: @@ -13181,14 +11211,6 @@ snapshots: jiti: 2.6.1 typescript: 5.9.3 - cosmiconfig@7.1.0: - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.1 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - cosmiconfig@9.0.0(typescript@5.9.3): dependencies: env-paths: 2.2.1 @@ -13231,22 +11253,10 @@ snapshots: crypto-js@4.2.0: {} - css-declaration-sorter@6.4.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - css-line-break@2.1.0: dependencies: utrie: 1.0.2 - css-select@4.3.0: - dependencies: - boolbase: 1.0.0 - css-what: 6.2.2 - domhandler: 4.3.1 - domutils: 2.8.0 - nth-check: 2.1.1 - css-select@5.2.2: dependencies: boolbase: 1.0.0 @@ -13255,11 +11265,6 @@ snapshots: domutils: 3.2.2 nth-check: 2.1.1 - css-tree@1.1.3: - dependencies: - mdn-data: 2.0.14 - source-map: 0.6.1 - css-tree@3.1.0: dependencies: mdn-data: 2.12.2 @@ -13271,54 +11276,6 @@ snapshots: cssesc@3.0.0: {} - cssnano-preset-default@5.2.14(postcss@8.5.6): - dependencies: - css-declaration-sorter: 6.4.1(postcss@8.5.6) - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-calc: 8.2.4(postcss@8.5.6) - postcss-colormin: 5.3.1(postcss@8.5.6) - postcss-convert-values: 5.1.3(postcss@8.5.6) - postcss-discard-comments: 5.1.2(postcss@8.5.6) - postcss-discard-duplicates: 5.1.0(postcss@8.5.6) - postcss-discard-empty: 5.1.1(postcss@8.5.6) - postcss-discard-overridden: 5.1.0(postcss@8.5.6) - postcss-merge-longhand: 5.1.7(postcss@8.5.6) - postcss-merge-rules: 5.1.4(postcss@8.5.6) - postcss-minify-font-values: 5.1.0(postcss@8.5.6) - postcss-minify-gradients: 5.1.1(postcss@8.5.6) - postcss-minify-params: 5.1.4(postcss@8.5.6) - postcss-minify-selectors: 5.2.1(postcss@8.5.6) - postcss-normalize-charset: 5.1.0(postcss@8.5.6) - postcss-normalize-display-values: 5.1.0(postcss@8.5.6) - postcss-normalize-positions: 5.1.1(postcss@8.5.6) - postcss-normalize-repeat-style: 5.1.1(postcss@8.5.6) - postcss-normalize-string: 5.1.0(postcss@8.5.6) - postcss-normalize-timing-functions: 5.1.0(postcss@8.5.6) - postcss-normalize-unicode: 5.1.1(postcss@8.5.6) - postcss-normalize-url: 5.1.0(postcss@8.5.6) - postcss-normalize-whitespace: 5.1.1(postcss@8.5.6) - postcss-ordered-values: 5.1.3(postcss@8.5.6) - postcss-reduce-initial: 5.1.2(postcss@8.5.6) - postcss-reduce-transforms: 5.1.0(postcss@8.5.6) - postcss-svgo: 5.1.0(postcss@8.5.6) - postcss-unique-selectors: 5.1.1(postcss@8.5.6) - - cssnano-utils@3.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - cssnano@5.1.15(postcss@8.5.6): - dependencies: - cssnano-preset-default: 5.2.14(postcss@8.5.6) - lilconfig: 2.1.0 - postcss: 8.5.6 - yaml: 1.10.2 - - csso@4.2.0: - dependencies: - css-tree: 1.1.3 - cssom@0.5.0: {} cssstyle@4.6.0: @@ -13369,28 +11326,18 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 - date-fns@3.6.0: {} - dateformat@4.6.3: {} debug@3.2.7: dependencies: ms: 2.1.3 - debug@4.3.4: - dependencies: - ms: 2.1.2 - debug@4.4.3: dependencies: ms: 2.1.3 - decamelize@6.0.0: {} - decimal.js@10.6.0: {} - decode-uri-component@0.2.2: {} - decompress-response@10.0.0: dependencies: mimic-response: 4.0.0 @@ -13451,12 +11398,6 @@ snapshots: dom-accessibility-api@0.6.3: {} - dom-serializer@1.4.1: - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - entities: 2.2.0 - dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -13465,20 +11406,10 @@ snapshots: domelementtype@2.3.0: {} - domhandler@4.3.1: - dependencies: - domelementtype: 2.3.0 - domhandler@5.0.3: dependencies: domelementtype: 2.3.0 - domutils@2.8.0: - dependencies: - dom-serializer: 1.4.1 - domelementtype: 2.3.0 - domhandler: 4.3.1 - domutils@3.2.2: dependencies: dom-serializer: 2.0.0 @@ -13540,8 +11471,6 @@ snapshots: ansi-colors: 4.1.3 strip-ansi: 6.0.1 - entities@2.2.0: {} - entities@4.5.0: {} entities@6.0.1: {} @@ -13663,56 +11592,6 @@ snapshots: es-toolkit@1.44.0: {} - esbuild@0.17.19: - optionalDependencies: - '@esbuild/android-arm': 0.17.19 - '@esbuild/android-arm64': 0.17.19 - '@esbuild/android-x64': 0.17.19 - '@esbuild/darwin-arm64': 0.17.19 - '@esbuild/darwin-x64': 0.17.19 - '@esbuild/freebsd-arm64': 0.17.19 - '@esbuild/freebsd-x64': 0.17.19 - '@esbuild/linux-arm': 0.17.19 - '@esbuild/linux-arm64': 0.17.19 - '@esbuild/linux-ia32': 0.17.19 - '@esbuild/linux-loong64': 0.17.19 - '@esbuild/linux-mips64el': 0.17.19 - '@esbuild/linux-ppc64': 0.17.19 - '@esbuild/linux-riscv64': 0.17.19 - '@esbuild/linux-s390x': 0.17.19 - '@esbuild/linux-x64': 0.17.19 - '@esbuild/netbsd-x64': 0.17.19 - '@esbuild/openbsd-x64': 0.17.19 - '@esbuild/sunos-x64': 0.17.19 - '@esbuild/win32-arm64': 0.17.19 - '@esbuild/win32-ia32': 0.17.19 - '@esbuild/win32-x64': 0.17.19 - - esbuild@0.18.20: - optionalDependencies: - '@esbuild/android-arm': 0.18.20 - '@esbuild/android-arm64': 0.18.20 - '@esbuild/android-x64': 0.18.20 - '@esbuild/darwin-arm64': 0.18.20 - '@esbuild/darwin-x64': 0.18.20 - '@esbuild/freebsd-arm64': 0.18.20 - '@esbuild/freebsd-x64': 0.18.20 - '@esbuild/linux-arm': 0.18.20 - '@esbuild/linux-arm64': 0.18.20 - '@esbuild/linux-ia32': 0.18.20 - '@esbuild/linux-loong64': 0.18.20 - '@esbuild/linux-mips64el': 0.18.20 - '@esbuild/linux-ppc64': 0.18.20 - '@esbuild/linux-riscv64': 0.18.20 - '@esbuild/linux-s390x': 0.18.20 - '@esbuild/linux-x64': 0.18.20 - '@esbuild/netbsd-x64': 0.18.20 - '@esbuild/openbsd-x64': 0.18.20 - '@esbuild/sunos-x64': 0.18.20 - '@esbuild/win32-arm64': 0.18.20 - '@esbuild/win32-ia32': 0.18.20 - '@esbuild/win32-x64': 0.18.20 - esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -13995,8 +11874,6 @@ snapshots: transitivePeerDependencies: - supports-color - esm@3.2.25: {} - espree@10.4.0: dependencies: acorn: 8.15.0 @@ -14037,24 +11914,10 @@ snapshots: event-target-shim@5.0.1: {} - eventemitter3@4.0.7: {} - eventemitter3@5.0.4: {} events@3.3.0: {} - execa@7.2.0: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 4.3.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 - expand-template@2.0.3: {} expect-type@1.3.0: {} @@ -14175,8 +12038,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - filter-obj@1.1.0: {} - find-my-way@8.2.2: dependencies: fast-deep-equal: 3.1.3 @@ -14217,8 +12078,6 @@ snapshots: flatted: 3.3.3 keyv: 4.5.4 - flat@6.0.1: {} - flatted@3.3.3: {} follow-redirects@1.15.11: {} @@ -14280,18 +12139,6 @@ snapshots: fs-constants@1.0.0: {} - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs-extra@11.2.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - fs-extra@11.3.3: dependencies: graceful-fs: 4.2.11 @@ -14310,8 +12157,6 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 - fs.realpath@1.0.0: {} - fsevents@2.3.2: optional: true @@ -14357,15 +12202,11 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 - get-package-type@0.1.0: {} - get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - get-stream@6.0.1: {} - get-stream@9.0.1: dependencies: '@sec-ant/readable-stream': 0.4.1 @@ -14381,8 +12222,6 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 - getopts@2.3.0: {} - git-raw-commits@4.0.0: dependencies: dargs: 8.1.0 @@ -14410,14 +12249,6 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - global-directory@4.0.1: dependencies: ini: 4.1.1 @@ -14526,8 +12357,6 @@ snapshots: dependencies: hermes-estree: 0.25.1 - hookable@5.5.3: {} - hsl-to-hex@1.0.0: dependencies: hsl-to-rgb-for-reals: 1.1.1 @@ -14610,8 +12439,6 @@ snapshots: human-id@4.1.3: {} - human-signals@4.3.1: {} - humanize-ms@1.2.1: dependencies: ms: 2.1.3 @@ -14632,10 +12459,6 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - icu-minify@4.8.2: dependencies: '@formatjs/icu-messageformat-parser': 3.5.1 @@ -14681,11 +12504,6 @@ snapshots: indent-string@5.0.0: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} ini@1.3.8: {} @@ -14789,8 +12607,6 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 - interpret@2.2.0: {} - intl-messageformat@11.1.2: dependencies: '@formatjs/ecma402-abstract': 3.1.1 @@ -14835,10 +12651,6 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-builtin-module@3.2.1: - dependencies: - builtin-modules: 3.3.0 - is-bun-module@2.0.0: dependencies: semver: 7.7.4 @@ -14890,12 +12702,8 @@ snapshots: is-interactive@1.0.0: {} - is-interactive@2.0.0: {} - is-map@2.0.3: {} - is-module@1.0.0: {} - is-negative-zero@2.0.3: {} is-number-object@1.1.1: @@ -14928,8 +12736,6 @@ snapshots: dependencies: call-bound: 1.0.4 - is-stream@3.0.0: {} - is-stream@4.0.1: {} is-string@1.1.1: @@ -14953,8 +12759,6 @@ snapshots: is-unicode-supported@0.1.0: {} - is-unicode-supported@1.3.0: {} - is-unicode-supported@2.1.0: {} is-url@1.2.4: {} @@ -15005,14 +12809,6 @@ snapshots: jiti@2.6.1: {} - joi@17.12.2: - dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.5 - '@sideway/formula': 3.0.1 - '@sideway/pinpoint': 2.0.0 - joycon@3.1.1: {} jquery@3.7.1: {} @@ -15026,10 +12822,6 @@ snapshots: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -15115,8 +12907,6 @@ snapshots: json5@2.2.3: {} - jsonc-parser@3.3.1: {} - jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 @@ -15144,25 +12934,6 @@ snapshots: kleur@3.0.3: {} - knex@3.1.0: - dependencies: - colorette: 2.0.19 - commander: 10.0.1 - debug: 4.3.4 - escalade: 3.2.0 - esm: 3.2.25 - get-package-type: 0.1.0 - getopts: 2.3.0 - interpret: 2.2.0 - lodash: 4.17.23 - pg-connection-string: 2.6.2 - rechoir: 0.8.0 - resolve-from: 5.0.0 - tarn: 3.0.2 - tildify: 2.0.0 - transitivePeerDependencies: - - supports-color - language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -15232,8 +13003,6 @@ snapshots: lightningcss-win32-x64-msvc: 1.30.2 optional: true - lilconfig@2.1.0: {} - lilconfig@3.1.3: {} linebreak@1.1.0: @@ -15284,16 +13053,12 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash-es@4.17.21: {} - lodash.camelcase@4.3.0: {} lodash.isequal@4.5.0: {} lodash.kebabcase@4.1.1: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} lodash.mergewith@4.6.2: {} @@ -15302,8 +13067,6 @@ snapshots: lodash.startcase@4.4.0: {} - lodash.uniq@4.5.0: {} - lodash.upperfirst@4.3.1: {} lodash@4.17.23: {} @@ -15313,11 +13076,6 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-symbols@5.1.0: - dependencies: - chalk: 5.6.2 - is-unicode-supported: 1.3.0 - log-update@6.1.0: dependencies: ansi-escapes: 7.3.0 @@ -15373,8 +13131,6 @@ snapshots: marked: 7.0.4 react: 19.2.4 - mdn-data@2.0.14: {} - mdn-data@2.12.2: {} media-engine@1.0.3: {} @@ -15392,8 +13148,6 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - micromustache@8.0.3: {} - mime-db@1.52.0: {} mime-types@2.1.35: @@ -15402,8 +13156,6 @@ snapshots: mimic-fn@2.1.0: {} - mimic-fn@4.0.0: {} - mimic-function@5.0.1: {} mimic-response@3.1.0: {} @@ -15416,10 +13168,6 @@ snapshots: dependencies: brace-expansion: 1.1.12 - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.2 - minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 @@ -15473,8 +13221,6 @@ snapshots: mrmime@2.0.1: optional: true - ms@2.1.2: {} - ms@2.1.3: {} mute-stream@0.0.8: {} @@ -15491,8 +13237,6 @@ snapshots: nanoid@3.3.11: {} - nanoid@5.0.6: {} - napi-build-utils@2.0.0: {} napi-postinstall@0.3.4: {} @@ -15572,14 +13316,8 @@ snapshots: dependencies: svg-arc-to-cubic-bezier: 3.2.0 - normalize-url@6.1.0: {} - normalize-url@8.1.1: {} - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -15642,10 +13380,6 @@ snapshots: dependencies: mimic-fn: 2.1.0 - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - onetime@7.0.0: dependencies: mimic-function: 5.0.1 @@ -15686,18 +13420,6 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 - ora@6.3.1: - dependencies: - chalk: 5.6.2 - cli-cursor: 4.0.0 - cli-spinners: 2.9.2 - is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - stdin-discarder: 0.1.0 - strip-ansi: 7.1.2 - wcwidth: 1.0.1 - os-tmpdir@1.0.2: {} outdent@0.5.0: {} @@ -15730,8 +13452,6 @@ snapshots: dependencies: p-map: 2.1.0 - p-finally@1.0.0: {} - p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -15750,15 +13470,6 @@ snapshots: p-map@2.1.0: {} - p-queue@6.6.2: - dependencies: - eventemitter3: 4.0.7 - p-timeout: 3.2.0 - - p-timeout@3.2.0: - dependencies: - p-finally: 1.0.0 - p-try@2.2.0: {} package-json-from-dist@1.0.1: {} @@ -15767,8 +13478,6 @@ snapshots: dependencies: quansync: 0.2.11 - packrup@0.1.2: {} - pako@0.2.9: {} pako@1.0.11: {} @@ -15816,8 +13525,6 @@ snapshots: path-key@3.1.1: {} - path-key@4.0.0: {} - path-parse@1.0.7: {} path-scurry@1.11.1: @@ -15839,8 +13546,6 @@ snapshots: peberminta@0.9.0: {} - pg-connection-string@2.6.2: {} - pg-int8@1.0.1: {} pg-protocol@1.11.0: {} @@ -15865,26 +13570,6 @@ snapshots: pify@4.0.1: {} - pinia@2.3.1(typescript@5.9.3)(vue@3.4.21(typescript@5.9.3)): - dependencies: - '@vue/devtools-api': 6.6.4 - vue: 3.4.21(typescript@5.9.3) - vue-demi: 0.14.10(vue@3.4.21(typescript@5.9.3)) - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - '@vue/composition-api' - - pinia@2.3.1(typescript@5.9.3)(vue@3.5.28(typescript@5.9.3)): - dependencies: - '@vue/devtools-api': 6.6.4 - vue: 3.5.28(typescript@5.9.3) - vue-demi: 0.14.10(vue@3.5.28(typescript@5.9.3)) - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - '@vue/composition-api' - pino-abstract-transport@2.0.0: dependencies: split2: 4.2.0 @@ -15963,42 +13648,6 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-calc@8.2.4(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - postcss-value-parser: 4.2.0 - - postcss-colormin@5.3.1(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-api: 3.0.0 - colord: 2.9.3 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-convert-values@5.1.3(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-discard-comments@5.1.2(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-duplicates@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-empty@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-discard-overridden@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-import@15.1.0(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -16029,133 +13678,11 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - postcss-merge-longhand@5.1.7(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - stylehacks: 5.1.1(postcss@8.5.6) - - postcss-merge-rules@5.1.4(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-api: 3.0.0 - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-minify-font-values@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-gradients@5.1.1(postcss@8.5.6): - dependencies: - colord: 2.9.3 - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-params@5.1.4(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-minify-selectors@5.2.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-modules-extract-imports@3.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-modules-local-by-default@4.2.0(postcss@8.5.6): - dependencies: - icss-utils: 5.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - postcss-value-parser: 4.2.0 - - postcss-modules-scope@3.2.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 7.1.1 - - postcss-modules-values@4.0.0(postcss@8.5.6): - dependencies: - icss-utils: 5.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-nested@6.2.0(postcss@8.5.6): dependencies: postcss: 8.5.6 postcss-selector-parser: 6.1.2 - postcss-normalize-charset@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - - postcss-normalize-display-values@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-positions@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-repeat-style@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-string@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-timing-functions@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-unicode@5.1.1(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-url@5.1.0(postcss@8.5.6): - dependencies: - normalize-url: 6.1.0 - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-normalize-whitespace@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-ordered-values@5.1.3(postcss@8.5.6): - dependencies: - cssnano-utils: 3.1.0(postcss@8.5.6) - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - - postcss-reduce-initial@5.1.2(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - caniuse-api: 3.0.0 - postcss: 8.5.6 - - postcss-reduce-transforms@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - postcss-selector-parser@6.0.10: dependencies: cssesc: 3.0.0 @@ -16166,22 +13693,6 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-selector-parser@7.1.1: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-svgo@5.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - svgo: 2.8.0 - - postcss-unique-selectors@5.1.1(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - postcss-value-parser@4.2.0: {} postcss@8.4.31: @@ -16287,13 +13798,6 @@ snapshots: quansync@0.2.11: {} - query-string@7.1.3: - dependencies: - decode-uri-component: 0.2.2 - filter-obj: 1.1.0 - split-on-first: 1.1.0 - strict-uri-encode: 2.0.0 - queue-microtask@1.2.3: {} queue@6.0.2: @@ -16378,10 +13882,6 @@ snapshots: real-require@0.2.0: {} - rechoir@0.8.0: - dependencies: - resolve: 1.22.11 - redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -16479,44 +13979,6 @@ snapshots: robots-parser@3.0.1: {} - rollup-plugin-esbuild@5.0.0(esbuild@0.17.19)(rollup@3.29.4): - dependencies: - '@rollup/pluginutils': 5.3.0(rollup@3.29.4) - debug: 4.4.3 - es-module-lexer: 1.7.0 - esbuild: 0.17.19 - joycon: 3.1.1 - jsonc-parser: 3.3.1 - rollup: 3.29.4 - transitivePeerDependencies: - - supports-color - - rollup-plugin-styles@4.0.0(rollup@3.29.4): - dependencies: - '@rollup/pluginutils': 4.2.1 - '@types/cssnano': 5.1.3(postcss@8.5.6) - cosmiconfig: 7.1.0 - cssnano: 5.1.15(postcss@8.5.6) - fs-extra: 10.1.0 - icss-utils: 5.1.0(postcss@8.5.6) - mime-types: 2.1.35 - p-queue: 6.6.2 - postcss: 8.5.6 - postcss-modules-extract-imports: 3.1.0(postcss@8.5.6) - postcss-modules-local-by-default: 4.2.0(postcss@8.5.6) - postcss-modules-scope: 3.2.1(postcss@8.5.6) - postcss-modules-values: 4.0.0(postcss@8.5.6) - postcss-value-parser: 4.2.0 - query-string: 7.1.3 - resolve: 1.22.11 - rollup: 3.29.4 - source-map-js: 1.2.1 - tslib: 2.8.1 - - rollup@3.29.4: - optionalDependencies: - fsevents: 2.3.3 - rollup@4.57.1: dependencies: '@types/estree': 1.0.8 @@ -16796,8 +14258,6 @@ snapshots: smart-buffer@4.2.0: {} - smob@1.5.0: {} - socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 @@ -16831,8 +14291,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - split-on-first@1.1.0: {} - split2@4.2.0: {} split@0.3.3: @@ -16843,8 +14301,6 @@ snapshots: stable-hash@0.0.5: {} - stable@0.1.8: {} - stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 @@ -16857,10 +14313,6 @@ snapshots: std-env@3.10.0: {} - stdin-discarder@0.1.0: - dependencies: - bl: 5.1.0 - stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -16876,8 +14328,6 @@ snapshots: dependencies: stream-chain: 2.2.5 - strict-uri-encode@2.0.0: {} - string-argv@0.3.2: {} string-comparison@1.3.0: {} @@ -16973,8 +14423,6 @@ snapshots: strip-bom@3.0.0: {} - strip-final-newline@3.0.0: {} - strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -17000,12 +14448,6 @@ snapshots: optionalDependencies: '@babel/core': 7.29.0 - stylehacks@5.1.1(postcss@8.5.6): - dependencies: - browserslist: 4.28.1 - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - sucrase@3.35.1: dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -17030,16 +14472,6 @@ snapshots: svg-arc-to-cubic-bezier@3.2.0: {} - svgo@2.8.0: - dependencies: - '@trysound/sax': 0.2.0 - commander: 7.2.0 - css-select: 4.3.0 - css-tree: 1.1.3 - csso: 4.2.0 - picocolors: 1.1.1 - stable: 0.1.8 - symbol-tree@3.2.4: {} tailwind-merge@2.6.1: {} @@ -17089,8 +14521,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - tarn@3.0.2: {} - term-size@2.2.1: {} terser-webpack-plugin@5.3.16(@swc/core@1.15.11(@swc/helpers@0.5.18))(webpack@5.105.0(@swc/core@1.15.11(@swc/helpers@0.5.18))): @@ -17142,8 +14572,6 @@ snapshots: through@2.3.8: {} - tildify@2.0.0: {} - tiny-inflate@1.0.3: {} tiny-typed-emitter@2.1.0: {} @@ -17356,13 +14784,6 @@ snapshots: undici@7.21.0: {} - unhead@1.11.20: - dependencies: - '@unhead/dom': 1.11.20 - '@unhead/schema': 1.11.20 - '@unhead/shared': 1.11.20 - hookable: 5.5.3 - unicode-properties@1.4.1: dependencies: base64-js: 1.5.1 @@ -17496,18 +14917,6 @@ snapshots: - supports-color - terser - vite@4.5.2(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): - dependencies: - esbuild: 0.18.20 - postcss: 8.5.6 - rollup: 3.29.4 - optionalDependencies: - '@types/node': 22.19.10 - fsevents: 2.3.3 - lightningcss: 1.30.2 - sass: 1.97.3 - terser: 5.46.0 - vite@5.4.21(@types/node@20.19.33)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): dependencies: esbuild: 0.21.5 @@ -17550,7 +14959,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 - vitest@2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): + vitest@2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): dependencies: '@vitest/expect': 2.1.9 '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)) @@ -17588,7 +14997,7 @@ snapshots: - supports-color - terser - vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 @@ -17630,7 +15039,7 @@ snapshots: - supports-color - terser - vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 @@ -17713,34 +15122,6 @@ snapshots: - tsx - yaml - vue-demi@0.14.10(vue@3.4.21(typescript@5.9.3)): - dependencies: - vue: 3.4.21(typescript@5.9.3) - - vue-demi@0.14.10(vue@3.5.28(typescript@5.9.3)): - dependencies: - vue: 3.5.28(typescript@5.9.3) - - vue@3.4.21(typescript@5.9.3): - dependencies: - '@vue/compiler-dom': 3.4.21 - '@vue/compiler-sfc': 3.4.21 - '@vue/runtime-dom': 3.4.21 - '@vue/server-renderer': 3.4.21(vue@3.4.21(typescript@5.9.3)) - '@vue/shared': 3.4.21 - optionalDependencies: - typescript: 5.9.3 - - vue@3.5.28(typescript@5.9.3): - dependencies: - '@vue/compiler-dom': 3.5.28 - '@vue/compiler-sfc': 3.5.28 - '@vue/runtime-dom': 3.5.28 - '@vue/server-renderer': 3.5.28(vue@3.5.28(typescript@5.9.3)) - '@vue/shared': 3.5.28 - optionalDependencies: - typescript: 5.9.3 - w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -17949,8 +15330,6 @@ snapshots: yallist@3.1.1: {} - yaml@1.10.2: {} - yaml@2.8.2: {} yargonaut@1.1.4: @@ -17987,12 +15366,8 @@ snapshots: yoga-layout@3.2.1: {} - zhead@2.2.4: {} - zod-validation-error@4.0.2(zod@3.25.76): dependencies: zod: 3.25.76 - zod@3.22.4: {} - zod@3.25.76: {} diff --git a/scripts/cms-apply.sh b/scripts/cms-apply.sh deleted file mode 100755 index 7be4de2..0000000 --- a/scripts/cms-apply.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/bash - -# Configuration -PROJECT="infra-cms" -LOCAL_SCHEMA_PATH="./packages/cms-infra/schema/snapshot.yaml" -REMOTE_HOST="root@infra.mintel.me" -REMOTE_DIR="/opt/infra/directus" - -ENV=$1 - -if [ -z "$ENV" ]; then - echo "Usage: ./scripts/cms-apply.sh [local|infra]" - exit 1 -fi - -case $ENV in - local) - PROJECT="infra-cms" - # Derive monorepo root - SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - ROOT_DIR="$( dirname "$SCRIPT_DIR" )" - CMD_PREFIX="docker compose -f $ROOT_DIR/packages/cms-infra/docker-compose.yml" - - LOCAL_CONTAINER=$($CMD_PREFIX ps -q $PROJECT) - if [ -z "$LOCAL_CONTAINER" ]; then - echo "❌ Local $PROJECT container not found. Is it running?" - exit 1 - fi - - echo "🧹 Reconciling database metadata..." - ./scripts/cms-reconcile.sh - - echo "🚀 Applying schema to LOCAL $PROJECT..." - docker exec "$LOCAL_CONTAINER" npx directus schema apply -y /directus/schema/snapshot.yaml - ;; - infra) - # 'infra' is the remote production server for at-mintel - PROJECT="directus" # Remote project name - - echo "🔍 Detecting remote container..." - REMOTE_CONTAINER=$(ssh "$REMOTE_HOST" "docker ps --filter label=com.docker.compose.project=$PROJECT --filter label=com.docker.compose.service=directus -q") - - if [ -z "$REMOTE_CONTAINER" ]; then - # Fallback to older name if labels fail - REMOTE_CONTAINER=$(ssh "$REMOTE_HOST" "docker ps -f name=directus-directus-1 -q") - fi - - if [ -z "$REMOTE_CONTAINER" ]; then - echo "❌ Remote container for $ENV not found." - exit 1 - fi - - echo "📦 Syncing extensions to REMOTE $ENV..." - # Ensure remote directory exists - ssh "$REMOTE_HOST" "mkdir -p $REMOTE_DIR/extensions" - rsync -avz --delete ./packages/cms-infra/extensions/ "$REMOTE_HOST:$REMOTE_DIR/extensions/" - - echo "📤 Injecting snapshot directly into container $REMOTE_CONTAINER..." - # Inject file via stdin to avoid needing a host-side mount or scp path matching - ssh "$REMOTE_HOST" "docker exec -i $REMOTE_CONTAINER sh -c 'cat > /tmp/snapshot.yaml'" < "$LOCAL_SCHEMA_PATH" - - echo "🚀 Applying schema to REMOTE $ENV..." - ssh "$REMOTE_HOST" "docker exec $REMOTE_CONTAINER npx directus schema apply -y /tmp/snapshot.yaml" - - echo "🔄 Restarting remote Directus to clear cache..." - ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose restart directus" - - # Cleanup - ssh "$REMOTE_HOST" "docker exec $REMOTE_CONTAINER rm /tmp/snapshot.yaml" - ;; - *) - echo "❌ Invalid environment: $ENV. Supported: local, infra." - exit 1 - ;; -esac - -echo "✨ Schema apply complete!" diff --git a/scripts/cms-reconcile.sh b/scripts/cms-reconcile.sh deleted file mode 100755 index e869f9d..0000000 --- a/scripts/cms-reconcile.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -# Configuration -# Derive monorepo root -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -ROOT_DIR="$( dirname "$SCRIPT_DIR" )" -DB_PATH="$ROOT_DIR/packages/cms-infra/database/data.db" - -if [ ! -f "$DB_PATH" ]; then - echo "❌ Database not found at $DB_PATH" - exit 1 -fi - -reconcile_table() { - local TABLE=$1 - echo "🔍 Reconciling table: $TABLE" - - # 1. Get all columns from SQLite - COLUMNS=$(sqlite3 "$DB_PATH" "PRAGMA table_info($TABLE);" | cut -d'|' -f2) - - for COL in $COLUMNS; do - # Skip system columns if needed, but usually it's safer to just check if they exist in Directus - - # 2. Check if field exists in directus_fields - EXISTS=$(sqlite3 "$DB_PATH" "SELECT count(*) FROM directus_fields WHERE collection = '$TABLE' AND field = '$COL';") - - if [ "$EXISTS" -eq 0 ]; then - echo "➕ Registering missing field: $TABLE.$COL" - - # Determine a basic interface based on column name or type (very simplified) - INTERFACE="input" - case $COL in - *id) INTERFACE="numeric" ;; - *text) INTERFACE="input-multiline" ;; - company|person|user_created|user_updated|feedback_id) INTERFACE="select-dropdown-m2o" ;; - date_created|date_updated) INTERFACE="datetime" ;; - screenshot|logo) INTERFACE="file" ;; - status|type) INTERFACE="select-dropdown" ;; - esac - - sqlite3 "$DB_PATH" "INSERT INTO directus_fields (collection, field, interface) VALUES ('$TABLE', '$COL', '$INTERFACE');" - else - echo "✅ Field already registered: $TABLE.$COL" - fi - done -} - -# Run for known problematic tables -reconcile_table "visual_feedback" -reconcile_table "visual_feedback_comments" -reconcile_table "people" -reconcile_table "leads" -reconcile_table "client_users" -reconcile_table "companies" - -echo "✨ SQL Reconciliation complete!" diff --git a/scripts/cms-snapshot.sh b/scripts/cms-snapshot.sh deleted file mode 100755 index 934664d..0000000 --- a/scripts/cms-snapshot.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# Configuration -PROJECT="infra-cms" -SCHEMA_PATH="./packages/cms-infra/schema/snapshot.yaml" -CMD_PREFIX="docker-compose -f packages/cms-infra/docker-compose.yml" - -# Detect local container -LOCAL_CONTAINER=$($CMD_PREFIX ps -q $PROJECT) - -if [ -z "$LOCAL_CONTAINER" ]; then - echo "❌ Local $PROJECT container not found. Is it running?" - exit 1 -fi - -echo "📸 Creating schema snapshot for local $PROJECT..." -# Note: we save it to the mounted volume path inside the container -docker exec "$LOCAL_CONTAINER" npx directus schema snapshot -y /directus/schema/snapshot.yaml - -echo "🛠️ Repairing snapshot for Postgres compatibility..." -python3 ./scripts/fix_snapshot_v3.py - -echo "✅ Snapshot saved and repaired at $SCHEMA_PATH" diff --git a/scripts/cms-up.sh b/scripts/cms-up.sh deleted file mode 100755 index 73dc05f..0000000 --- a/scripts/cms-up.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# Configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -echo "🚀 Starting CMS infrastructure..." - -# 1. Build extensions (pass all arguments to handle flags like --link) -"$SCRIPT_DIR/sync-extensions.sh" "$@" - -# Filter out --link before passing to docker compose -DOCKER_ARGS=() -for arg in "$@"; do - if [ "$arg" != "--link" ]; then - DOCKER_ARGS+=("$arg") - fi -done - -# 2. Docker compose up with arguments -cd "$REPO_ROOT/packages/cms-infra" -docker compose up -d "${DOCKER_ARGS[@]}" - -# 3. Apply core patch -"$SCRIPT_DIR/patch-cms.sh" - -echo "✨ CMS is up and patched!" diff --git a/scripts/fix_snapshot_v3.py b/scripts/fix_snapshot_v3.py deleted file mode 100644 index bb42cb5..0000000 --- a/scripts/fix_snapshot_v3.py +++ /dev/null @@ -1,96 +0,0 @@ -import sys -import os - -path = '/Users/marcmintel/Projects/at-mintel/packages/cms-infra/schema/snapshot.yaml' -if not os.path.exists(path): - print(f"File not found: {path}") - sys.exit(1) - -with open(path, 'r') as f: - lines = f.readlines() - -new_lines = [] -current_collection = None -current_field = None -in_schema = False - -fix_fields = {'id', 'company', 'user_created', 'user_updated', 'screenshot', 'logo', 'feedback_id'} -uuid_fields = {'id', 'company', 'user_created', 'user_updated'} - -# For multi-pass logic -snapshot_has_feedback_id = False - -for line in lines: - stripped = line.strip() - - if stripped.startswith('- collection:'): - current_collection = stripped.split(':')[-1].strip() - in_schema = False - elif stripped.startswith('field:'): - current_field = stripped.split(':')[-1].strip() - if current_collection == 'visual_feedback_comments' and current_field == 'feedback_id': - snapshot_has_feedback_id = True - elif stripped == 'schema:': - in_schema = True - elif stripped == 'meta:' or stripped.startswith('- collection:') or (not line.startswith(' ') and line.strip() and not line.startswith('-')): - in_schema = False - - # Top-level field type - if not in_schema and stripped.startswith('type:') and current_field in uuid_fields: - line = line.replace('type: string', 'type: uuid') - - # Schema data type - if in_schema and current_field in fix_fields: - if 'data_type: char' in line or 'data_type: varchar' in line: - line = line.replace('data_type: char', 'data_type: uuid').replace('data_type: varchar', 'data_type: uuid') - if 'max_length:' in line: - line = ' max_length: null\n' - - new_lines.append(line) - -# Handle Missing feedback_id Injection -if not snapshot_has_feedback_id: - # We find systemFields and inject before it - injected = False - final_lines = [] - feedback_id_block = """ - collection: visual_feedback_comments - field: feedback_id - type: integer - meta: - collection: visual_feedback_comments - field: feedback_id - interface: select-dropdown-m2o - required: true - sort: 4 - width: full - schema: - name: feedback_id - table: visual_feedback_comments - data_type: integer - is_nullable: false - is_indexed: true - foreign_key_table: visual_feedback - foreign_key_column: id -""" - for line in new_lines: - if 'systemFields:' in line and not injected: - final_lines.append(feedback_id_block) - injected = True - final_lines.append(line) - new_lines = final_lines - -# Second pass for primary key nullability -final_lines = [] -for i in range(len(new_lines)): - line = new_lines[i] - if 'is_primary_key: true' in line: - # Search backwards and forwards - for j in range(max(0, i-10), min(len(new_lines), i+10)): - if 'is_nullable: true' in new_lines[j]: - new_lines[j] = new_lines[j].replace('is_nullable: true', 'is_nullable: false') - final_lines.append(line) - -with open(path, 'w') as f: - f.writelines(new_lines) - -print("SUCCESS: Full normalization and field injection complete.") diff --git a/scripts/patch-cms.sh b/scripts/patch-cms.sh deleted file mode 100755 index 8b36e9c..0000000 --- a/scripts/patch-cms.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# Configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -CONTAINERS=("cms-infra-infra-cms-1" "at-mintel-directus-1") - -echo "🔧 Checking for Directus containers to patch..." - -for CONTAINER in "${CONTAINERS[@]}"; do - if [ "$(docker ps -q -f name=^/${CONTAINER}$)" ]; then - echo "🔧 Applying core patches to: $CONTAINER..." - - # Capture output to determine if restart is needed - OUTPUT=$(docker exec -i "$CONTAINER" node << 'EOF' - const fs = require("node:fs"); - const { execSync } = require("node:child_process"); - let patched = false; - - try { - // 1. Patch @directus/extensions node.js (Entrypoints) - const findNodeCmd = "find /directus/node_modules -path \"*/@directus/extensions/dist/node.js\""; - const nodePaths = execSync(findNodeCmd).toString().trim().split("\n").filter(Boolean); - - nodePaths.forEach(targetPath => { - let content = fs.readFileSync(targetPath, "utf8"); - let modified = false; - - const filterPatch = 'extension.host === "app" && (extension.entrypoint.app || extension.entrypoint)'; - - // Only replace if the OLD pattern exists - if (content.includes('extension.host === "app" && !!extension.entrypoint.app')) { - content = content.replace(/extension\.host === "app" && !!extension\.entrypoint\.app/g, filterPatch); - modified = true; - } - - // Only replace if the OLD pattern exists for entrypoint - // We check if "extension.entrypoint.app" is present but NOT part of our patch - // This is a simple heuristic: if the patch string is NOT present, but the target IS. - if (!content.includes("(extension.entrypoint.app || extension.entrypoint)")) { - if (content.includes("extension.entrypoint.app")) { - content = content.replace(/extension\.entrypoint\.app/g, "(extension.entrypoint.app || extension.entrypoint)"); - modified = true; - } - } - - if (modified) { - fs.writeFileSync(targetPath, content); - console.log(`✅ Entrypoint patched.`); - patched = true; - } - }); - - // 2. Patch @directus/api manager.js (HTML Injection) - const findManagerCmd = "find /directus/node_modules -path \"*/@directus/api/dist/extensions/manager.js\""; - const managerPaths = execSync(findManagerCmd).toString().trim().split("\n").filter(Boolean); - - managerPaths.forEach(targetPath => { - let content = fs.readFileSync(targetPath, "utf8"); - - const original = "head: wrapEmbeds('Custom Embed Head', this.hookEmbedsHead),"; - const injection = "head: '\\n' + wrapEmbeds('Custom Embed Head', this.hookEmbedsHead),"; - - if (content.includes(original) && !content.includes("/extensions/sources/index.js")) { - content = content.replace(original, injection); - fs.writeFileSync(targetPath, content); - console.log(`✅ Injection patched.`); - patched = true; - } - }); - - // 3. Patch @directus/api app.js (CSP for unsafe-inline) - const findAppCmd = "find /directus/node_modules -path \"*/@directus/api/dist/app.js\""; - const appPaths = execSync(findAppCmd).toString().trim().split("\n").filter(Boolean); - - appPaths.forEach(targetPath => { - let content = fs.readFileSync(targetPath, "utf8"); - let modified = false; - - const original = "scriptSrc: [\"'self'\", \"'unsafe-eval'\"],"; - const patchedStr = "scriptSrc: [\"'self'\", \"'unsafe-eval'\", \"'unsafe-inline'\"],"; - - if (content.includes(original)) { - content = content.replace(original, patchedStr); - modified = true; - } - - if (modified) { - fs.writeFileSync(targetPath, content); - console.log(`✅ CSP patched in app.js.`); - patched = true; - } - }); - - if (patched) process.exit(100); // Signal restart needed - - } catch (error) { - console.error("❌ Error applying patch:", error.message); - process.exit(1); - } -EOF - ) - EXIT_CODE=$? - echo "$OUTPUT" - - if [ $EXIT_CODE -eq 100 ]; then - echo "🔄 Patches applied. Restarting Directus container: $CONTAINER..." - docker restart "$CONTAINER" - else - echo "✅ Container $CONTAINER is already patched. No restart needed." - fi - else - echo "ℹ️ Container $CONTAINER not found. Skipping." - fi -done - -echo "✨ All patches check complete." diff --git a/scripts/sync-directus.sh b/scripts/sync-directus.sh deleted file mode 100755 index c788cd3..0000000 --- a/scripts/sync-directus.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash - -# Configuration -REMOTE_HOST="root@infra.mintel.me" -REMOTE_DIR="/opt/infra/directus" - -# DB Details (matching docker-compose defaults) -DB_USER="directus" -DB_NAME="directus" - -ACTION=$1 -ENV=$2 - -# Help -if [ -z "$ACTION" ] || [ -z "$ENV" ]; then - echo "Usage: ./scripts/sync-directus.sh [push|pull] [infra|testing|staging|production]" - echo "" - echo "Commands:" - echo " push Sync LOCAL data -> REMOTE" - echo " pull Sync REMOTE data -> LOCAL" - echo "" - echo "Environments:" - echo " infra (infra.mintel.me)" - exit 1 -fi - -# Map Environment -case $ENV in - infra) - PROJECT_NAME="directus" - ;; - *) - echo "❌ Invalid environment: $ENV. Only 'infra' is currently configured for monorepo sync." - exit 1 - ;; -esac - -# Detect local containers -echo "🔍 Detecting local database..." -LOCAL_DB_CONTAINER=$(docker compose ps -q at-mintel-directus-db) -if [ -z "$LOCAL_DB_CONTAINER" ]; then - echo "❌ Local directus-db container not found. Is it running? (npm run dev)" - exit 1 -fi - -if [ "$ACTION" == "push" ]; then - echo "🚀 Pushing Local Data to $ENV..." - - # 1. DB Dump - echo "📦 Dumping local database..." - docker exec "$LOCAL_DB_CONTAINER" pg_dump -U "$DB_USER" --clean --if-exists --no-owner --no-privileges "$DB_NAME" > dump.sql - - # 2. Upload Dump - echo "📤 Uploading dump to remote server..." - scp dump.sql "$REMOTE_HOST:$REMOTE_DIR/dump.sql" - - # 3. Restore on Remote - echo "🔄 Restoring dump on $ENV..." - REMOTE_DB_CONTAINER=$(ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose -p $PROJECT_NAME ps -q directus-postgres") - - if [ -z "$REMOTE_DB_CONTAINER" ]; then - echo "❌ Remote $ENV-db container not found!" - exit 1 - fi - - # Wipe remote DB clean before restore to avoid constraint errors - echo "🧹 Wiping remote database schema..." - ssh "$REMOTE_HOST" "docker exec $REMOTE_DB_CONTAINER psql -U $DB_USER $DB_NAME -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'" - - echo "⚡ Restoring database..." - ssh "$REMOTE_HOST" "docker exec -i $REMOTE_DB_CONTAINER psql -U $DB_USER $DB_NAME < $REMOTE_DIR/dump.sql" - - # 4. Sync Uploads - echo "📁 Syncing uploads (Local -> $ENV)..." - rsync -avz --progress ./directus/uploads/ "$REMOTE_HOST:$REMOTE_DIR/uploads/" - - # Clean up - rm dump.sql - ssh "$REMOTE_HOST" "rm $REMOTE_DIR/dump.sql" - - # 5. Restart Directus to trigger migrations and refresh schema cache - echo "🔄 Restarting remote Directus to apply migrations..." - ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose -p $PROJECT_NAME restart directus" - - echo "✨ Push to $ENV complete!" - -elif [ "$ACTION" == "pull" ]; then - echo "📥 Pulling $ENV Data to Local..." - - # 1. DB Dump on Remote - echo "📦 Dumping remote database ($ENV)..." - REMOTE_DB_CONTAINER=$(ssh "$REMOTE_HOST" "cd $REMOTE_DIR && docker compose -p $PROJECT_NAME ps -q directus-postgres") - - if [ -z "$REMOTE_DB_CONTAINER" ]; then - echo "❌ Remote $ENV-db container not found!" - exit 1 - fi - ssh "$REMOTE_HOST" "docker exec $REMOTE_DB_CONTAINER pg_dump -U $DB_USER --clean --if-exists --no-owner --no-privileges $DB_NAME > $REMOTE_DIR/dump.sql" - - # 2. Download Dump - echo "📥 Downloading dump..." - scp "$REMOTE_HOST:$REMOTE_DIR/dump.sql" dump.sql - - # Wipe local DB clean before restore to avoid constraint errors - echo "🧹 Wiping local database schema..." - docker exec "$LOCAL_DB_CONTAINER" psql -U "$DB_USER" "$DB_NAME" -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;' - - echo "⚡ Restoring database locally..." - docker exec -i "$LOCAL_DB_CONTAINER" psql -U "$DB_USER" "$DB_NAME" < dump.sql - - # 4. Sync Uploads - echo "📁 Syncing uploads ($ENV -> Local)..." - rsync -avz --progress "$REMOTE_HOST:$REMOTE_DIR/uploads/" ./directus/uploads/ - - # Clean up - rm dump.sql - ssh "$REMOTE_HOST" "rm $REMOTE_DIR/dump.sql" - - echo "✨ Pull to Local complete!" -else - echo "Invalid action: $ACTION. Use push or pull." - exit 1 -fi diff --git a/scripts/sync-extensions.sh b/scripts/sync-extensions.sh deleted file mode 100755 index 1833482..0000000 --- a/scripts/sync-extensions.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/bash - -# Configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -EXTENSIONS_ROOT="$REPO_ROOT/packages" - -# Strict local targets for bombproof isolation -TARGET_DIRS=( - "$REPO_ROOT/packages/cms-infra/extensions" - "$REPO_ROOT/directus/extensions" -) - -# List of extension packages to sync -EXTENSION_PACKAGES=( - "acquisition" - "acquisition-manager" - "company-manager" - "customer-manager" - "feedback-commander" - "people-manager" - "unified-dashboard" -) - -# Parse flags -LINK_MODE=false -for arg in "$@"; do - if [ "$arg" == "--link" ]; then - LINK_MODE=true - fi -done - -echo "🚀 Starting isolated extension sync..." - -# Ensure target directories exist -for TARGET in "${TARGET_DIRS[@]}"; do - mkdir -p "$TARGET" -done - -# Build the acquisition library if it exists -if [ -d "$REPO_ROOT/packages/acquisition" ]; then - echo "📦 Building acquisition..." - (cd "$REPO_ROOT/packages/acquisition" && pnpm build) -fi - -for PKG in "${EXTENSION_PACKAGES[@]}"; do - PKG_PATH="$EXTENSIONS_ROOT/$PKG" - - if [ -d "$PKG_PATH" ]; then - echo "📦 Processing $PKG..." - - # 1. Build the extension - (cd "$PKG_PATH" && pnpm build) - - EXT_NAME="$PKG" - echo "🚚 Syncing $EXT_NAME..." - - # 3. Sync to each target directory - for TARGET_BASE in "${TARGET_DIRS[@]}"; do - # FLAT STRUCTURE: Directus 11.15.x local scanner is FLAT. - FINAL_TARGET="$TARGET_BASE/$EXT_NAME" - - echo "🚚 Syncing $EXT_NAME to $FINAL_TARGET..." - - # Clean target first to avoid ghost files - mkdir -p "$FINAL_TARGET" - rm -rf "${FINAL_TARGET:?}"/* - - # Copy build artifacts - if [ -f "$PKG_PATH/dist/index.js" ]; then - cp "$PKG_PATH/dist/index.js" "$FINAL_TARGET/index.js" - elif [ -f "$PKG_PATH/index.js" ]; then - cp "$PKG_PATH/index.js" "$FINAL_TARGET/index.js" - fi - - if [ -f "$PKG_PATH/package.json" ]; then - # We ALWAYS copy and patch package.json to avoid messing with source - cp "$PKG_PATH/package.json" "$FINAL_TARGET/" - # We force the registration path to index.js and ensure host/source are set - node -e " - const fs = require('fs'); - const pkgPath = '$FINAL_TARGET/package.json'; - const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); - if (!pkg['directus:extension']) pkg['directus:extension'] = {}; - - // Standard metadata for Directus 11.15.x (with core patch applied) - pkg['directus:extension'].path = 'index.js'; - if (!pkg['directus:extension'].host) { - pkg['directus:extension'].host = pkg['directus:extension'].type === 'endpoint' ? 'api' : 'app'; - } - if (!pkg['directus:extension'].source) { - pkg['directus:extension'].source = 'src/index.ts'; - } - - fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2)); - " - fi - - if [ -d "$PKG_PATH/dist" ]; then - if [ "$LINK_MODE" = true ]; then - REL_PATH=$(python3 -c "import os; print(os.path.relpath('$PKG_PATH/dist', '$FINAL_TARGET'))") - ln -sf "$REL_PATH" "$FINAL_TARGET/dist" - else - cp -r "$PKG_PATH/dist" "$FINAL_TARGET/" - fi - fi - done - - echo "✅ $PKG synced." - else - echo "❌ Extension source not found: $PKG_PATH" - fi -done - -# Cleanup: remove anything from extensions root that isn't in our whitelist -WHITELIST=("${EXTENSION_PACKAGES[@]}" "sources" "endpoints" "hooks" "layouts" "modules" "operations" "panels" "displays" "interfaces") - -for TARGET_BASE in "${TARGET_DIRS[@]}"; do - echo "🧹 Cleaning up $TARGET_BASE..." - for ITEM in "$TARGET_BASE"/*; do - [ -e "$ITEM" ] || continue - BN=$(basename "$ITEM") - IS_ALLOWED=false - for W in "${WHITELIST[@]}"; do - if [[ "$BN" == "$W" ]]; then IS_ALLOWED=true; break; fi - done - - if [ "$IS_ALLOWED" = false ]; then - echo " 🗑️ Removing extra/legacy item: $BN" - rm -rf "$ITEM" - fi - done -done - -# Container patching is now handled by scripts/patch-cms.sh -# which should be run AFTER the containers are up. - -echo "✨ Sync complete! Extensions are in packages/cms-infra/extensions." diff --git a/scripts/validate-cms.sh b/scripts/validate-cms.sh deleted file mode 100755 index 6af500a..0000000 --- a/scripts/validate-cms.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash - -# Configuration -CONTAINER="cms-infra-infra-cms-1" - -echo "🔍 Validating Directus Extension Stability..." - -# 1. Verify Patches -echo "🛠️ Checking Core Patches..." -docker exec -i "$CONTAINER" node << 'EOF' -const fs = require('node:fs'); -const { execSync } = require('node:child_process'); - -let failures = 0; - -// Check Node.js patch -const findNode = 'find /directus/node_modules -path "*/@directus/extensions/dist/node.js"'; -const nodePaths = execSync(findNode).toString().trim().split('\n').filter(Boolean); -nodePaths.forEach(p => { - const c = fs.readFileSync(p, 'utf8'); - if (!c.includes('(extension.entrypoint.app || extension.entrypoint)')) { - console.error('❌ Missing node.js patch at ' + p); - failures++; - } -}); - -// Check Manager.js patch -const findManager = 'find /directus/node_modules -path "*/@directus/api/dist/extensions/manager.js"'; -const managerPaths = execSync(findManager).toString().trim().split('\n').filter(Boolean); -managerPaths.forEach(p => { - const c = fs.readFileSync(p, 'utf8'); - if (!c.includes('/extensions/sources/index.js')) { - console.error('❌ Missing manager.js patch at ' + p); - failures++; - } -}); - -if (failures === 0) { - console.log('✅ Core patches are healthy.'); -} -process.exit(failures > 0 ? 1 : 0); -EOF - -if [ $? -ne 0 ]; then - echo "⚠️ Core patches missing! Run 'bash scripts/patch-cms.sh' to fix." -fi - -# 2. Verify Module Bar -echo "📋 Checking Sidebar Configuration..." -docker exec -i "$CONTAINER" node << 'EOF' -const sqlite3 = require('/directus/node_modules/.pnpm/sqlite3@5.1.7/node_modules/sqlite3'); -const db = new sqlite3.Database('/directus/database/data.db'); -const managerIds = ["unified-dashboard", "acquisition-manager", "company-manager", "customer-manager", "feedback-commander", "people-manager"]; - -db.get('SELECT module_bar FROM directus_settings WHERE id = 1', (err, row) => { - if (err) { console.error('❌ DB Error:', err.message); process.exit(1); } - - let mb = []; - try { mb = JSON.parse(row.module_bar || '[]'); } catch(e) { mb = []; } - - const existingIds = mb.map(m => m.id); - const missing = managerIds.filter(id => !existingIds.includes(id)); - const disabled = mb.filter(m => managerIds.includes(m.id) && m.enabled === false); - - if (missing.length === 0 && disabled.length === 0) { - console.log('✅ Sidebar is healthy with all manager modules enabled.'); - process.exit(0); - } else { - if (missing.length > 0) console.log('⚠️ Missing modules:', missing.join(', ')); - if (disabled.length > 0) console.log('⚠️ Disabled modules:', disabled.map(m => m.id).join(', ')); - - console.log('🔧 Self-healing in progress...'); - - // Construct Golden State Module Bar - const goldenMB = [ - { type: 'module', id: 'content', enabled: true }, - { type: 'module', id: 'users', enabled: true }, - { type: 'module', id: 'files', enabled: true }, - { type: 'module', id: 'insights', enabled: true }, - ...managerIds.map(id => ({ type: 'module', id, enabled: true })), - { type: 'module', id: 'settings', enabled: true } - ]; - - db.run('UPDATE directus_settings SET module_bar = ? WHERE id = 1', [JSON.stringify(goldenMB)], function(err) { - if (err) { console.error('❌ Repair failed:', err.message); process.exit(1); } - console.log('✨ Sidebar repaired successfully!'); - process.exit(0); - }); - } -}); -EOF diff --git a/scripts/validate-extensions.sh b/scripts/validate-extensions.sh deleted file mode 100644 index 76bc9e6..0000000 --- a/scripts/validate-extensions.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash - -# Configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -TARGET_DIRS=( - "$REPO_ROOT/packages/cms-infra/extensions" - "$REPO_ROOT/directus/extensions" -) - -echo "🛡️ Directus Extension Validator" -echo "=================================" - -for TARGET in "${TARGET_DIRS[@]}"; do - echo "" - echo "📂 Checking: $TARGET" - - if [ ! -d "$TARGET" ]; then - echo " ❌ Directory does not exist!" - continue - fi - - CATEGORIES=("endpoints" "hooks" "layouts" "modules" "operations" "panels" "displays" "interfaces") - FOUND_ANY=false - - for CAT in "${CATEGORIES[@]}"; do - CAT_PATH="$TARGET/$CAT" - if [ -d "$CAT_PATH" ]; then - EXTS=$(ls "$CAT_PATH") - if [ -n "$EXTS" ]; then - FOUND_ANY=true - echo " 📦 $CAT:" - for EXT in $EXTS; do - EXT_PATH="$CAT_PATH/$EXT" - if [ -f "$EXT_PATH/package.json" ]; then - VERSION=$(node -e "console.log(require('$EXT_PATH/package.json').version)") - echo " ✅ $EXT (v$VERSION)" - else - echo " ⚠️ $EXT (MISSING package.json!)" - fi - done - fi - fi - done - - if [ "$FOUND_ANY" = false ]; then - echo " 📭 No extensions found in standard category folders." - fi - - # Check for legacy files - LEGACY=$(find "$TARGET" -maxdepth 1 -not -path "$TARGET" -not -name ".*" -type d) - for L in $LEGACY; do - BN=$(basename "$L") - IS_CAT=false - for CAT in "${CATEGORIES[@]}"; do - if [ "$BN" == "$CAT" ]; then IS_CAT=true; break; fi - done - - if [ "$IS_CAT" = false ]; then - echo " 🚨 LEGACY/UNRESOLVED FOLDER FOUND: $BN (Will NOT be loaded by Directus)" - fi - done -done - -echo "" -echo "✨ Validation complete." diff --git a/scripts/validate-sdk-imports.sh b/scripts/validate-sdk-imports.sh deleted file mode 100755 index f5bb153..0000000 --- a/scripts/validate-sdk-imports.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash -# validate-sdk-imports.sh -# Validates that Directus extensions only use exports that exist in @directus/extensions-sdk. -# Prevents the "SyntaxError: doesn't provide an export named" runtime crash -# that silently breaks ALL extensions in the browser. - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Valid exports from @directus/extensions-sdk in Directus 11.x -# If Directus is upgraded, update this list by running: -# curl -s http://cms.localhost/admin/assets/@directus_extensions-sdk.*.entry.js | grep -oE 'export\{[^}]+\}' -VALID_EXPORTS=( - "defineDisplay" - "defineEndpoint" - "defineHook" - "defineInterface" - "defineLayout" - "defineModule" - "defineOperationApi" - "defineOperationApp" - "definePanel" - "defineTheme" - "getFieldsFromTemplate" - "getRelationType" - "useApi" - "useCollection" - "useExtensions" - "useFilterFields" - "useItems" - "useLayout" - "useSdk" - "useStores" - "useSync" -) - -ERRORS=0 - -echo "🔍 Validating @directus/extensions-sdk imports..." -echo "" - -# Search all .ts and .vue files in extension directories -SEARCH_DIRS=( - "$REPO_ROOT/packages/cms-infra/extensions" - "$REPO_ROOT/packages/unified-dashboard" - "$REPO_ROOT/packages/customer-manager" - "$REPO_ROOT/packages/company-manager" - "$REPO_ROOT/packages/people-manager" - "$REPO_ROOT/packages/acquisition-manager" - "$REPO_ROOT/packages/feedback-commander" -) - -for DIR in "${SEARCH_DIRS[@]}"; do - [ -d "$DIR" ] || continue - - # Find all imports from @directus/extensions-sdk - while IFS= read -r line; do - FILE=$(echo "$line" | cut -d: -f1) - LINENUM=$(echo "$line" | cut -d: -f2) - CONTENT=$(echo "$line" | cut -d: -f3-) - - # Extract imported names from the import statement - IMPORTS=$(echo "$CONTENT" | grep -oE '\{[^}]+\}' | tr -d '{}' | tr ',' '\n' | sed 's/^ *//;s/ *$//' | sed 's/ as .*//') - - for IMPORT in $IMPORTS; do - [ -z "$IMPORT" ] && continue - FOUND=false - for VALID in "${VALID_EXPORTS[@]}"; do - if [ "$IMPORT" = "$VALID" ]; then - FOUND=true - break - fi - done - - if [ "$FOUND" = false ]; then - echo "❌ INVALID IMPORT: '$IMPORT' in $FILE:$LINENUM" - echo " '$IMPORT' is NOT exported by @directus/extensions-sdk in Directus 11.x" - echo " This WILL crash ALL extensions at runtime!" - echo "" - ERRORS=$((ERRORS + 1)) - fi - done - done < <(grep -rn "from ['\"]@directus/extensions-sdk['\"]" "$DIR" --include="*.ts" --include="*.vue" 2>/dev/null || true) -done - -if [ "$ERRORS" -gt 0 ]; then - echo "💥 Found $ERRORS invalid import(s)!" - echo "" - echo "Valid exports from @directus/extensions-sdk:" - printf " %s\n" "${VALID_EXPORTS[@]}" - echo "" - echo "Common fixes:" - echo " useRouter → import { useRouter } from 'vue-router'" - echo " useRoute → import { useRoute } from 'vue-router'" - exit 1 -else - echo "✅ All @directus/extensions-sdk imports are valid." -fi diff --git a/scripts/verify-extensions-live.sh b/scripts/verify-extensions-live.sh deleted file mode 100755 index 79d0dd5..0000000 --- a/scripts/verify-extensions-live.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -set -e - -HOST="http://cms.localhost" -EXTENSIONS=("customer-manager" "people-manager" "company-manager" "feedback-commander" "unified-dashboard") - -echo "🔍 Verifying extensions at $HOST..." - -# 1. Check Main Manifest -MANIFEST=$(curl -s "$HOST/extensions/sources/index.js") - -if [ -z "$MANIFEST" ]; then - echo "❌ Error: Manifest returned empty response." - exit 1 -fi - -echo "✅ Manifest loaded (${#MANIFEST} bytes)." - -# 2. Check for unexpected 404/500 -if echo "$MANIFEST" | grep -q ""; then - echo "❌ Error: Manifest returned HTML (likely 404 or error page) instead of JS." - exit 1 -fi - -# 3. Verify each extension is in the bundle -FAILURE=0 -for EXT in "${EXTENSIONS[@]}"; do - # Directus bundles strings usually, or imports them. - # We look for the ID or the unique module name from src (e.g. "Customer Manager") - # Or simply the path matching. - - if echo "$MANIFEST" | grep -q "$EXT"; then - echo "✅ Found '$EXT' in manifest." - else - echo "❌ MISSING '$EXT' in manifest!" - FAILURE=1 - fi -done - -if [ $FAILURE -eq 1 ]; then - echo "🚨 VERIFICATION FAILED: One or more extensions are missing from the public bundle." - exit 1 -else - echo "🎉 ALL EXTENSIONS VERIFIED." - exit 0 -fi