diff --git a/check_drizzle.ts b/check_drizzle.ts
deleted file mode 100644
index 44932d7..0000000
--- a/check_drizzle.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-
-import { db } from "./src/db";
-import { sql } from "drizzle-orm";
-
-async function check() {
- try {
- const res = await db.execute(sql`SELECT COUNT(*) FROM ventes_produits`);
- console.log("Total rows in ventes_produits:", res.rows[0].count);
-
- const resDistinct = await db.execute(sql`SELECT COUNT(DISTINCT codein) FROM ventes_produits`);
- console.log("Total distinct codein in ventes_produits:", resDistinct.rows[0].count);
-
- const resSupplier = await db.execute(sql`SELECT code_fournisseur, COUNT(*) as row_count, COUNT(DISTINCT codein) as prod_count FROM ventes_produits GROUP BY code_fournisseur`);
- console.log("Counts per supplier:", resSupplier.rows);
- } catch (e) {
- console.error("Error:", e);
- }
-}
-check();
diff --git a/drizzle.config.ts b/drizzle.config.ts
deleted file mode 100644
index 91d078b..0000000
--- a/drizzle.config.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { defineConfig } from "drizzle-kit";
-import * as dotenv from "dotenv";
-
-dotenv.config({ path: ".env.local" });
-
-export default defineConfig({
- schema: "./src/db/schema.ts",
- out: "./src/db/migrations",
- dialect: "postgresql",
- dbCredentials: {
- url: process.env.DATABASE_URL!,
- },
-});
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 05e726d..8108e2e 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,18 +1,36 @@
import { defineConfig, globalIgnores } from "eslint/config";
-import nextVitals from "eslint-config-next/core-web-vitals";
-import nextTs from "eslint-config-next/typescript";
+import js from "@eslint/js";
+import globals from "globals";
+import tseslint from "typescript-eslint";
+import reactHooks from "eslint-plugin-react-hooks";
+import reactRefresh from "eslint-plugin-react-refresh";
+/**
+ * Lint de l'interface (SPA Vite). Seul `src/` est vérifié : `server/` est en
+ * Rust, `scripts/` et les fichiers .js de la racine sont des utilitaires Node.
+ */
const eslintConfig = defineConfig([
- ...nextVitals,
- ...nextTs,
- // Override default ignores of eslint-config-next.
- globalIgnores([
- // Default ignores of eslint-config-next:
- ".next/**",
- "out/**",
- "build/**",
- "next-env.d.ts",
- ]),
+ globalIgnores(["dist/**", "server/**", "scripts/**", "_bmad/**", "_bmad-output/**", "docs/**", "*.js", "*.mjs"]),
+ {
+ files: ["src/**/*.{ts,tsx}", "vite.config.mts"],
+ extends: [js.configs.recommended, tseslint.configs.recommended, reactHooks.configs.flat.recommended],
+ plugins: { "react-refresh": reactRefresh },
+ languageOptions: {
+ ecmaVersion: 2022,
+ globals: globals.browser,
+ },
+ rules: {
+ // Exports utilitaires historiques des composants (rechargement à chaud
+ // seulement moins fin pour ces fichiers).
+ "react-refresh/only-export-components": [
+ "warn",
+ {
+ allowConstantExport: true,
+ allowExportNames: ["buttonVariants", "toast", "confirmer", "useUrlTab", "PROFONDEUR_MAX"],
+ },
+ ],
+ },
+ },
]);
export default eslintConfig;
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..833e6c5
--- /dev/null
+++ b/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+ CollectFlow
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/next.config.ts b/next.config.ts
deleted file mode 100644
index c05866c..0000000
--- a/next.config.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/** @type {import('next').NextConfig} */
-const nextConfig = {
- output: "standalone",
- serverExternalPackages: ["pg", "ws", "httpntlm", "playwright-core"],
- experimental: {
- serverActions: {
- bodySizeLimit: "50mb",
- },
- },
- typescript: {
- ignoreBuildErrors: true,
- },
-};
-
-export default nextConfig;
diff --git a/package-lock.json b/package-lock.json
index 3f5018a..7b63db4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,39 +12,34 @@
"@tanstack/react-virtual": "^3.13.18",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "drizzle-orm": "^0.45.1",
"exceljs": "^4.4.0",
- "httpntlm": "^1.8.13",
"jspdf": "^4.2.0",
"jspdf-autotable": "^5.0.7",
"lucide-react": "^0.575.0",
- "next": "16.1.6",
- "next-auth": "^5.0.0-beta.30",
"next-themes": "^0.4.6",
- "pg": "^8.18.0",
- "playwright-core": "^1.61.0",
"radix-ui": "^1.4.3",
"react": "19.2.3",
"react-dom": "19.2.3",
+ "react-router": "^7.18.4",
"tailwind-merge": "^3.5.0",
- "ws": "^8.21.0",
- "zod": "^4.3.6",
"zustand": "^5.0.11"
},
"devDependencies": {
+ "@eslint/js": "^9.39.5",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
- "@types/pg": "^8.16.0",
"@types/react": "^19",
"@types/react-dom": "^19",
- "@types/ws": "^8.18.1",
- "drizzle-kit": "^0.31.9",
+ "@vitejs/plugin-react": "^6.1.2",
"eslint": "^9",
- "eslint-config-next": "16.1.6",
- "shadcn": "^3.8.5",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.5.7",
+ "globals": "^17.13.0",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
- "typescript": "5.9.3"
+ "typescript": "5.9.3",
+ "typescript-eslint": "^8.71.2",
+ "vite": "^8.3.4"
}
},
"node_modules/@alloc/quick-lru": {
@@ -60,65 +55,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@antfu/ni": {
- "version": "25.0.0",
- "resolved": "https://registry.npmjs.org/@antfu/ni/-/ni-25.0.0.tgz",
- "integrity": "sha512-9q/yCljni37pkMr4sPrI3G4jqdIk074+iukc5aFJl7kmDCCsiJrbZ6zKxnES1Gwg+i9RcDZwvktl23puGslmvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansis": "^4.0.0",
- "fzf": "^0.5.2",
- "package-manager-detector": "^1.3.0",
- "tinyexec": "^1.0.1"
- },
- "bin": {
- "na": "bin/na.mjs",
- "nci": "bin/nci.mjs",
- "ni": "bin/ni.mjs",
- "nlx": "bin/nlx.mjs",
- "nr": "bin/nr.mjs",
- "nun": "bin/nun.mjs",
- "nup": "bin/nup.mjs"
- }
- },
- "node_modules/@auth/core": {
- "version": "0.41.0",
- "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.41.0.tgz",
- "integrity": "sha512-Wd7mHPQ/8zy6Qj7f4T46vg3aoor8fskJm6g2Zyj064oQ3+p0xNZXAV60ww0hY+MbTesfu29kK14Zk5d5JTazXQ==",
- "license": "ISC",
- "dependencies": {
- "@panva/hkdf": "^1.2.1",
- "jose": "^6.0.6",
- "oauth4webapi": "^3.3.0",
- "preact": "10.24.3",
- "preact-render-to-string": "6.5.11"
- },
- "peerDependencies": {
- "@simplewebauthn/browser": "^9.0.1",
- "@simplewebauthn/server": "^9.0.2",
- "nodemailer": "^6.8.0"
- },
- "peerDependenciesMeta": {
- "@simplewebauthn/browser": {
- "optional": true
- },
- "@simplewebauthn/server": {
- "optional": true
- },
- "nodemailer": {
- "optional": true
- }
- }
- },
"node_modules/@babel/code-frame": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
- "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/helper-validator-identifier": "^7.29.7",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
},
@@ -127,9 +71,9 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
- "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -137,21 +81,21 @@
}
},
"node_modules/@babel/core": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
- "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.29.0",
- "@babel/types": "^7.29.0",
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
"@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
@@ -168,14 +112,14 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.29.1",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
- "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
+ "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.29.0",
- "@babel/types": "^7.29.0",
+ "@babel/parser": "^7.29.8",
+ "@babel/types": "^7.29.8",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
@@ -184,28 +128,15 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.27.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
- "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.3"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
- "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
"browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
@@ -214,76 +145,40 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz",
- "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/helper-replace-supers": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/traverse": "^7.28.6",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
"node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz",
- "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.5",
- "@babel/types": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-module-imports": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
- "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
- "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.28.6"
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
@@ -292,65 +187,10 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
- "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
- "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-replace-supers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz",
- "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
- "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -358,9 +198,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
- "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -368,9 +208,9 @@
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -378,27 +218,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
- "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "version": "7.29.10",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz",
+ "integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
- "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
+ "version": "7.29.9",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz",
+ "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.29.0"
+ "@babel/types": "^7.29.8"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -407,95 +247,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
- "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
- "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz",
- "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-typescript": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz",
- "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/plugin-syntax-typescript": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/preset-typescript": {
- "version": "7.28.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz",
- "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-validator-option": "^7.27.1",
- "@babel/plugin-syntax-jsx": "^7.27.1",
- "@babel/plugin-transform-modules-commonjs": "^7.27.1",
- "@babel/plugin-transform-typescript": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/runtime": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
@@ -506,33 +257,33 @@
}
},
"node_modules/@babel/template": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
- "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6"
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
- "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "version": "7.29.10",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz",
+ "integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0",
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.8",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.9",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8",
"debug": "^4.3.1"
},
"engines": {
@@ -540,1149 +291,19 @@
}
},
"node_modules/@babel/types": {
- "version": "7.29.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
- "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@dotenvx/dotenvx": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.52.0.tgz",
- "integrity": "sha512-CaQcc8JvtzQhUSm9877b6V4Tb7HCotkcyud9X2YwdqtQKwgljkMRwU96fVYKnzN3V0Hj74oP7Es+vZ0mS+Aa1w==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "commander": "^11.1.0",
- "dotenv": "^17.2.1",
- "eciesjs": "^0.4.10",
- "execa": "^5.1.1",
- "fdir": "^6.2.0",
- "ignore": "^5.3.0",
- "object-treeify": "1.1.33",
- "picomatch": "^4.0.2",
- "which": "^4.0.0"
- },
- "bin": {
- "dotenvx": "src/cli/dotenvx.js"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/commander": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
- "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/execa": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
- "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^6.0.0",
- "human-signals": "^2.1.0",
- "is-stream": "^2.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.1",
- "onetime": "^5.1.2",
- "signal-exit": "^3.0.3",
- "strip-final-newline": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/get-stream": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
- "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/human-signals": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
- "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=10.17.0"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/isexe": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz",
- "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/npm-run-path": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
- "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/@dotenvx/dotenvx/node_modules/strip-final-newline": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
- "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@dotenvx/dotenvx/node_modules/which": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
- "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^3.1.1"
- },
- "bin": {
- "node-which": "bin/which.js"
- },
- "engines": {
- "node": "^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/@drizzle-team/brocli": {
- "version": "0.10.2",
- "resolved": "https://registry.npmjs.org/@drizzle-team/brocli/-/brocli-0.10.2.tgz",
- "integrity": "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==",
- "dev": true,
- "license": "Apache-2.0"
- },
- "node_modules/@ecies/ciphers": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@ecies/ciphers/-/ciphers-0.2.5.tgz",
- "integrity": "sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "bun": ">=1",
- "deno": ">=2",
- "node": ">=16"
- },
- "peerDependencies": {
- "@noble/ciphers": "^1.0.0"
- }
- },
- "node_modules/@emnapi/core": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
- "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.1.0",
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/runtime": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
- "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/wasi-threads": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
- "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@esbuild-kit/core-utils": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz",
- "integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==",
- "deprecated": "Merged into tsx: https://tsx.is",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "~0.18.20",
- "source-map-support": "^0.5.21"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "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"
- }
- },
- "node_modules/@esbuild-kit/esm-loader": {
- "version": "2.6.5",
- "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz",
- "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==",
- "deprecated": "Merged into tsx: https://tsx.is",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@esbuild-kit/core-utils": "^3.3.2",
- "get-tsconfig": "^4.7.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
- "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
- "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
- "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
- "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
- "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
- "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
- "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
- "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
- "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
- "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
- "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
- "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
- "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
- "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
- "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
- "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
- "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
- "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
- "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
- "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openharmony"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
- "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
- "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
- "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
- "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
@@ -1790,10 +411,23 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@eslint/js": {
- "version": "9.39.3",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz",
- "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==",
+ "version": "9.39.5",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz",
+ "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1906,19 +540,6 @@
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
"license": "MIT"
},
- "node_modules/@hono/node-server": {
- "version": "1.19.9",
- "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
- "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18.14.1"
- },
- "peerDependencies": {
- "hono": "^4"
- }
- },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1971,560 +592,6 @@
"url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@img/colour": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
- "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@img/sharp-darwin-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
- "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-darwin-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
- "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
- "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
- "cpu": [
- "arm64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "darwin"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
- "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
- "cpu": [
- "x64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "darwin"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
- "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
- "cpu": [
- "arm"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
- "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
- "cpu": [
- "arm64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-ppc64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
- "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
- "cpu": [
- "ppc64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-riscv64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
- "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
- "cpu": [
- "riscv64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
- "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
- "cpu": [
- "s390x"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
- "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
- "cpu": [
- "x64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
- "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
- "cpu": [
- "arm64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
- "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
- "cpu": [
- "x64"
- ],
- "license": "LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-linux-arm": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
- "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
- "cpu": [
- "arm"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
- "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-ppc64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
- "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
- "cpu": [
- "ppc64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-ppc64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-riscv64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
- "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
- "cpu": [
- "riscv64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-riscv64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-s390x": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
- "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
- "cpu": [
- "s390x"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linux-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
- "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
- "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
- "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
- }
- },
- "node_modules/@img/sharp-wasm32": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
- "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
- "cpu": [
- "wasm32"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/runtime": "^1.7.0"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
- "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
- "cpu": [
- "arm64"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-ia32": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
- "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
- "cpu": [
- "ia32"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
- "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
- "cpu": [
- "x64"
- ],
- "license": "Apache-2.0 AND LGPL-3.0-or-later",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@inquirer/ansi": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz",
- "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@inquirer/confirm": {
- "version": "5.1.21",
- "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz",
- "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@inquirer/core": "^10.3.2",
- "@inquirer/type": "^3.0.10"
- },
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "@types/node": ">=18"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- }
- }
- },
- "node_modules/@inquirer/core": {
- "version": "10.3.2",
- "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz",
- "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@inquirer/ansi": "^1.0.2",
- "@inquirer/figures": "^1.0.15",
- "@inquirer/type": "^3.0.10",
- "cli-width": "^4.1.0",
- "mute-stream": "^2.0.0",
- "signal-exit": "^4.1.0",
- "wrap-ansi": "^6.2.0",
- "yoctocolors-cjs": "^2.1.3"
- },
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "@types/node": ">=18"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- }
- }
- },
- "node_modules/@inquirer/figures": {
- "version": "1.0.15",
- "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz",
- "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@inquirer/type": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz",
- "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "@types/node": ">=18"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- }
- }
- },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -2575,379 +642,14 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@modelcontextprotocol/sdk": {
- "version": "1.26.0",
- "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz",
- "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==",
+ "node_modules/@oxc-project/types": {
+ "version": "0.153.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.153.0.tgz",
+ "integrity": "sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@hono/node-server": "^1.19.9",
- "ajv": "^8.17.1",
- "ajv-formats": "^3.0.1",
- "content-type": "^1.0.5",
- "cors": "^2.8.5",
- "cross-spawn": "^7.0.5",
- "eventsource": "^3.0.2",
- "eventsource-parser": "^3.0.0",
- "express": "^5.2.1",
- "express-rate-limit": "^8.2.1",
- "hono": "^4.11.4",
- "jose": "^6.1.3",
- "json-schema-typed": "^8.0.2",
- "pkce-challenge": "^5.0.0",
- "raw-body": "^3.0.0",
- "zod": "^3.25 || ^4.0",
- "zod-to-json-schema": "^3.25.1"
- },
- "engines": {
- "node": ">=18"
- },
- "peerDependencies": {
- "@cfworker/json-schema": "^4.1.1",
- "zod": "^3.25 || ^4.0"
- },
- "peerDependenciesMeta": {
- "@cfworker/json-schema": {
- "optional": true
- },
- "zod": {
- "optional": false
- }
- }
- },
- "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@mswjs/interceptors": {
- "version": "0.41.3",
- "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz",
- "integrity": "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@open-draft/deferred-promise": "^2.2.0",
- "@open-draft/logger": "^0.3.0",
- "@open-draft/until": "^2.0.0",
- "is-node-process": "^1.2.0",
- "outvariant": "^1.4.3",
- "strict-event-emitter": "^0.5.1"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@napi-rs/wasm-runtime": {
- "version": "0.2.12",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
- "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/core": "^1.4.3",
- "@emnapi/runtime": "^1.4.3",
- "@tybys/wasm-util": "^0.10.0"
- }
- },
- "node_modules/@next/env": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.6.tgz",
- "integrity": "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==",
- "license": "MIT"
- },
- "node_modules/@next/eslint-plugin-next": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.1.6.tgz",
- "integrity": "sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-glob": "3.3.1"
- }
- },
- "node_modules/@next/swc-darwin-arm64": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz",
- "integrity": "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-darwin-x64": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz",
- "integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-arm64-gnu": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz",
- "integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-arm64-musl": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz",
- "integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-x64-gnu": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz",
- "integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-x64-musl": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz",
- "integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-win32-arm64-msvc": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz",
- "integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-win32-x64-msvc": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz",
- "integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@noble/ciphers": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
- "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@noble/curves": {
- "version": "1.9.7",
- "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz",
- "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@noble/hashes": "1.8.0"
- },
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nolyfill/is-core-module": {
- "version": "1.0.39",
- "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
- "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.4.0"
- }
- },
- "node_modules/@open-draft/deferred-promise": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz",
- "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@open-draft/logger": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz",
- "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-node-process": "^1.2.0",
- "outvariant": "^1.4.0"
- }
- },
- "node_modules/@open-draft/until": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz",
- "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@opentelemetry/api": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
- "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
- "license": "Apache-2.0",
- "optional": true,
- "peer": true,
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/@panva/hkdf": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
- "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==",
- "license": "MIT",
"funding": {
- "url": "https://github.com/sponsors/panva"
+ "url": "https://github.com/sponsors/oxc-project"
}
},
"node_modules/@radix-ui/number": {
@@ -4448,42 +2150,268 @@
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
"license": "MIT"
},
- "node_modules/@rtsao/scc": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
- "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@sec-ant/readable-stream": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
- "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@sindresorhus/merge-streams": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
- "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
+ "node_modules/@rolldown/binding-android-arm-eabi": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.13.tgz",
+ "integrity": "sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==",
+ "cpu": [
+ "arm"
+ ],
"dev": true,
"license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": "^20.19.0 || >=22.12.0"
}
},
- "node_modules/@swc/helpers": {
- "version": "0.5.15",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
- "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.8.0"
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.13.tgz",
+ "integrity": "sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
}
},
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.13.tgz",
+ "integrity": "sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.13.tgz",
+ "integrity": "sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.13.tgz",
+ "integrity": "sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.13.tgz",
+ "integrity": "sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.13.tgz",
+ "integrity": "sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.13.tgz",
+ "integrity": "sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.13.tgz",
+ "integrity": "sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.13.tgz",
+ "integrity": "sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.13.tgz",
+ "integrity": "sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.13.tgz",
+ "integrity": "sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.13.tgz",
+ "integrity": "sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.13.tgz",
+ "integrity": "sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.13.tgz",
+ "integrity": "sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@tailwindcss/node": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.0.tgz",
@@ -4879,98 +2807,6 @@
"url": "https://github.com/sponsors/tannerlinsley"
}
},
- "node_modules/@ts-morph/common": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.27.0.tgz",
- "integrity": "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-glob": "^3.3.3",
- "minimatch": "^10.0.1",
- "path-browserify": "^1.0.1"
- }
- },
- "node_modules/@ts-morph/common/node_modules/balanced-match": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz",
- "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/@ts-morph/common/node_modules/brace-expansion": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz",
- "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/@ts-morph/common/node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/@ts-morph/common/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/@ts-morph/common/node_modules/minimatch": {
- "version": "10.2.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz",
- "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@tybys/wasm-util": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
- "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
@@ -4985,18 +2821,11 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/json5": {
- "version": "0.0.29",
- "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
- "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/node": {
"version": "20.19.33",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz",
"integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
@@ -5008,18 +2837,6 @@
"integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==",
"license": "MIT"
},
- "node_modules/@types/pg": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.16.0.tgz",
- "integrity": "sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "pg-protocol": "*",
- "pg-types": "^2.2.0"
- }
- },
"node_modules/@types/raf": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
@@ -5047,13 +2864,6 @@
"@types/react": "^19.2.0"
}
},
- "node_modules/@types/statuses": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz",
- "integrity": "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
@@ -5061,38 +2871,21 @@
"license": "MIT",
"optional": true
},
- "node_modules/@types/validate-npm-package-name": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@types/validate-npm-package-name/-/validate-npm-package-name-4.0.2.tgz",
- "integrity": "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/ws": {
- "version": "8.18.1",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
- "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz",
- "integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz",
+ "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.56.0",
- "@typescript-eslint/type-utils": "8.56.0",
- "@typescript-eslint/utils": "8.56.0",
- "@typescript-eslint/visitor-keys": "8.56.0",
+ "@typescript-eslint/scope-manager": "8.71.2",
+ "@typescript-eslint/type-utils": "8.71.2",
+ "@typescript-eslint/utils": "8.71.2",
+ "@typescript-eslint/visitor-keys": "8.71.2",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
- "ts-api-utils": "^2.4.0"
+ "ts-api-utils": "^2.5.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5102,15 +2895,15 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.56.0",
+ "@typescript-eslint/parser": "^8.71.2",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz",
+ "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5118,16 +2911,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz",
- "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz",
+ "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.56.0",
- "@typescript-eslint/types": "8.56.0",
- "@typescript-eslint/typescript-estree": "8.56.0",
- "@typescript-eslint/visitor-keys": "8.56.0",
+ "@typescript-eslint/scope-manager": "8.71.2",
+ "@typescript-eslint/types": "8.71.2",
+ "@typescript-eslint/typescript-estree": "8.71.2",
+ "@typescript-eslint/visitor-keys": "8.71.2",
"debug": "^4.4.3"
},
"engines": {
@@ -5139,18 +2932,18 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz",
- "integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz",
+ "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.56.0",
- "@typescript-eslint/types": "^8.56.0",
+ "@typescript-eslint/tsconfig-utils": "^8.71.2",
+ "@typescript-eslint/types": "^8.71.2",
"debug": "^4.4.3"
},
"engines": {
@@ -5161,18 +2954,18 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz",
- "integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz",
+ "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.56.0",
- "@typescript-eslint/visitor-keys": "8.56.0"
+ "@typescript-eslint/types": "8.71.2",
+ "@typescript-eslint/visitor-keys": "8.71.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5183,9 +2976,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz",
- "integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz",
+ "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5196,21 +2989,21 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz",
- "integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz",
+ "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.56.0",
- "@typescript-eslint/typescript-estree": "8.56.0",
- "@typescript-eslint/utils": "8.56.0",
+ "@typescript-eslint/types": "8.71.2",
+ "@typescript-eslint/typescript-estree": "8.71.2",
+ "@typescript-eslint/utils": "8.71.2",
"debug": "^4.4.3",
- "ts-api-utils": "^2.4.0"
+ "ts-api-utils": "^2.5.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5221,13 +3014,13 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz",
- "integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz",
+ "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5239,21 +3032,21 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz",
- "integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz",
+ "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.56.0",
- "@typescript-eslint/tsconfig-utils": "8.56.0",
- "@typescript-eslint/types": "8.56.0",
- "@typescript-eslint/visitor-keys": "8.56.0",
+ "@typescript-eslint/project-service": "8.71.2",
+ "@typescript-eslint/tsconfig-utils": "8.71.2",
+ "@typescript-eslint/types": "8.71.2",
+ "@typescript-eslint/visitor-keys": "8.71.2",
"debug": "^4.4.3",
- "minimatch": "^9.0.5",
+ "minimatch": "^10.2.2",
"semver": "^7.7.3",
"tinyglobby": "^0.2.15",
- "ts-api-utils": "^2.4.0"
+ "ts-api-utils": "^2.5.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5263,39 +3056,52 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "version": "5.0.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0"
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "version": "10.2.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz",
+ "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==",
"dev": true,
- "license": "ISC",
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "brace-expansion": "^5.0.8"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -5306,16 +3112,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz",
- "integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz",
+ "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.56.0",
- "@typescript-eslint/types": "8.56.0",
- "@typescript-eslint/typescript-estree": "8.56.0"
+ "@typescript-eslint/scope-manager": "8.71.2",
+ "@typescript-eslint/types": "8.71.2",
+ "@typescript-eslint/typescript-estree": "8.71.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5326,17 +3132,17 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz",
- "integrity": "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz",
+ "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.56.0",
+ "@typescript-eslint/types": "8.71.2",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -5360,287 +3166,34 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/@unrs/resolver-binding-android-arm-eabi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
- "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@unrs/resolver-binding-android-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
- "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@unrs/resolver-binding-darwin-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
- "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@unrs/resolver-binding-darwin-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
- "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@unrs/resolver-binding-freebsd-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
- "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
- "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
- "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
- "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
- "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
- "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
- "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
- "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
- "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
- "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-linux-x64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
- "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@unrs/resolver-binding-wasm32-wasi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
- "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
- "cpu": [
- "wasm32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@napi-rs/wasm-runtime": "^0.2.11"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
- "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
- "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
- "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/accepts": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
- "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "node_modules/@vitejs/plugin-react": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.2.tgz",
+ "integrity": "sha512-fhJNGUdscQa4HkI0xFxwonWyhnVReCPDbXI7FH7jmzpnVCrFQI7PRrhWecO263610vOrs9tr2Y4xcf8uAdFxbw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "mime-types": "^3.0.0",
- "negotiator": "^1.0.0"
+ "@rolldown/pluginutils": "^1.0.1"
},
"engines": {
- "node": ">= 0.6"
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
+ "babel-plugin-react-compiler": "^1.0.0",
+ "oxc-transform-react": "^0.152.0",
+ "vite": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rolldown/plugin-babel": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
+ "oxc-transform-react": {
+ "optional": true
+ }
}
},
"node_modules/acorn": {
@@ -5666,16 +3219,6 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/agent-base": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
- "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/ajv": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
@@ -5693,61 +3236,6 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/ajv-formats": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
- "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependenciesMeta": {
- "ajv": {
- "optional": true
- }
- }
- },
- "node_modules/ajv-formats/node_modules/ajv": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ajv-formats/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@@ -5764,16 +3252,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/ansis": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz",
- "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/archiver": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz",
@@ -5868,248 +3346,12 @@
"node": ">=10"
}
},
- "node_modules/aria-query": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
- "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
- "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "is-array-buffer": "^3.0.5"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array-includes": {
- "version": "3.1.9",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
- "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.24.0",
- "es-object-atoms": "^1.1.1",
- "get-intrinsic": "^1.3.0",
- "is-string": "^1.1.1",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.findlast": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
- "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.2",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "es-shim-unscopables": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.findlastindex": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
- "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.9",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "es-shim-unscopables": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.flat": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
- "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-shim-unscopables": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.flatmap": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
- "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-shim-unscopables": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.tosorted": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
- "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.3",
- "es-errors": "^1.3.0",
- "es-shim-unscopables": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
- "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.1",
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "is-array-buffer": "^3.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/ast-types": {
- "version": "0.16.1",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
- "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ast-types-flow": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
- "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"license": "MIT"
},
- "node_modules/async-function": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
- "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "possible-typed-array-names": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/axe-core": {
- "version": "4.11.1",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.1.tgz",
- "integrity": "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==",
- "dev": true,
- "license": "MPL-2.0",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/axobject-query": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
- "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -6147,9 +3389,10 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
- "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
+ "version": "2.11.28",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.28.tgz",
+ "integrity": "sha512-br0LOmjJqr6Rt4AEkadbcNf67Zpo7EPwKsWbjnRrJIa1QYFHQBqM4C7F2WTbV8ahTEcg1Eo+Y0aWjjORInYFyA==",
+ "dev": true,
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.cjs"
@@ -6197,31 +3440,6 @@
"integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==",
"license": "MIT"
},
- "node_modules/body-parser": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
- "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "bytes": "^3.1.2",
- "content-type": "^1.0.5",
- "debug": "^4.4.3",
- "http-errors": "^2.0.0",
- "iconv-lite": "^0.7.0",
- "on-finished": "^2.4.1",
- "qs": "^6.14.1",
- "raw-body": "^3.0.1",
- "type-is": "^2.0.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
@@ -6232,23 +3450,10 @@
"concat-map": "0.0.1"
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/browserslist": {
- "version": "4.28.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
- "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "version": "4.29.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz",
+ "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==",
"dev": true,
"funding": [
{
@@ -6266,11 +3471,11 @@
],
"license": "MIT",
"dependencies": {
- "baseline-browser-mapping": "^2.9.0",
- "caniuse-lite": "^1.0.30001759",
- "electron-to-chromium": "^1.5.263",
- "node-releases": "^2.0.27",
- "update-browserslist-db": "^1.2.0"
+ "baseline-browser-mapping": "^2.11.26",
+ "caniuse-lite": "^1.0.30001813",
+ "electron-to-chromium": "^1.5.439",
+ "node-releases": "^2.0.57",
+ "update-browserslist-db": "^1.3.3"
},
"bin": {
"browserslist": "cli.js"
@@ -6312,13 +3517,6 @@
"node": "*"
}
},
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/buffer-indexof-polyfill": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
@@ -6336,82 +3534,6 @@
"node": ">=0.2.0"
}
},
- "node_modules/bundle-name": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
- "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "run-applescript": "^7.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
- "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.0",
- "es-define-property": "^1.0.0",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -6423,9 +3545,10 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001770",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz",
- "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==",
+ "version": "1.0.30001815",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001815.tgz",
+ "integrity": "sha512-uDybUEyfgbyJJ93J1vikTylBX31AkdVYeVPeffMQpf8XN7hSfr0oZOn4VFOIMNvtU5+rHvC5Udg2TgtJKHm23Q==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -6503,129 +3626,6 @@
"url": "https://polar.sh/cva"
}
},
- "node_modules/cli-cursor": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
- "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "restore-cursor": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cli-spinners": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
- "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cli-width": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
- "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/client-only": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
- "license": "MIT"
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cliui/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cliui/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -6635,13 +3635,6 @@
"node": ">=6"
}
},
- "node_modules/code-block-writer": {
- "version": "13.0.3",
- "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz",
- "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -6662,16 +3655,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/commander": {
- "version": "14.0.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
- "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20"
- }
- },
"node_modules/compress-commons": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz",
@@ -6693,30 +3676,6 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"license": "MIT"
},
- "node_modules/content-disposition": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
- "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -6724,26 +3683,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
- "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.6.0"
- }
- },
"node_modules/core-js": {
"version": "3.48.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz",
@@ -6762,51 +3701,6 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
- "node_modules/cors": {
- "version": "2.8.6",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
- "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "object-assign": "^4",
- "vary": "^1"
- },
- "engines": {
- "node": ">= 0.10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/cosmiconfig": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
- "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "env-paths": "^2.2.1",
- "import-fresh": "^3.3.0",
- "js-yaml": "^4.1.0",
- "parse-json": "^5.2.0"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/d-fischer"
- },
- "peerDependencies": {
- "typescript": ">=4.9.5"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
"node_modules/crc-32": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
@@ -6857,19 +3751,6 @@
"utrie": "^1.0.2"
}
},
- "node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -6877,77 +3758,6 @@
"devOptional": true,
"license": "MIT"
},
- "node_modules/damerau-levenshtein": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
- "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
- "dev": true,
- "license": "BSD-2-Clause"
- },
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/data-view-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
- "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/data-view-byte-length": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
- "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/inspect-js"
- }
- },
- "node_modules/data-view-byte-offset": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
- "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "is-data-view": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/dayjs": {
"version": "1.11.19",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
@@ -6972,21 +3782,6 @@
}
}
},
- "node_modules/dedent": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz",
- "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "babel-plugin-macros": "^3.1.0"
- },
- "peerDependenciesMeta": {
- "babel-plugin-macros": {
- "optional": true
- }
- }
- },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -6994,120 +3789,11 @@
"dev": true,
"license": "MIT"
},
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/default-browser": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz",
- "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "bundle-name": "^4.1.0",
- "default-browser-id": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/default-browser-id": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz",
- "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/define-lazy-prop": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
- "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/des.js": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz",
- "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
- }
- },
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "devOptional": true,
+ "dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -7119,29 +3805,6 @@
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
"license": "MIT"
},
- "node_modules/diff": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz",
- "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/dompurify": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.2.tgz",
@@ -7155,175 +3818,6 @@
"@types/trusted-types": "^2.0.7"
}
},
- "node_modules/dotenv": {
- "version": "17.3.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
- "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/drizzle-kit": {
- "version": "0.31.9",
- "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.31.9.tgz",
- "integrity": "sha512-GViD3IgsXn7trFyBUUHyTFBpH/FsHTxYJ66qdbVggxef4UBPHRYxQaRzYLTuekYnk9i5FIEL9pbBIwMqX/Uwrg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@drizzle-team/brocli": "^0.10.2",
- "@esbuild-kit/esm-loader": "^2.5.5",
- "esbuild": "^0.25.4",
- "esbuild-register": "^3.5.0"
- },
- "bin": {
- "drizzle-kit": "bin.cjs"
- }
- },
- "node_modules/drizzle-orm": {
- "version": "0.45.1",
- "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.45.1.tgz",
- "integrity": "sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@aws-sdk/client-rds-data": ">=3",
- "@cloudflare/workers-types": ">=4",
- "@electric-sql/pglite": ">=0.2.0",
- "@libsql/client": ">=0.10.0",
- "@libsql/client-wasm": ">=0.10.0",
- "@neondatabase/serverless": ">=0.10.0",
- "@op-engineering/op-sqlite": ">=2",
- "@opentelemetry/api": "^1.4.1",
- "@planetscale/database": ">=1.13",
- "@prisma/client": "*",
- "@tidbcloud/serverless": "*",
- "@types/better-sqlite3": "*",
- "@types/pg": "*",
- "@types/sql.js": "*",
- "@upstash/redis": ">=1.34.7",
- "@vercel/postgres": ">=0.8.0",
- "@xata.io/client": "*",
- "better-sqlite3": ">=7",
- "bun-types": "*",
- "expo-sqlite": ">=14.0.0",
- "gel": ">=2",
- "knex": "*",
- "kysely": "*",
- "mysql2": ">=2",
- "pg": ">=8",
- "postgres": ">=3",
- "sql.js": ">=1",
- "sqlite3": ">=5"
- },
- "peerDependenciesMeta": {
- "@aws-sdk/client-rds-data": {
- "optional": true
- },
- "@cloudflare/workers-types": {
- "optional": true
- },
- "@electric-sql/pglite": {
- "optional": true
- },
- "@libsql/client": {
- "optional": true
- },
- "@libsql/client-wasm": {
- "optional": true
- },
- "@neondatabase/serverless": {
- "optional": true
- },
- "@op-engineering/op-sqlite": {
- "optional": true
- },
- "@opentelemetry/api": {
- "optional": true
- },
- "@planetscale/database": {
- "optional": true
- },
- "@prisma/client": {
- "optional": true
- },
- "@tidbcloud/serverless": {
- "optional": true
- },
- "@types/better-sqlite3": {
- "optional": true
- },
- "@types/pg": {
- "optional": true
- },
- "@types/sql.js": {
- "optional": true
- },
- "@upstash/redis": {
- "optional": true
- },
- "@vercel/postgres": {
- "optional": true
- },
- "@xata.io/client": {
- "optional": true
- },
- "better-sqlite3": {
- "optional": true
- },
- "bun-types": {
- "optional": true
- },
- "expo-sqlite": {
- "optional": true
- },
- "gel": {
- "optional": true
- },
- "knex": {
- "optional": true
- },
- "kysely": {
- "optional": true
- },
- "mysql2": {
- "optional": true
- },
- "pg": {
- "optional": true
- },
- "postgres": {
- "optional": true
- },
- "prisma": {
- "optional": true
- },
- "sql.js": {
- "optional": true
- },
- "sqlite3": {
- "optional": true
- }
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@@ -7369,55 +3863,13 @@
"safe-buffer": "~5.1.0"
}
},
- "node_modules/eciesjs": {
- "version": "0.4.17",
- "resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.17.tgz",
- "integrity": "sha512-TOOURki4G7sD1wDCjj7NfLaXZZ49dFOeEb5y39IXpb8p0hRzVvfvzZHOi5JcT+PpyAbi/Y+lxPb8eTag2WYH8w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@ecies/ciphers": "^0.2.5",
- "@noble/ciphers": "^1.3.0",
- "@noble/curves": "^1.9.7",
- "@noble/hashes": "^1.8.0"
- },
- "engines": {
- "bun": ">=1",
- "deno": ">=2",
- "node": ">=16"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/electron-to-chromium": {
- "version": "1.5.302",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz",
- "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==",
+ "version": "1.5.452",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.452.tgz",
+ "integrity": "sha512-cVvk1YBSj6571VmV6hdJTqj94Y79xSu8cj6Y9t6ae4Y4431z8/7EJFvu3rVp90xhfuv9BpPKUmaLfTo4+FOGBg==",
"dev": true,
"license": "ISC"
},
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
@@ -7441,258 +3893,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/error-ex": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
- "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.2.1"
- }
- },
- "node_modules/es-abstract": {
- "version": "1.24.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
- "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-buffer-byte-length": "^1.0.2",
- "arraybuffer.prototype.slice": "^1.0.4",
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "data-view-buffer": "^1.0.2",
- "data-view-byte-length": "^1.0.2",
- "data-view-byte-offset": "^1.0.1",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "es-set-tostringtag": "^2.1.0",
- "es-to-primitive": "^1.3.0",
- "function.prototype.name": "^1.1.8",
- "get-intrinsic": "^1.3.0",
- "get-proto": "^1.0.1",
- "get-symbol-description": "^1.1.0",
- "globalthis": "^1.0.4",
- "gopd": "^1.2.0",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "internal-slot": "^1.1.0",
- "is-array-buffer": "^3.0.5",
- "is-callable": "^1.2.7",
- "is-data-view": "^1.0.2",
- "is-negative-zero": "^2.0.3",
- "is-regex": "^1.2.1",
- "is-set": "^2.0.3",
- "is-shared-array-buffer": "^1.0.4",
- "is-string": "^1.1.1",
- "is-typed-array": "^1.1.15",
- "is-weakref": "^1.1.1",
- "math-intrinsics": "^1.1.0",
- "object-inspect": "^1.13.4",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.7",
- "own-keys": "^1.0.1",
- "regexp.prototype.flags": "^1.5.4",
- "safe-array-concat": "^1.1.3",
- "safe-push-apply": "^1.0.0",
- "safe-regex-test": "^1.1.0",
- "set-proto": "^1.0.0",
- "stop-iteration-iterator": "^1.1.0",
- "string.prototype.trim": "^1.2.10",
- "string.prototype.trimend": "^1.0.9",
- "string.prototype.trimstart": "^1.0.8",
- "typed-array-buffer": "^1.0.3",
- "typed-array-byte-length": "^1.0.3",
- "typed-array-byte-offset": "^1.0.4",
- "typed-array-length": "^1.0.7",
- "unbox-primitive": "^1.1.0",
- "which-typed-array": "^1.1.19"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-iterator-helpers": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz",
- "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.24.1",
- "es-errors": "^1.3.0",
- "es-set-tostringtag": "^2.1.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.3.0",
- "globalthis": "^1.0.4",
- "gopd": "^1.2.0",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "internal-slot": "^1.1.0",
- "iterator.prototype": "^1.1.5",
- "safe-array-concat": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-shim-unscopables": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
- "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-to-primitive": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
- "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-callable": "^1.2.7",
- "is-date-object": "^1.0.5",
- "is-symbol": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/esbuild": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
- "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.12",
- "@esbuild/android-arm": "0.25.12",
- "@esbuild/android-arm64": "0.25.12",
- "@esbuild/android-x64": "0.25.12",
- "@esbuild/darwin-arm64": "0.25.12",
- "@esbuild/darwin-x64": "0.25.12",
- "@esbuild/freebsd-arm64": "0.25.12",
- "@esbuild/freebsd-x64": "0.25.12",
- "@esbuild/linux-arm": "0.25.12",
- "@esbuild/linux-arm64": "0.25.12",
- "@esbuild/linux-ia32": "0.25.12",
- "@esbuild/linux-loong64": "0.25.12",
- "@esbuild/linux-mips64el": "0.25.12",
- "@esbuild/linux-ppc64": "0.25.12",
- "@esbuild/linux-riscv64": "0.25.12",
- "@esbuild/linux-s390x": "0.25.12",
- "@esbuild/linux-x64": "0.25.12",
- "@esbuild/netbsd-arm64": "0.25.12",
- "@esbuild/netbsd-x64": "0.25.12",
- "@esbuild/openbsd-arm64": "0.25.12",
- "@esbuild/openbsd-x64": "0.25.12",
- "@esbuild/openharmony-arm64": "0.25.12",
- "@esbuild/sunos-x64": "0.25.12",
- "@esbuild/win32-arm64": "0.25.12",
- "@esbuild/win32-ia32": "0.25.12",
- "@esbuild/win32-x64": "0.25.12"
- }
- },
- "node_modules/esbuild-register": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz",
- "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "peerDependencies": {
- "esbuild": ">=0.12 <1"
- }
- },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -7703,13 +3903,6 @@
"node": ">=6"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -7783,238 +3976,6 @@
}
}
},
- "node_modules/eslint-config-next": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.1.6.tgz",
- "integrity": "sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@next/eslint-plugin-next": "16.1.6",
- "eslint-import-resolver-node": "^0.3.6",
- "eslint-import-resolver-typescript": "^3.5.2",
- "eslint-plugin-import": "^2.32.0",
- "eslint-plugin-jsx-a11y": "^6.10.0",
- "eslint-plugin-react": "^7.37.0",
- "eslint-plugin-react-hooks": "^7.0.0",
- "globals": "16.4.0",
- "typescript-eslint": "^8.46.0"
- },
- "peerDependencies": {
- "eslint": ">=9.0.0",
- "typescript": ">=3.3.1"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-config-next/node_modules/globals": {
- "version": "16.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
- "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint-import-resolver-node": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
- "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^3.2.7",
- "is-core-module": "^2.13.0",
- "resolve": "^1.22.4"
- }
- },
- "node_modules/eslint-import-resolver-node/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-import-resolver-typescript": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
- "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "@nolyfill/is-core-module": "1.0.39",
- "debug": "^4.4.0",
- "get-tsconfig": "^4.10.0",
- "is-bun-module": "^2.0.0",
- "stable-hash": "^0.0.5",
- "tinyglobby": "^0.2.13",
- "unrs-resolver": "^1.6.2"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint-import-resolver-typescript"
- },
- "peerDependencies": {
- "eslint": "*",
- "eslint-plugin-import": "*",
- "eslint-plugin-import-x": "*"
- },
- "peerDependenciesMeta": {
- "eslint-plugin-import": {
- "optional": true
- },
- "eslint-plugin-import-x": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-module-utils": {
- "version": "2.12.1",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
- "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^3.2.7"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependenciesMeta": {
- "eslint": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-module-utils/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-plugin-import": {
- "version": "2.32.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
- "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@rtsao/scc": "^1.1.0",
- "array-includes": "^3.1.9",
- "array.prototype.findlastindex": "^1.2.6",
- "array.prototype.flat": "^1.3.3",
- "array.prototype.flatmap": "^1.3.3",
- "debug": "^3.2.7",
- "doctrine": "^2.1.0",
- "eslint-import-resolver-node": "^0.3.9",
- "eslint-module-utils": "^2.12.1",
- "hasown": "^2.0.2",
- "is-core-module": "^2.16.1",
- "is-glob": "^4.0.3",
- "minimatch": "^3.1.2",
- "object.fromentries": "^2.0.8",
- "object.groupby": "^1.0.3",
- "object.values": "^1.2.1",
- "semver": "^6.3.1",
- "string.prototype.trimend": "^1.0.9",
- "tsconfig-paths": "^3.15.0"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
- }
- },
- "node_modules/eslint-plugin-import/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-plugin-jsx-a11y": {
- "version": "6.10.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
- "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "aria-query": "^5.3.2",
- "array-includes": "^3.1.8",
- "array.prototype.flatmap": "^1.3.2",
- "ast-types-flow": "^0.0.8",
- "axe-core": "^4.10.0",
- "axobject-query": "^4.1.0",
- "damerau-levenshtein": "^1.0.8",
- "emoji-regex": "^9.2.2",
- "hasown": "^2.0.2",
- "jsx-ast-utils": "^3.3.5",
- "language-tags": "^1.0.9",
- "minimatch": "^3.1.2",
- "object.fromentries": "^2.0.8",
- "safe-regex-test": "^1.0.3",
- "string.prototype.includes": "^2.0.1"
- },
- "engines": {
- "node": ">=4.0"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
- }
- },
- "node_modules/eslint-plugin-react": {
- "version": "7.37.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
- "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-includes": "^3.1.8",
- "array.prototype.findlast": "^1.2.5",
- "array.prototype.flatmap": "^1.3.3",
- "array.prototype.tosorted": "^1.1.4",
- "doctrine": "^2.1.0",
- "es-iterator-helpers": "^1.2.1",
- "estraverse": "^5.3.0",
- "hasown": "^2.0.2",
- "jsx-ast-utils": "^2.4.1 || ^3.0.0",
- "minimatch": "^3.1.2",
- "object.entries": "^1.1.9",
- "object.fromentries": "^2.0.8",
- "object.values": "^1.2.1",
- "prop-types": "^15.8.1",
- "resolve": "^2.0.0-next.5",
- "semver": "^6.3.1",
- "string.prototype.matchall": "^4.0.12",
- "string.prototype.repeat": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
- }
- },
"node_modules/eslint-plugin-react-hooks": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
@@ -8035,28 +3996,14 @@
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
}
},
- "node_modules/eslint-plugin-react/node_modules/resolve": {
- "version": "2.0.0-next.6",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz",
- "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==",
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.7.tgz",
+ "integrity": "sha512-XhJSzLljuYD4UjNuFGJu2v7aD3sqNVK12w5/DCUfrNfHWegZo2+TsavNx8MuxMwEquuFAzNbNfXKU0WoZ+YUIg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "is-core-module": "^2.16.1",
- "node-exports-info": "^1.6.0",
- "object-keys": "^1.1.1",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "peerDependencies": {
+ "eslint": "^9 || ^10"
}
},
"node_modules/eslint-scope": {
@@ -8089,6 +4036,19 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint/node_modules/@eslint/js": {
+ "version": "9.39.3",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz",
+ "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
"node_modules/espree": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
@@ -8107,20 +4067,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true,
- "license": "BSD-2-Clause",
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/esquery": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
@@ -8167,39 +4113,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/eventsource": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz",
- "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "eventsource-parser": "^3.0.1"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/eventsource-parser": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz",
- "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18.0.0"
- }
- },
"node_modules/exceljs": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.4.0.tgz",
@@ -8220,96 +4133,6 @@
"node": ">=8.3.0"
}
},
- "node_modules/execa": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz",
- "integrity": "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@sindresorhus/merge-streams": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "figures": "^6.1.0",
- "get-stream": "^9.0.0",
- "human-signals": "^8.0.1",
- "is-plain-obj": "^4.1.0",
- "is-stream": "^4.0.1",
- "npm-run-path": "^6.0.0",
- "pretty-ms": "^9.2.0",
- "signal-exit": "^4.1.0",
- "strip-final-newline": "^4.0.0",
- "yoctocolors": "^2.1.1"
- },
- "engines": {
- "node": "^18.19.0 || >=20.5.0"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/express": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
- "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "accepts": "^2.0.0",
- "body-parser": "^2.2.1",
- "content-disposition": "^1.0.0",
- "content-type": "^1.0.5",
- "cookie": "^0.7.1",
- "cookie-signature": "^1.2.1",
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "finalhandler": "^2.1.0",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.0",
- "merge-descriptors": "^2.0.0",
- "mime-types": "^3.0.0",
- "on-finished": "^2.4.1",
- "once": "^1.4.0",
- "parseurl": "^1.3.3",
- "proxy-addr": "^2.0.7",
- "qs": "^6.14.0",
- "range-parser": "^1.2.1",
- "router": "^2.2.0",
- "send": "^1.1.0",
- "serve-static": "^2.2.0",
- "statuses": "^2.0.1",
- "type-is": "^2.0.1",
- "vary": "^1.1.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express-rate-limit": {
- "version": "8.2.1",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz",
- "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ip-address": "10.0.1"
- },
- "engines": {
- "node": ">= 16"
- },
- "funding": {
- "url": "https://github.com/sponsors/express-rate-limit"
- },
- "peerDependencies": {
- "express": ">= 4.11"
- }
- },
"node_modules/fast-csv": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz",
@@ -8330,36 +4153,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fast-glob": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -8391,55 +4184,22 @@
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
"license": "(MIT AND Zlib)"
},
- "node_modules/fast-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
- "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/fastq": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
- "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
"license": "MIT",
- "dependencies": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
- },
"engines": {
- "node": "^12.20 || >= 14.13"
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
}
},
"node_modules/fflate": {
@@ -8448,22 +4208,6 @@
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"license": "MIT"
},
- "node_modules/figures": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz",
- "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-unicode-supported": "^2.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -8477,41 +4221,6 @@
"node": ">=16.0.0"
}
},
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/finalhandler": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
- "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "on-finished": "^2.4.1",
- "parseurl": "^1.3.3",
- "statuses": "^2.0.1"
- },
- "engines": {
- "node": ">= 18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -8550,82 +4259,33 @@
"dev": true,
"license": "ISC"
},
- "node_modules/for-each": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
- "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-callable": "^1.2.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fetch-blob": "^3.1.2"
- },
- "engines": {
- "node": ">=12.20.0"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
- "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
"license": "MIT"
},
- "node_modules/fs-extra": {
- "version": "11.3.3",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz",
- "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC"
},
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/fstream": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
@@ -8642,71 +4302,6 @@
"node": ">=0.6"
}
},
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/function.prototype.name": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
- "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "functions-have-names": "^1.2.3",
- "hasown": "^2.0.2",
- "is-callable": "^1.2.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/fuzzysort": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz",
- "integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fzf": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fzf/-/fzf-0.5.2.tgz",
- "integrity": "sha512-Tt4kuxLXFKHy8KT40zwsUPUkg1CrsgY25FxA2U/j/0WgEDCk3ddc/zLTCCcbSHX9FcKtLuVaDGtGE/STWC+j3Q==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
- "node_modules/generator-function": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
- "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -8717,54 +4312,6 @@
"node": ">=6.9.0"
}
},
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-east-asian-width": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz",
- "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/get-nonce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
@@ -8774,81 +4321,6 @@
"node": ">=6"
}
},
- "node_modules/get-own-enumerable-keys": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-own-enumerable-keys/-/get-own-enumerable-keys-1.0.0.tgz",
- "integrity": "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/get-stream": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
- "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@sec-ant/readable-stream": "^0.4.1",
- "is-stream": "^4.0.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/get-symbol-description": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
- "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-tsconfig": {
- "version": "4.13.6",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz",
- "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "resolve-pkg-maps": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
- }
- },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -8884,9 +4356,9 @@
}
},
"node_modules/globals": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
- "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "version": "17.13.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-17.13.0.tgz",
+ "integrity": "sha512-RwMTC61u7hrG3ZJMkZQOK4JLJrKS8QtoTii63EmWvFXHqycY9FObBJQCbsLxSO8kjKhWE5kV1GC+Vb1g3RI0Zg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8896,65 +4368,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/globalthis": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
- "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "define-properties": "^1.2.1",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
- "node_modules/graphql": {
- "version": "16.12.0",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz",
- "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
- }
- },
- "node_modules/has-bigints": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
- "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -8965,84 +4384,6 @@
"node": ">=8"
}
},
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
- "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/headers-polyfill": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz",
- "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/hermes-estree": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
@@ -9060,16 +4401,6 @@
"hermes-estree": "0.25.1"
}
},
- "node_modules/hono": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.0.tgz",
- "integrity": "sha512-NekXntS5M94pUfiVZ8oXXK/kkri+5WpX2/Ik+LVsl+uvw+soj4roXIsPqO+XsWrAw20mOzaXOZf3Q7PfB9A/IA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=16.9.0"
- }
- },
"node_modules/html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
@@ -9084,101 +4415,6 @@
"node": ">=8.0.0"
}
},
- "node_modules/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/httpntlm": {
- "version": "1.8.13",
- "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.8.13.tgz",
- "integrity": "sha512-2F2FDPiWT4rewPzNMg3uPhNkP3NExENlUGADRUDPQvuftuUTGW98nLZtGemCIW3G40VhWZYgkIDcQFAwZ3mf2Q==",
- "funding": [
- {
- "type": "paypal",
- "url": "https://www.paypal.com/donate/?hosted_button_id=2CKNJLZJBW8ZC"
- },
- {
- "type": "buymeacoffee",
- "url": "https://www.buymeacoffee.com/samdecrock"
- }
- ],
- "dependencies": {
- "des.js": "^1.0.1",
- "httpreq": ">=0.4.22",
- "js-md4": "^0.3.2",
- "underscore": "~1.12.1"
- },
- "engines": {
- "node": ">=10.4.0"
- }
- },
- "node_modules/httpreq": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-1.1.1.tgz",
- "integrity": "sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==",
- "license": "MIT",
- "engines": {
- "node": ">= 6.15.1"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/human-signals": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz",
- "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.18.0"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
- "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -9259,228 +4495,12 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
- "node_modules/internal-slot": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
- "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "hasown": "^2.0.2",
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/iobuffer": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
"integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
"license": "MIT"
},
- "node_modules/ip-address": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
- "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/is-array-buffer": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
- "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/is-async-function": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
- "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "async-function": "^1.0.0",
- "call-bound": "^1.0.3",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-bigint": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
- "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-bigints": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-boolean-object": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
- "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-bun-module": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
- "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "semver": "^7.7.1"
- }
- },
- "node_modules/is-bun-module/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-data-view": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
- "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "get-intrinsic": "^1.2.6",
- "is-typed-array": "^1.1.13"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-date-object": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
- "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-docker": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
- "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "is-docker": "cli.js"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -9491,52 +4511,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-finalizationregistry": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
- "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-generator-function": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
- "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.4",
- "generator-function": "^2.0.0",
- "get-proto": "^1.0.1",
- "has-tostringtag": "^1.0.2",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -9550,351 +4524,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-in-ssh": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz",
- "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-inside-container": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
- "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-docker": "^3.0.0"
- },
- "bin": {
- "is-inside-container": "cli.js"
- },
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-interactive": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
- "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-map": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
- "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
- "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-node-process": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz",
- "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-number-object": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
- "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-obj": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz",
- "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-plain-obj": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
- "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-promise": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
- "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/is-regex": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
- "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-regexp": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz",
- "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-set": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
- "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
- "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-stream": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
- "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-string": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
- "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
- "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "has-symbols": "^1.1.0",
- "safe-regex-test": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
- "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "which-typed-array": "^1.1.16"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-unicode-supported": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz",
- "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-weakmap": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
- "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakref": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
- "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakset": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
- "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "get-intrinsic": "^1.2.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-wsl": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
- "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-inside-container": "^1.0.0"
- },
- "engines": {
- "node": ">=16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -9902,24 +4531,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/iterator.prototype": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
- "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-object-atoms": "^1.0.0",
- "get-intrinsic": "^1.2.6",
- "get-proto": "^1.0.0",
- "has-symbols": "^1.1.0",
- "set-function-name": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/jiti": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
@@ -9930,21 +4541,6 @@
"jiti": "lib/jiti-cli.mjs"
}
},
- "node_modules/jose": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
- "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/panva"
- }
- },
- "node_modules/js-md4": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz",
- "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==",
- "license": "MIT"
- },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -9985,13 +4581,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -9999,13 +4588,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-schema-typed": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz",
- "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==",
- "dev": true,
- "license": "BSD-2-Clause"
- },
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
@@ -10026,19 +4608,6 @@
"node": ">=6"
}
},
- "node_modules/jsonfile": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
- "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
"node_modules/jspdf": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.0.tgz",
@@ -10065,22 +4634,6 @@
"jspdf": "^2 || ^3 || ^4"
}
},
- "node_modules/jsx-ast-utils": {
- "version": "3.3.5",
- "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
- "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-includes": "^3.1.6",
- "array.prototype.flat": "^1.3.1",
- "object.assign": "^4.1.4",
- "object.values": "^1.1.6"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
@@ -10139,36 +4692,6 @@
"json-buffer": "3.0.1"
}
},
- "node_modules/kleur": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
- "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/language-subtag-registry": {
- "version": "0.3.23",
- "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
- "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
- "dev": true,
- "license": "CC0-1.0"
- },
- "node_modules/language-tags": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
- "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "language-subtag-registry": "^0.3.20"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/lazystream": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
@@ -10501,13 +5024,6 @@
"url": "https://opencollective.com/parcel"
}
},
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/listenercount": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
@@ -10616,62 +5132,6 @@
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
"license": "MIT"
},
- "node_modules/log-symbols": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz",
- "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^5.3.0",
- "is-unicode-supported": "^1.3.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
- "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/log-symbols/node_modules/is-unicode-supported": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
- "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
- "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
- }
- },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -10701,126 +5161,6 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/media-typer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
- "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
- "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
- "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/mimic-function": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
- "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimalistic-assert": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
- "license": "ISC"
- },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -10861,79 +5201,11 @@
"dev": true,
"license": "MIT"
},
- "node_modules/msw": {
- "version": "2.12.10",
- "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.10.tgz",
- "integrity": "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "@inquirer/confirm": "^5.0.0",
- "@mswjs/interceptors": "^0.41.2",
- "@open-draft/deferred-promise": "^2.2.0",
- "@types/statuses": "^2.0.6",
- "cookie": "^1.0.2",
- "graphql": "^16.12.0",
- "headers-polyfill": "^4.0.2",
- "is-node-process": "^1.2.0",
- "outvariant": "^1.4.3",
- "path-to-regexp": "^6.3.0",
- "picocolors": "^1.1.1",
- "rettime": "^0.10.1",
- "statuses": "^2.0.2",
- "strict-event-emitter": "^0.5.1",
- "tough-cookie": "^6.0.0",
- "type-fest": "^5.2.0",
- "until-async": "^3.0.2",
- "yargs": "^17.7.2"
- },
- "bin": {
- "msw": "cli/index.js"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/mswjs"
- },
- "peerDependencies": {
- "typescript": ">= 4.8.x"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/msw/node_modules/cookie": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
- "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/mute-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
- "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": "^18.17.0 || >=20.5.0"
- }
- },
"node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "version": "3.3.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -10948,22 +5220,6 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
- "node_modules/napi-postinstall": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
- "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "napi-postinstall": "lib/cli.js"
- },
- "engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/napi-postinstall"
- }
- },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -10971,96 +5227,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/negotiator": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
- "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/next": {
- "version": "16.1.6",
- "resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz",
- "integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==",
- "license": "MIT",
- "dependencies": {
- "@next/env": "16.1.6",
- "@swc/helpers": "0.5.15",
- "baseline-browser-mapping": "^2.8.3",
- "caniuse-lite": "^1.0.30001579",
- "postcss": "8.4.31",
- "styled-jsx": "5.1.6"
- },
- "bin": {
- "next": "dist/bin/next"
- },
- "engines": {
- "node": ">=20.9.0"
- },
- "optionalDependencies": {
- "@next/swc-darwin-arm64": "16.1.6",
- "@next/swc-darwin-x64": "16.1.6",
- "@next/swc-linux-arm64-gnu": "16.1.6",
- "@next/swc-linux-arm64-musl": "16.1.6",
- "@next/swc-linux-x64-gnu": "16.1.6",
- "@next/swc-linux-x64-musl": "16.1.6",
- "@next/swc-win32-arm64-msvc": "16.1.6",
- "@next/swc-win32-x64-msvc": "16.1.6",
- "sharp": "^0.34.4"
- },
- "peerDependencies": {
- "@opentelemetry/api": "^1.1.0",
- "@playwright/test": "^1.51.1",
- "babel-plugin-react-compiler": "*",
- "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
- "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
- "sass": "^1.3.0"
- },
- "peerDependenciesMeta": {
- "@opentelemetry/api": {
- "optional": true
- },
- "@playwright/test": {
- "optional": true
- },
- "babel-plugin-react-compiler": {
- "optional": true
- },
- "sass": {
- "optional": true
- }
- }
- },
- "node_modules/next-auth": {
- "version": "5.0.0-beta.30",
- "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.30.tgz",
- "integrity": "sha512-+c51gquM3F6nMVmoAusRJ7RIoY0K4Ts9HCCwyy/BRoe4mp3msZpOzYMyb5LAYc1wSo74PMQkGDcaghIO7W6Xjg==",
- "license": "ISC",
- "dependencies": {
- "@auth/core": "0.41.0"
- },
- "peerDependencies": {
- "@simplewebauthn/browser": "^9.0.1",
- "@simplewebauthn/server": "^9.0.2",
- "next": "^14.0.0-0 || ^15.0.0 || ^16.0.0",
- "nodemailer": "^7.0.7",
- "react": "^18.2.0 || ^19.0.0"
- },
- "peerDependenciesMeta": {
- "@simplewebauthn/browser": {
- "optional": true
- },
- "@simplewebauthn/server": {
- "optional": true
- },
- "nodemailer": {
- "optional": true
- }
- }
- },
"node_modules/next-themes": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz",
@@ -11071,99 +5237,15 @@
"react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
}
},
- "node_modules/next/node_modules/postcss": {
- "version": "8.4.31",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
- "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "deprecated": "Use your platform's native DOMException instead",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=10.5.0"
- }
- },
- "node_modules/node-exports-info": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz",
- "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array.prototype.flatmap": "^1.3.3",
- "es-errors": "^1.3.0",
- "object.entries": "^1.1.9",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/node-fetch": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
- "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/node-fetch"
- }
- },
"node_modules/node-releases": {
- "version": "2.0.27",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
- "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "version": "2.0.58",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.58.tgz",
+ "integrity": "sha512-BdiKAgbfRlvfMq/XzO/AF9NPmaA8a+YpLAyAFTVFBj3gARrAIfWvNq7Q7NE4se3KgFu0KkrvQMxTS0XVnsGzHg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -11174,191 +5256,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/npm-run-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
- "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^4.0.0",
- "unicorn-magic": "^0.3.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/npm-run-path/node_modules/path-key": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
- "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/oauth4webapi": {
- "version": "3.8.5",
- "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.5.tgz",
- "integrity": "sha512-A8jmyUckVhRJj5lspguklcl90Ydqk61H3dcU0oLhH3Yv13KpAliKTt5hknpGGPZSSfOwGyraNEFmofDYH+1kSg==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/panva"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object-treeify": {
- "version": "1.1.33",
- "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz",
- "integrity": "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
- "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0",
- "has-symbols": "^1.1.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object.entries": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
- "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.fromentries": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
- "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.2",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object.groupby": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
- "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.values": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
- "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -11368,43 +5265,6 @@
"wrappy": "1"
}
},
- "node_modules/onetime": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
- "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-function": "^5.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/open": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz",
- "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "default-browser": "^5.4.0",
- "define-lazy-prop": "^3.0.0",
- "is-in-ssh": "^1.0.0",
- "is-inside-container": "^1.0.0",
- "powershell-utils": "^0.1.0",
- "wsl-utils": "^0.3.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -11423,68 +5283,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/ora": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz",
- "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^5.3.0",
- "cli-cursor": "^5.0.0",
- "cli-spinners": "^2.9.2",
- "is-interactive": "^2.0.0",
- "is-unicode-supported": "^2.0.0",
- "log-symbols": "^6.0.0",
- "stdin-discarder": "^0.2.2",
- "string-width": "^7.2.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora/node_modules/chalk": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
- "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/outvariant": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz",
- "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/own-keys": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
- "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "get-intrinsic": "^1.2.6",
- "object-keys": "^1.1.1",
- "safe-push-apply": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -11517,13 +5315,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/package-manager-detector": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz",
- "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -11543,55 +5334,6 @@
"node": ">=6"
}
},
- "node_modules/parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
- "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parse-ms": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
- "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-browserify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
- "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -11621,20 +5363,6 @@
"node": ">=8"
}
},
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/path-to-regexp": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
- "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -11642,150 +5370,30 @@
"license": "MIT",
"optional": true
},
- "node_modules/pg": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/pg/-/pg-8.18.0.tgz",
- "integrity": "sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==",
- "license": "MIT",
- "dependencies": {
- "pg-connection-string": "^2.11.0",
- "pg-pool": "^3.11.0",
- "pg-protocol": "^1.11.0",
- "pg-types": "2.2.0",
- "pgpass": "1.0.5"
- },
- "engines": {
- "node": ">= 16.0.0"
- },
- "optionalDependencies": {
- "pg-cloudflare": "^1.3.0"
- },
- "peerDependencies": {
- "pg-native": ">=3.0.1"
- },
- "peerDependenciesMeta": {
- "pg-native": {
- "optional": true
- }
- }
- },
- "node_modules/pg-cloudflare": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz",
- "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/pg-connection-string": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz",
- "integrity": "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==",
- "license": "MIT"
- },
- "node_modules/pg-int8": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
- "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
- "license": "ISC",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/pg-pool": {
- "version": "3.11.0",
- "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.11.0.tgz",
- "integrity": "sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==",
- "license": "MIT",
- "peerDependencies": {
- "pg": ">=8.0"
- }
- },
- "node_modules/pg-protocol": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.11.0.tgz",
- "integrity": "sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==",
- "license": "MIT"
- },
- "node_modules/pg-types": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
- "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
- "license": "MIT",
- "dependencies": {
- "pg-int8": "1.0.1",
- "postgres-array": "~2.0.0",
- "postgres-bytea": "~1.0.0",
- "postgres-date": "~1.0.4",
- "postgres-interval": "^1.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/pgpass": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
- "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
- "license": "MIT",
- "dependencies": {
- "split2": "^4.1.0"
- }
- },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8.6"
+ "node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/pkce-challenge": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
- "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=16.20.0"
- }
- },
- "node_modules/playwright-core": {
- "version": "1.61.0",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.0.tgz",
- "integrity": "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==",
- "license": "Apache-2.0",
- "bin": {
- "playwright-core": "cli.js"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/possible-typed-array-names": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
- "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/postcss": {
- "version": "8.5.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
- "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "version": "8.5.29",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz",
+ "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==",
"dev": true,
"funding": [
{
@@ -11803,99 +5411,14 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
+ "nanoid": "^3.3.19",
"picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
+ "source-map-js": "^1.2.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/postcss-selector-parser": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
- "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postgres-array": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
- "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postgres-bytea": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
- "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/postgres-date": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
- "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/postgres-interval": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
- "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
- "license": "MIT",
- "dependencies": {
- "xtend": "^4.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/powershell-utils": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz",
- "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/preact": {
- "version": "10.24.3",
- "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz",
- "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==",
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/preact"
- }
- },
- "node_modules/preact-render-to-string": {
- "version": "6.5.11",
- "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz",
- "integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==",
- "license": "MIT",
- "peerDependencies": {
- "preact": ">=10"
- }
- },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -11906,78 +5429,12 @@
"node": ">= 0.8.0"
}
},
- "node_modules/pretty-ms": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz",
- "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "parse-ms": "^4.0.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"license": "MIT"
},
- "node_modules/prompts": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
- "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "kleur": "^3.0.3",
- "sisteransi": "^1.0.5"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/prompts/node_modules/kleur": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
- "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- }
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -11988,43 +5445,6 @@
"node": ">=6"
}
},
- "node_modules/qs": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
- "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
"node_modules/radix-ui": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz",
@@ -12112,32 +5532,6 @@
"performance-now": "^2.1.0"
}
},
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
- "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.7.0",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/react": {
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
@@ -12159,13 +5553,6 @@
"react": "^19.2.3"
}
},
- "node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/react-remove-scroll": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
@@ -12213,6 +5600,41 @@
}
}
},
+ "node_modules/react-router": {
+ "version": "7.18.4",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.4.tgz",
+ "integrity": "sha512-PUPQcMhMGRAslLcvtlPz/kmzBEWPhLdgLFrL7pLNepBL6dX0lWj4WD2cUYVgYCuT3jxvghYFg81cDTj44DhetQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router/node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/react-style-singleton": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
@@ -12279,46 +5701,6 @@
"node": ">=10"
}
},
- "node_modules/recast": {
- "version": "0.23.11",
- "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
- "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ast-types": "^0.16.1",
- "esprima": "~4.0.0",
- "source-map": "~0.6.1",
- "tiny-invariant": "^1.3.3",
- "tslib": "^2.0.1"
- },
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/reflect.getprototypeof": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
- "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.9",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "get-intrinsic": "^1.2.7",
- "get-proto": "^1.0.1",
- "which-builtin-type": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
@@ -12326,68 +5708,6 @@
"license": "MIT",
"optional": true
},
- "node_modules/regexp.prototype.flags": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
- "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-errors": "^1.3.0",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "set-function-name": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require-from-string": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.11",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
- "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-core-module": "^2.16.1",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -12398,51 +5718,6 @@
"node": ">=4"
}
},
- "node_modules/resolve-pkg-maps": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
- }
- },
- "node_modules/restore-cursor": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
- "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "onetime": "^7.0.0",
- "signal-exit": "^4.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/rettime": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.10.1.tgz",
- "integrity": "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/reusify": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
- "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
"node_modules/rgbcolor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
@@ -12466,89 +5741,38 @@
"rimraf": "bin.js"
}
},
- "node_modules/router": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
- "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "node_modules/rolldown": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.13.tgz",
+ "integrity": "sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "is-promise": "^4.0.0",
- "parseurl": "^1.3.3",
- "path-to-regexp": "^8.0.0"
+ "@oxc-project/types": "=0.153.0",
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
},
"engines": {
- "node": ">= 18"
- }
- },
- "node_modules/router/node_modules/path-to-regexp": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
- "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/run-applescript": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",
- "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
+ "node": "^20.19.0 || >=22.12.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/safe-array-concat": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
- "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.2",
- "get-intrinsic": "^1.2.6",
- "has-symbols": "^1.1.0",
- "isarray": "^2.0.5"
- },
- "engines": {
- "node": ">=0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm-eabi": "1.2.13",
+ "@rolldown/binding-android-arm64": "1.2.13",
+ "@rolldown/binding-darwin-arm64": "1.2.13",
+ "@rolldown/binding-darwin-x64": "1.2.13",
+ "@rolldown/binding-freebsd-x64": "1.2.13",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.13",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.13",
+ "@rolldown/binding-linux-arm64-musl": "1.2.13",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.13",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.13",
+ "@rolldown/binding-linux-x64-gnu": "1.2.13",
+ "@rolldown/binding-linux-x64-musl": "1.2.13",
+ "@rolldown/binding-openharmony-arm64": "1.2.13",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.13",
+ "@rolldown/binding-win32-x64-msvc": "1.2.13"
}
},
"node_modules/safe-buffer": {
@@ -12571,48 +5795,6 @@
],
"license": "MIT"
},
- "node_modules/safe-push-apply": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
- "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "isarray": "^2.0.5"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safe-regex-test": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
- "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "is-regex": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/saxes": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
@@ -12641,101 +5823,11 @@
"semver": "bin/semver.js"
}
},
- "node_modules/send": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
- "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.3",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.1",
- "mime-types": "^3.0.2",
- "ms": "^2.1.3",
- "on-finished": "^2.4.1",
- "range-parser": "^1.2.1",
- "statuses": "^2.0.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/serve-static": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
- "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "parseurl": "^1.3.3",
- "send": "^1.2.0"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/set-function-length": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
- "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/set-function-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
- "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/set-proto": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
- "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
},
"node_modules/setimmediate": {
"version": "1.0.5",
@@ -12743,173 +5835,6 @@
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"license": "MIT"
},
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/shadcn": {
- "version": "3.8.5",
- "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-3.8.5.tgz",
- "integrity": "sha512-jPRx44e+eyeV7xwY3BLJXcfrks00+M0h5BGB9l6DdcBW4BpAj4x3lVmVy0TXPEs2iHEisxejr62sZAAw6B1EVA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@antfu/ni": "^25.0.0",
- "@babel/core": "^7.28.0",
- "@babel/parser": "^7.28.0",
- "@babel/plugin-transform-typescript": "^7.28.0",
- "@babel/preset-typescript": "^7.27.1",
- "@dotenvx/dotenvx": "^1.48.4",
- "@modelcontextprotocol/sdk": "^1.26.0",
- "@types/validate-npm-package-name": "^4.0.2",
- "browserslist": "^4.26.2",
- "commander": "^14.0.0",
- "cosmiconfig": "^9.0.0",
- "dedent": "^1.6.0",
- "deepmerge": "^4.3.1",
- "diff": "^8.0.2",
- "execa": "^9.6.0",
- "fast-glob": "^3.3.3",
- "fs-extra": "^11.3.1",
- "fuzzysort": "^3.1.0",
- "https-proxy-agent": "^7.0.6",
- "kleur": "^4.1.5",
- "msw": "^2.10.4",
- "node-fetch": "^3.3.2",
- "open": "^11.0.0",
- "ora": "^8.2.0",
- "postcss": "^8.5.6",
- "postcss-selector-parser": "^7.1.0",
- "prompts": "^2.4.2",
- "recast": "^0.23.11",
- "stringify-object": "^5.0.0",
- "tailwind-merge": "^3.0.1",
- "ts-morph": "^26.0.0",
- "tsconfig-paths": "^4.2.0",
- "validate-npm-package-name": "^7.0.1",
- "zod": "^3.24.1",
- "zod-to-json-schema": "^3.24.6"
- },
- "bin": {
- "shadcn": "dist/index.js"
- }
- },
- "node_modules/shadcn/node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/shadcn/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/shadcn/node_modules/tsconfig-paths": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
- "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "json5": "^2.2.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/shadcn/node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
- "node_modules/sharp": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
- "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "optional": true,
- "dependencies": {
- "@img/colour": "^1.0.0",
- "detect-libc": "^2.1.2",
- "semver": "^7.7.3"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.34.5",
- "@img/sharp-darwin-x64": "0.34.5",
- "@img/sharp-libvips-darwin-arm64": "1.2.4",
- "@img/sharp-libvips-darwin-x64": "1.2.4",
- "@img/sharp-libvips-linux-arm": "1.2.4",
- "@img/sharp-libvips-linux-arm64": "1.2.4",
- "@img/sharp-libvips-linux-ppc64": "1.2.4",
- "@img/sharp-libvips-linux-riscv64": "1.2.4",
- "@img/sharp-libvips-linux-s390x": "1.2.4",
- "@img/sharp-libvips-linux-x64": "1.2.4",
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
- "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
- "@img/sharp-linux-arm": "0.34.5",
- "@img/sharp-linux-arm64": "0.34.5",
- "@img/sharp-linux-ppc64": "0.34.5",
- "@img/sharp-linux-riscv64": "0.34.5",
- "@img/sharp-linux-s390x": "0.34.5",
- "@img/sharp-linux-x64": "0.34.5",
- "@img/sharp-linuxmusl-arm64": "0.34.5",
- "@img/sharp-linuxmusl-x64": "0.34.5",
- "@img/sharp-wasm32": "0.34.5",
- "@img/sharp-win32-arm64": "0.34.5",
- "@img/sharp-win32-ia32": "0.34.5",
- "@img/sharp-win32-x64": "0.34.5"
- }
- },
- "node_modules/sharp/node_modules/semver": {
- "version": "7.7.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
- "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -12933,148 +5858,16 @@
"node": ">=8"
}
},
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/sisteransi": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
- "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
+ "dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "node_modules/split2": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
- "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
- "license": "ISC",
- "engines": {
- "node": ">= 10.x"
- }
- },
- "node_modules/stable-hash": {
- "version": "0.0.5",
- "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
- "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/stackblur-canvas": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
@@ -13085,50 +5878,6 @@
"node": ">=0.1.14"
}
},
- "node_modules/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/stdin-discarder": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz",
- "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/stop-iteration-iterator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
- "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "internal-slot": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/strict-event-emitter": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
- "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -13138,201 +5887,6 @@
"safe-buffer": "~5.2.0"
}
},
- "node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/string-width/node_modules/emoji-regex": {
- "version": "10.6.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
- "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/string.prototype.includes": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
- "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/string.prototype.matchall": {
- "version": "4.0.12",
- "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
- "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.6",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "get-intrinsic": "^1.2.6",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "internal-slot": "^1.1.0",
- "regexp.prototype.flags": "^1.5.3",
- "set-function-name": "^2.0.2",
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.repeat": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
- "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- }
- },
- "node_modules/string.prototype.trim": {
- "version": "1.2.10",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
- "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.2",
- "define-data-property": "^1.1.4",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-object-atoms": "^1.0.0",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimend": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
- "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.2",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
- "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/stringify-object": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-5.0.0.tgz",
- "integrity": "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "get-own-enumerable-keys": "^1.0.0",
- "is-obj": "^3.0.0",
- "is-regexp": "^3.1.0"
- },
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "url": "https://github.com/yeoman/stringify-object?sponsor=1"
- }
- },
- "node_modules/strip-ansi": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
- "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/strip-final-newline": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
- "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -13346,29 +5900,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/styled-jsx": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
- "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
- "license": "MIT",
- "dependencies": {
- "client-only": "0.0.1"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "peerDependencies": {
- "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
- },
- "peerDependenciesMeta": {
- "@babel/core": {
- "optional": true
- },
- "babel-plugin-macros": {
- "optional": true
- }
- }
- },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -13382,19 +5913,6 @@
"node": ">=8"
}
},
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/svg-pathdata": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
@@ -13405,19 +5923,6 @@
"node": ">=12.0.0"
}
},
- "node_modules/tagged-tag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz",
- "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/tailwind-merge": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz",
@@ -13475,32 +5980,15 @@
"utrie": "^1.0.2"
}
},
- "node_modules/tiny-invariant": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
- "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/tinyexec": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
- "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
"node_modules/tinyglobby": {
- "version": "0.2.15",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
- "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
- "picomatch": "^4.0.3"
+ "picomatch": "^4.0.4"
},
"engines": {
"node": ">=12.0.0"
@@ -13509,57 +5997,6 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
- "node_modules/tinyglobby/node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/tldts": {
- "version": "7.0.23",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz",
- "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tldts-core": "^7.0.23"
- },
- "bin": {
- "tldts": "bin/cli.js"
- }
- },
- "node_modules/tldts-core": {
- "version": "7.0.23",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz",
- "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/tmp": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
@@ -13569,42 +6006,6 @@
"node": ">=14.14"
}
},
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/tough-cookie": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz",
- "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tldts": "^7.0.5"
- },
- "engines": {
- "node": ">=16"
- }
- },
"node_modules/traverse": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
@@ -13615,9 +6016,9 @@
}
},
"node_modules/ts-api-utils": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
- "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+ "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -13627,43 +6028,6 @@
"typescript": ">=4.8.4"
}
},
- "node_modules/ts-morph": {
- "version": "26.0.0",
- "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-26.0.0.tgz",
- "integrity": "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@ts-morph/common": "~0.27.0",
- "code-block-writer": "^13.0.3"
- }
- },
- "node_modules/tsconfig-paths": {
- "version": "3.15.0",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
- "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/json5": "^0.0.29",
- "json5": "^1.0.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- }
- },
- "node_modules/tsconfig-paths/node_modules/json5": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
- "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.0"
- },
- "bin": {
- "json5": "lib/cli.js"
- }
- },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -13693,115 +6057,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/type-fest": {
- "version": "5.4.4",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.4.tgz",
- "integrity": "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "dependencies": {
- "tagged-tag": "^1.0.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/type-is": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
- "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "content-type": "^1.0.5",
- "media-typer": "^1.1.0",
- "mime-types": "^3.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typed-array-buffer": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
- "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-typed-array": "^1.1.14"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typed-array-byte-length": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
- "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "for-each": "^0.3.3",
- "gopd": "^1.2.0",
- "has-proto": "^1.2.0",
- "is-typed-array": "^1.1.14"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-byte-offset": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
- "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "for-each": "^0.3.3",
- "gopd": "^1.2.0",
- "has-proto": "^1.2.0",
- "is-typed-array": "^1.1.15",
- "reflect.getprototypeof": "^1.0.9"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typed-array-length": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
- "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.7",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "is-typed-array": "^1.1.13",
- "possible-typed-array-names": "^1.0.0",
- "reflect.getprototypeof": "^1.0.6"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@@ -13817,16 +6072,16 @@
}
},
"node_modules/typescript-eslint": {
- "version": "8.56.0",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.0.tgz",
- "integrity": "sha512-c7toRLrotJ9oixgdW7liukZpsnq5CZ7PuKztubGYlNppuTqhIoWfhgHo/7EU0v06gS2l/x0i2NEFK1qMIf0rIg==",
+ "version": "8.71.2",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.2.tgz",
+ "integrity": "sha512-Rz4effbMy2g9wnvOJZG6SbVavX313Lap1vNEbk1RUochzickvzP8P4HB+bkNg5e50eVz1hQGjh9K1omI1xB4Bw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/eslint-plugin": "8.56.0",
- "@typescript-eslint/parser": "8.56.0",
- "@typescript-eslint/typescript-estree": "8.56.0",
- "@typescript-eslint/utils": "8.56.0"
+ "@typescript-eslint/eslint-plugin": "8.71.2",
+ "@typescript-eslint/parser": "8.71.2",
+ "@typescript-eslint/typescript-estree": "8.71.2",
+ "@typescript-eslint/utils": "8.71.2"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -13837,119 +6092,16 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.0.0"
+ "typescript": ">=4.8.4 <6.1.0"
}
},
- "node_modules/unbox-primitive": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
- "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.1.0",
- "which-boxed-primitive": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/underscore": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
- "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==",
- "license": "MIT"
- },
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "devOptional": true,
+ "dev": true,
"license": "MIT"
},
- "node_modules/unicorn-magic": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
- "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/unrs-resolver": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
- "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "napi-postinstall": "^0.3.0"
- },
- "funding": {
- "url": "https://opencollective.com/unrs-resolver"
- },
- "optionalDependencies": {
- "@unrs/resolver-binding-android-arm-eabi": "1.11.1",
- "@unrs/resolver-binding-android-arm64": "1.11.1",
- "@unrs/resolver-binding-darwin-arm64": "1.11.1",
- "@unrs/resolver-binding-darwin-x64": "1.11.1",
- "@unrs/resolver-binding-freebsd-x64": "1.11.1",
- "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1",
- "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1",
- "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-arm64-musl": "1.11.1",
- "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1",
- "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-x64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-x64-musl": "1.11.1",
- "@unrs/resolver-binding-wasm32-wasi": "1.11.1",
- "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1",
- "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1",
- "@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
- }
- },
- "node_modules/until-async": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/until-async/-/until-async-3.0.2.tgz",
- "integrity": "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/kettanaito"
- }
- },
"node_modules/unzipper": {
"version": "0.10.14",
"resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz",
@@ -14005,9 +6157,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
- "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz",
+ "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==",
"dev": true,
"funding": [
{
@@ -14122,34 +6274,343 @@
"uuid": "dist/bin/uuid"
}
},
- "node_modules/validate-npm-package-name": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz",
- "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": "^20.17.0 || >=22.9.0"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "node_modules/vite": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.4.tgz",
+ "integrity": "sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "lightningcss": "^1.33.0",
+ "picomatch": "^4.0.7",
+ "postcss": "^8.5.29",
+ "rolldown": "~1.2.12",
+ "tinyglobby": "^0.2.17"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
"engines": {
- "node": ">= 0.8"
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.7.1",
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
}
},
- "node_modules/web-streams-polyfill": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
- "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "node_modules/vite/node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
"engines": {
- "node": ">= 8"
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
"node_modules/which": {
@@ -14168,95 +6629,6 @@
"node": ">= 8"
}
},
- "node_modules/which-boxed-primitive": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
- "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-bigint": "^1.1.0",
- "is-boolean-object": "^1.2.1",
- "is-number-object": "^1.1.1",
- "is-string": "^1.1.1",
- "is-symbol": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-builtin-type": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
- "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "function.prototype.name": "^1.1.6",
- "has-tostringtag": "^1.0.2",
- "is-async-function": "^2.0.0",
- "is-date-object": "^1.1.0",
- "is-finalizationregistry": "^1.1.0",
- "is-generator-function": "^1.0.10",
- "is-regex": "^1.2.1",
- "is-weakref": "^1.0.2",
- "isarray": "^2.0.5",
- "which-boxed-primitive": "^1.1.0",
- "which-collection": "^1.0.2",
- "which-typed-array": "^1.1.16"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-collection": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
- "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-map": "^2.0.3",
- "is-set": "^2.0.3",
- "is-weakmap": "^2.0.2",
- "is-weakset": "^2.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.20",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
- "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "for-each": "^0.3.5",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
@@ -14267,135 +6639,18 @@
"node": ">=0.10.0"
}
},
- "node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/wrap-ansi/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
- "node_modules/ws": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
- "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/wsl-utils": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz",
- "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-wsl": "^3.1.0",
- "powershell-utils": "^0.1.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/xmlchars": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"license": "MIT"
},
- "node_modules/xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
@@ -14403,80 +6658,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/yargs/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@@ -14490,32 +6671,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/yoctocolors": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz",
- "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/yoctocolors-cjs": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz",
- "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/zip-stream": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz",
@@ -14552,24 +6707,15 @@
}
},
"node_modules/zod": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
- "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
+ "version": "4.6.7",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz",
+ "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
- "node_modules/zod-to-json-schema": {
- "version": "3.25.1",
- "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz",
- "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==",
- "dev": true,
- "license": "ISC",
- "peerDependencies": {
- "zod": "^3.25 || ^4"
- }
- },
"node_modules/zod-validation-error": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
diff --git a/package.json b/package.json
index 16b7847..9571b2a 100644
--- a/package.json
+++ b/package.json
@@ -3,10 +3,11 @@
"version": "0.1.0",
"private": true,
"scripts": {
- "dev": "next dev",
- "build": "next build",
- "start": "node scripts/db-init.js && next start",
+ "dev": "vite",
+ "build": "tsc --noEmit && vite build",
+ "preview": "vite preview",
"lint": "eslint",
+ "typecheck": "tsc --noEmit",
"docker:up": "docker-compose up -d",
"docker:down": "docker-compose down",
"docker:build": "docker-compose up -d --build"
@@ -16,38 +17,33 @@
"@tanstack/react-virtual": "^3.13.18",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "drizzle-orm": "^0.45.1",
"exceljs": "^4.4.0",
- "httpntlm": "^1.8.13",
"jspdf": "^4.2.0",
"jspdf-autotable": "^5.0.7",
"lucide-react": "^0.575.0",
- "next": "16.1.6",
- "next-auth": "^5.0.0-beta.30",
"next-themes": "^0.4.6",
- "pg": "^8.18.0",
- "playwright-core": "^1.61.0",
"radix-ui": "^1.4.3",
"react": "19.2.3",
"react-dom": "19.2.3",
+ "react-router": "^7.18.4",
"tailwind-merge": "^3.5.0",
- "ws": "^8.21.0",
- "zod": "^4.3.6",
"zustand": "^5.0.11"
},
"devDependencies": {
+ "@eslint/js": "^9.39.5",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
- "@types/pg": "^8.16.0",
"@types/react": "^19",
"@types/react-dom": "^19",
- "@types/ws": "^8.18.1",
- "drizzle-kit": "^0.31.9",
+ "@vitejs/plugin-react": "^6.1.2",
"eslint": "^9",
- "eslint-config-next": "16.1.6",
- "shadcn": "^3.8.5",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.5.7",
+ "globals": "^17.13.0",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
- "typescript": "5.9.3"
+ "typescript": "5.9.3",
+ "typescript-eslint": "^8.71.2",
+ "vite": "^8.3.4"
}
}
diff --git a/src/app/favicon.ico b/public/favicon.ico
similarity index 100%
rename from src/app/favicon.ico
rename to public/favicon.ico
diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx
index f31bd72..0397c8a 100644
--- a/src/app/(auth)/login/page.tsx
+++ b/src/app/(auth)/login/page.tsx
@@ -1,9 +1,12 @@
-import type { Metadata } from "next";
+import { Navigate } from "react-router";
+import { useSession } from "next-auth/react";
import { LoginForm } from "@/features/auth/components/login-form";
-export const metadata: Metadata = { title: "Connexion" };
-
export default function LoginPage() {
+ // Déjà connecté : l'accueil (le serveur fait de même pour un accès direct).
+ const { status } = useSession();
+ if (status === "authenticated") return ;
+
return (
diff --git a/src/app/(dashboard)/admin/synchronisation/client.tsx b/src/app/(dashboard)/admin/synchronisation/client.tsx
index 8171871..4f0dd8a 100644
--- a/src/app/(dashboard)/admin/synchronisation/client.tsx
+++ b/src/app/(dashboard)/admin/synchronisation/client.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
CalendarClock, Play, Square, RefreshCw, Loader2, AlertTriangle,
diff --git a/src/app/(dashboard)/admin/synchronisation/page.tsx b/src/app/(dashboard)/admin/synchronisation/page.tsx
index 86b6644..5ddd4d0 100644
--- a/src/app/(dashboard)/admin/synchronisation/page.tsx
+++ b/src/app/(dashboard)/admin/synchronisation/page.tsx
@@ -1,17 +1,16 @@
-import type { Metadata } from "next";
-import { redirect } from "next/navigation";
-import { verifierAdmin } from "@/lib/authz";
+import { AdminOnly } from "@/components/shared/admin-only";
import { SynchronisationClient } from "./client";
-export const metadata: Metadata = { title: "Synchronisation" };
-
/**
* Paramétrage de la synchronisation nocturne des fournisseurs.
*
- * L'accès admin est déjà imposé par le middleware (préfixe /admin), sur le rôle
- * du jeton ; la page le revérifie en base, comme les routes /api/admin/sync.
+ * L'accès admin est déjà imposé par le serveur (préfixe /admin, rôle relu en
+ * base) ; la page le revérifie pour une navigation dans l'application.
*/
-export default async function SynchronisationPage() {
- if (!(await verifierAdmin()).ok) redirect("/dashboard");
- return ;
+export default function SynchronisationPage() {
+ return (
+
+
+
+ );
}
diff --git a/src/app/(dashboard)/analytics/client.tsx b/src/app/(dashboard)/analytics/client.tsx
index 81e30fb..244d594 100644
--- a/src/app/(dashboard)/analytics/client.tsx
+++ b/src/app/(dashboard)/analytics/client.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useRouter } from "next/navigation";
import { useMemo, useTransition } from "react";
import { Loader2 } from "lucide-react";
diff --git a/src/app/(dashboard)/analytics/page.tsx b/src/app/(dashboard)/analytics/page.tsx
index 3f984df..5972ac5 100644
--- a/src/app/(dashboard)/analytics/page.tsx
+++ b/src/app/(dashboard)/analytics/page.tsx
@@ -1,15 +1,13 @@
-import type { Metadata } from "next";
import Link from "next/link";
import { CalendarRange, RotateCcw } from "lucide-react";
-import { pgGetCaByFournisseur, pgGetCaByNomenclature } from "@/lib/pg-ff-client";
-import { cachedFF } from "@/lib/ff-cache";
+import type { CaByFournisseurRow, CaByNomenclatureRow } from "@/types/ff";
+import { fetchPage } from "@/lib/rpc";
+import { usePageResult, usePageSearchParams } from "@/lib/page-data";
import { PageHeader } from "@/components/ui/page-header";
import { ErrorState } from "@/components/ui/states";
import { Button } from "@/components/ui/button";
import { AnalyticsClient, type AnalyticsRow, type ModeAnalytics, type OptionMois } from "./client";
-export const metadata: Metadata = { title: "Ventes par mois" };
-
const NOMS_MOIS = [
"janvier", "février", "mars", "avril", "mai", "juin",
"juillet", "août", "septembre", "octobre", "novembre", "décembre",
@@ -82,10 +80,10 @@ function pivotData(
return result;
}
-export default async function AnalyticsPage(props: {
- searchParams: Promise>;
-}) {
- const searchParams = await props.searchParams;
+type LigneCa = { code: string; label: string; site: string; mois: string; ca_ttc: number };
+
+export default function AnalyticsPage() {
+ const searchParams = usePageSearchParams();
// Toute autre valeur que « fournisseur » affichait déjà la vue par famille.
const mode: ModeAnalytics = ((searchParams.mode as string) || "fournisseur") === "fournisseur" ? "fournisseur" : "nomenclature";
const moisParam = (searchParams.mois as string) || "";
@@ -108,36 +106,34 @@ export default async function AnalyticsPage(props: {
moisDisponibles.push({ value: mois, label: libelleMois(mois) });
}
- let pivotted: AnalyticsRow[] | null = null;
- let erreur: string | null = null;
- try {
- let rows: Array<{ code: string; label: string; site: string; mois: string; ca_ttc: number }> =
- [];
-
+ // Lignes de la base FF, mises en cache par le serveur (mêmes clés qu'avant).
+ const resultat = usePageResult(`analytics?${mode}:${mois}:${moisN1}`, async (): Promise => {
if (mode === "fournisseur") {
- const result = await cachedFF(`ca-fournisseur:${mois}:${moisN1}`, () => pgGetCaByFournisseur(mois, moisN1));
- rows = result.map((r) => ({
+ const result = await fetchPage("analytics", { mode, mois, moisN1 });
+ return result.map((r) => ({
code: r.code,
label: r.nom,
site: r.site,
mois: r.mois,
ca_ttc: r.ca_ttc,
}));
- } else {
- const result = await cachedFF(`ca-nomenclature:${mois}:${moisN1}`, () => pgGetCaByNomenclature(mois, moisN1));
- rows = result.map((r) => ({
- code: r.code,
- label: `${r.code} — ${r.libelle}`,
- site: r.site,
- mois: r.mois,
- ca_ttc: r.ca_ttc,
- }));
}
+ const result = await fetchPage("analytics", { mode, mois, moisN1 });
+ return result.map((r) => ({
+ code: r.code,
+ label: `${r.code} — ${r.libelle}`,
+ site: r.site,
+ mois: r.mois,
+ ca_ttc: r.ca_ttc,
+ }));
+ });
- pivotted = pivotData(rows, mois, moisN1, mode);
- } catch (e) {
- console.error("[analytics] chargement impossible :", e);
- erreur = e instanceof Error ? e.message : String(e);
+ let pivotted: AnalyticsRow[] | null = null;
+ let erreur: string | null = null;
+ if (resultat.ok) {
+ pivotted = pivotData(resultat.data, mois, moisN1, mode);
+ } else {
+ erreur = resultat.error;
}
return (
diff --git a/src/app/(dashboard)/commandes-auto/cadencier-client.tsx b/src/app/(dashboard)/commandes-auto/cadencier-client.tsx
index 01d688a..4d71dd2 100644
--- a/src/app/(dashboard)/commandes-auto/cadencier-client.tsx
+++ b/src/app/(dashboard)/commandes-auto/cadencier-client.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useMemo, useState, useTransition, type FormEvent } from "react";
import { AlertTriangle, CalendarClock, Plus, Power, Trash2 } from "lucide-react";
import {
@@ -217,8 +215,9 @@ function SectionMagasin({
/**
* Exécute une action serveur et en rend compte : message de réussite, ou
* message d'erreur (refus de l'action ou exception) — jamais d'échec muet.
- * Pas de router.refresh() : les actions appellent déjà revalidatePath, dont
- * la réponse rafraîchit la page. Les deux ensemble rechargeaient tout deux fois.
+ * Pas de router.refresh() : les actions rafraîchissent déjà la page après une
+ * réussite (cf. features/commandes-auto/actions.ts). Les deux ensemble
+ * rechargeaient tout deux fois.
*/
function executer(action: () => Promise, messages: { succes: string; echec: string }): Promise {
return new Promise((resolve) => {
diff --git a/src/app/(dashboard)/commandes-auto/client.tsx b/src/app/(dashboard)/commandes-auto/client.tsx
index 6b0491a..6a66daf 100644
--- a/src/app/(dashboard)/commandes-auto/client.tsx
+++ b/src/app/(dashboard)/commandes-auto/client.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useMemo } from "react";
import { ShoppingCart } from "lucide-react";
import type { PgCommandeAutoRow } from "./page";
diff --git a/src/app/(dashboard)/commandes-auto/page.tsx b/src/app/(dashboard)/commandes-auto/page.tsx
index f74f669..2fe9941 100644
--- a/src/app/(dashboard)/commandes-auto/page.tsx
+++ b/src/app/(dashboard)/commandes-auto/page.tsx
@@ -1,33 +1,30 @@
-import type { Metadata } from "next";
import { ShoppingCart } from "lucide-react";
-import { pgGetCommandesAuto, type PgCommandeAutoRow } from "@/lib/pg-ff-client";
-import { listCadences, getFournisseursPourCadence } from "@/features/commandes-auto/actions";
+import type { PgCommandeAutoRow } from "@/types/ff";
+import type { CadenceView } from "@/features/commandes-auto/actions";
+import { fetchPage } from "@/lib/rpc";
+import { usePageData, usePageSearchParams } from "@/lib/page-data";
import { PageHeader } from "@/components/ui/page-header";
import { CommandesAutoTabs, type Onglet } from "./tabs";
-import { cachedFF } from "@/lib/ff-cache";
export type { PgCommandeAutoRow };
-export const metadata: Metadata = { title: "Commandes fournisseurs" };
+/** Données de la page : propositions de l'API FF, cadencier et référentiel fournisseurs. */
+interface DonneesCommandesAuto {
+ rows: PgCommandeAutoRow[];
+ cadences: CadenceView[];
+ fournisseurs: { code: string; nom: string }[];
+}
-// Données live (DB + API FF Nancy) : rendu à la requête, jamais prérendu au build.
-export const dynamic = "force-dynamic";
-
-export default async function CommandesAutoPage(props: { searchParams: Promise<{ onglet?: string | string[] }> }) {
- const { onglet } = await props.searchParams;
+// Données live (DB + API FF Nancy) : relues à chaque affichage. Les propositions
+// sont gardées 2 minutes par le serveur, pour que chaque modification du
+// cadencier — qui rafraîchit la page — n'attende pas de nouveau toute l'API.
+export default function CommandesAutoPage() {
+ const { onglet } = usePageSearchParams();
const ongletInitial: Onglet = onglet === "cadencier" ? "cadencier" : "propositions";
- const [rows, cadences, fournisseurs] = await Promise.all([
- // Propositions de l'API FF (un appel, plus un par fournisseur sans franco) :
- // gardées 2 minutes, pour que chaque modification du cadencier — qui
- // re-rend la page — n'attende pas de nouveau toute l'API.
- cachedFF("commandes-auto", () => pgGetCommandesAuto(), {
- ttlMs: 2 * 60 * 1000,
- cacheIf: (rows) => rows.length > 0,
- }),
- listCadences(),
- getFournisseursPourCadence(),
- ]);
+ const { rows, cadences, fournisseurs } = usePageData("commandes-auto", () =>
+ fetchPage("commandes-auto"),
+ );
return (
diff --git a/src/app/(dashboard)/commandes-auto/tabs.tsx b/src/app/(dashboard)/commandes-auto/tabs.tsx
index 4ff1652..90e2d37 100644
--- a/src/app/(dashboard)/commandes-auto/tabs.tsx
+++ b/src/app/(dashboard)/commandes-auto/tabs.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { ShoppingCart, CalendarClock } from "lucide-react";
import { Tabs, useUrlTab } from "@/components/ui/tabs";
import { CommandesAutoClient } from "./client";
diff --git a/src/app/(dashboard)/dashboard/page.tsx b/src/app/(dashboard)/dashboard/page.tsx
index 75e21a9..4653769 100644
--- a/src/app/(dashboard)/dashboard/page.tsx
+++ b/src/app/(dashboard)/dashboard/page.tsx
@@ -1,8 +1,8 @@
-import type { Metadata } from "next";
import Link from "next/link";
-import { unstable_cache } from "next/cache";
import { BarChart3, Euro, House, Receipt, ShoppingBasket, ShoppingCart, Store } from "lucide-react";
-import { pgGetDashboardData, type DashboardSiteStats, type DashboardSiteTop10, type DashboardTopItem } from "@/lib/pg-ff-client";
+import type { DashboardData, DashboardSiteStats, DashboardSiteTop10, DashboardTopItem } from "@/types/ff";
+import { fetchPage } from "@/lib/rpc";
+import { usePageResult } from "@/lib/page-data";
import { PageHeader } from "@/components/ui/page-header";
import { StatCard } from "@/components/ui/stat-card";
import { Card, CardHeader } from "@/components/ui/card";
@@ -13,15 +13,6 @@ import { LIBELLE_TOUS_MAGASINS, nomMagasin } from "@/lib/magasins";
import { fmtDecimal1, fmtEntier, fmtEur2 } from "@/lib/format";
import { couleurMarge } from "@/lib/marge";
-export const metadata: Metadata = { title: "Accueil" };
-
-const getCachedDashboardData = unstable_cache(
- pgGetDashboardData,
- ["dashboard-data"],
- // 30 minutes : ce sont les ventes de la veille, elles ne changent pas dans la journée.
- { revalidate: 1800 }
-);
-
// ---------------------------------------------------------------------------
// Calculs
// ---------------------------------------------------------------------------
@@ -203,25 +194,23 @@ function TitreSection({ titre, description }: { titre: string; description?: Rea
// Page
// ---------------------------------------------------------------------------
-export default async function DashboardPage() {
- let data;
- try {
- data = await getCachedDashboardData();
- } catch (e) {
- console.error("[Dashboard] pgGetDashboardData failed:", e);
+export default function DashboardPage() {
+ // Mis en cache 30 minutes par le serveur : ce sont les ventes de la veille.
+ const resultat = usePageResult("dashboard", () => fetchPage
("dashboard"));
+ if (!resultat.ok) {
return (
);
}
- const { dateHier, dateN1, sites, top10BySite } = data;
+ const { dateHier, dateN1, sites, top10BySite } = resultat.data;
const totalCa = sites.reduce((s, r) => s + r.ca_hier, 0);
const totalCaN1 = sites.reduce((s, r) => s + r.ca_n1, 0);
diff --git a/src/app/(dashboard)/error.tsx b/src/app/(dashboard)/error.tsx
index 133e216..278f3ae 100644
--- a/src/app/(dashboard)/error.tsx
+++ b/src/app/(dashboard)/error.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useEffect } from "react";
import { RotateCcw } from "lucide-react";
import { ErrorState } from "@/components/ui/states";
diff --git a/src/app/(dashboard)/exports/page.tsx b/src/app/(dashboard)/exports/page.tsx
index 151dddf..c9c859a 100644
--- a/src/app/(dashboard)/exports/page.tsx
+++ b/src/app/(dashboard)/exports/page.tsx
@@ -1,6 +1,6 @@
-import { redirect } from "next/navigation";
+import { Navigate } from "react-router";
/** Ancienne adresse, conservée pour les favoris : voir /historique. */
export default function ExportsPage() {
- redirect("/historique?vue=exports");
+ return ;
}
diff --git a/src/app/(dashboard)/grid/page.tsx b/src/app/(dashboard)/grid/page.tsx
index b8d30a3..53633e9 100644
--- a/src/app/(dashboard)/grid/page.tsx
+++ b/src/app/(dashboard)/grid/page.tsx
@@ -1,23 +1,11 @@
-import type { Metadata } from "next";
-import { auth } from "@/lib/auth";
+import { useSessionResolue } from "next-auth/react";
import { getFournisseurs, getMagasins } from "@/features/grid/actions";
+import { usePageData, usePageSearchParams } from "@/lib/page-data";
import { GridClient } from "@/features/grid/components/grid-client";
import { SupplierSelectionLanding } from "@/features/grid/components/supplier-selection-landing";
-export const metadata: Metadata = { title: "Révision d'assortiment" };
-
-interface GridPageProps {
- searchParams: Promise<{
- fournisseur?: string;
- magasin?: string;
- code1?: string;
- code2?: string;
- code3?: string;
- }>;
-}
-
-export default async function GridPage({ searchParams }: GridPageProps) {
- const params = await searchParams;
+export default function GridPage() {
+ const params = usePageSearchParams();
const codeFournisseur = params.fournisseur;
const magasin = params.magasin ?? "TOTAL";
const filters = {
@@ -27,13 +15,10 @@ export default async function GridPage({ searchParams }: GridPageProps) {
code3: params.code3 ? String(params.code3).split(",").filter(Boolean) : null,
};
- // 1. Fetch available suppliers & stores (et les droits, lus une fois côté serveur)
- const [fournisseurs, magasins, session] = await Promise.all([
- getFournisseurs(),
- getMagasins(),
- auth(),
- ]);
- const isAdmin = (session?.user as { role?: string } | undefined)?.role === "admin";
+ // 1. Fetch available suppliers & stores (et les droits, lus une fois avant le rendu)
+ const [fournisseurs, magasins] = usePageData("grid", () => Promise.all([getFournisseurs(), getMagasins()]));
+ const session = useSessionResolue();
+ const isAdmin = session?.user.role === "admin";
// 2. If no supplier selected, show compact selection UI
if (!codeFournisseur) {
diff --git a/src/app/(dashboard)/historique/page.tsx b/src/app/(dashboard)/historique/page.tsx
index 2aefed6..0963805 100644
--- a/src/app/(dashboard)/historique/page.tsx
+++ b/src/app/(dashboard)/historique/page.tsx
@@ -1,10 +1,8 @@
-import type { Metadata } from "next";
import { History } from "lucide-react";
import { PageHeader } from "@/components/ui/page-header";
+import { usePageSearchParams } from "@/lib/page-data";
import { HistoriqueTabs } from "./tabs";
-export const metadata: Metadata = { title: "Historique" };
-
/**
* Historique des sessions de révision et des exports Excel.
*
@@ -12,8 +10,8 @@ export const metadata: Metadata = { title: "Historique" };
* filtrée différemment (et dont la seconde s'intitulait « Historique d'arbitrage »).
* Chacun ne voit que ses propres enregistrements.
*/
-export default async function HistoriquePage(props: { searchParams: Promise<{ vue?: string }> }) {
- const { vue } = await props.searchParams;
+export default function HistoriquePage() {
+ const { vue } = usePageSearchParams();
return (
>;
-}) {
- const searchParams = await props.searchParams;
+export default function HitParadePage() {
+ const searchParams = usePageSearchParams();
const defaults = defaultDates();
- const dateDebut = (searchParams.debut as string) || defaults.debut;
- const dateFin = (searchParams.fin as string) || defaults.fin;
+ const dateDebut = searchParams.debut || defaults.debut;
+ const dateFin = searchParams.fin || defaults.fin;
+
+ // Lignes de la base FF, mises en cache par le serveur.
+ const resultat = usePageResult(`hit-parade?${dateDebut}:${dateFin}`, () =>
+ fetchPage("hit-parade", { debut: dateDebut, fin: dateFin }),
+ );
let pivotted: HitParadePivotRow[] | null = null;
let erreur: string | null = null;
- try {
- const rows = await cachedFF(`hit-parade:${dateDebut}:${dateFin}`, () => pgGetHitParade(dateDebut, dateFin));
- pivotted = pivotHitParade(rows);
- } catch (e) {
- console.error("[hit-parade] chargement impossible :", e);
- erreur = e instanceof Error ? e.message : String(e);
+ if (resultat.ok) {
+ pivotted = pivotHitParade(resultat.data);
+ } else {
+ erreur = resultat.error;
}
return (
diff --git a/src/app/(dashboard)/layout.tsx b/src/app/(dashboard)/layout.tsx
index 929f166..e4cbc52 100644
--- a/src/app/(dashboard)/layout.tsx
+++ b/src/app/(dashboard)/layout.tsx
@@ -1,13 +1,23 @@
+import { useEffect, useRef } from "react";
+import { useLocation } from "react-router";
import { Sidebar } from "@/components/shared/sidebar";
import { Header } from "@/components/shared/header";
-export default async function DashboardLayout({ children }: { children: React.ReactNode }) {
+export default function DashboardLayout({ children }: { children: React.ReactNode }) {
+ const { pathname } = useLocation();
+ const contenu = useRef(null);
+
+ // Changement de page : on repart du haut, comme une navigation Next.js.
+ useEffect(() => {
+ contenu.current?.scrollTo({ top: 0 });
+ }, [pathname]);
+
return (
-
+
{children}
diff --git a/src/app/(dashboard)/produits/fiche.tsx b/src/app/(dashboard)/produits/fiche.tsx
index 65ba6b2..b14f871 100644
--- a/src/app/(dashboard)/produits/fiche.tsx
+++ b/src/app/(dashboard)/produits/fiche.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
diff --git a/src/app/(dashboard)/produits/opportunites.tsx b/src/app/(dashboard)/produits/opportunites.tsx
index 5594d65..9d11cce 100644
--- a/src/app/(dashboard)/produits/opportunites.tsx
+++ b/src/app/(dashboard)/produits/opportunites.tsx
@@ -1,9 +1,7 @@
-"use client";
-
import { useState } from "react";
import Link from "next/link";
import { Loader2, RefreshCw, TrendingUp } from "lucide-react";
-import type { PgOpportuniteRow } from "@/lib/pg-ff-client";
+import type { PgOpportuniteRow } from "@/types/ff";
import { Button } from "@/components/ui/button";
import { DataTable, type DataColumn } from "@/components/ui/data-table";
import { EmptyState, ErrorState } from "@/components/ui/states";
diff --git a/src/app/(dashboard)/produits/page.tsx b/src/app/(dashboard)/produits/page.tsx
index d9b4a75..422c33e 100644
--- a/src/app/(dashboard)/produits/page.tsx
+++ b/src/app/(dashboard)/produits/page.tsx
@@ -1,6 +1,7 @@
-import type { Metadata } from "next";
import { PackageSearch, SearchX } from "lucide-react";
-import { getProduitFiche, getProduitFicheByCodeCentrale } from "@/features/produits/api/get-produit-fiche";
+import type { ProduitFiche } from "@/features/produits/types";
+import { fetchPage } from "@/lib/rpc";
+import { usePageData, usePageSearchParams } from "@/lib/page-data";
import { PageHeader } from "@/components/ui/page-header";
import { EmptyState } from "@/components/ui/states";
import { Terme } from "@/components/ui/tooltip";
@@ -8,33 +9,29 @@ import { ProduitSearchBar } from "./search-bar";
import { ProduitResults } from "./results";
import { ProduitFicheView } from "./fiche";
-export const metadata: Metadata = { title: "Recherche produit" };
-
-export const dynamic = "force-dynamic";
-
/**
* Recherche produit — **Qlik d'abord**, catalogue FF Nancy ensuite.
*
* - `?q=…` → liste de résultats (chargée côté client : l'extraction Qlik
- * prend plusieurs secondes, on ne bloque pas le rendu serveur)
+ * prend plusieurs secondes, on ne bloque pas l'affichage)
* - `?codein=…` → fiche d'un produit de notre catalogue (URL partageable)
* - `?cc=…` → fiche d'un produit du réseau par son code centrale, qu'il
* soit référencé chez nous ou non
*/
-export default async function ProduitsPage(props: {
- searchParams: Promise<{ q?: string; codein?: string; cc?: string }>;
-}) {
- const searchParams = await props.searchParams;
+export default function ProduitsPage() {
+ const searchParams = usePageSearchParams();
const q = (searchParams.q ?? "").trim();
const codein = (searchParams.codein ?? "").trim();
const codeCentrale = (searchParams.cc ?? "").trim();
- const fiche = codein
- ? await getProduitFiche(codein)
- : codeCentrale
- ? await getProduitFicheByCodeCentrale(codeCentrale)
- : null;
const ficheDemandee = Boolean(codein || codeCentrale);
+ const fiche = usePageData(`produit-fiche?${codein}:${codeCentrale}`, (): Promise
=>
+ codein
+ ? fetchPage("produit-fiche", { codein })
+ : codeCentrale
+ ? fetchPage("produit-fiche", { cc: codeCentrale })
+ : Promise.resolve(null),
+ );
return (
diff --git a/src/app/(dashboard)/produits/results.tsx b/src/app/(dashboard)/produits/results.tsx
index ed8d4fe..d8b9142 100644
--- a/src/app/(dashboard)/produits/results.tsx
+++ b/src/app/(dashboard)/produits/results.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useEffect, useMemo, useState, type ReactNode } from "react";
import Link from "next/link";
import { PackageSearch, Loader2, RefreshCw, AlertTriangle, Database, Globe } from "lucide-react";
diff --git a/src/app/(dashboard)/produits/search-bar.tsx b/src/app/(dashboard)/produits/search-bar.tsx
index dc55282..f5bb2d6 100644
--- a/src/app/(dashboard)/produits/search-bar.tsx
+++ b/src/app/(dashboard)/produits/search-bar.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useState } from "react";
import { useRouter } from "next/navigation";
import { Search, X } from "lucide-react";
diff --git a/src/app/(dashboard)/publicites/client.tsx b/src/app/(dashboard)/publicites/client.tsx
index 56337ea..5a05a54 100644
--- a/src/app/(dashboard)/publicites/client.tsx
+++ b/src/app/(dashboard)/publicites/client.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useMemo, useTransition } from "react";
import { useRouter } from "next/navigation";
import { History, Info, Megaphone, RotateCcw } from "lucide-react";
diff --git a/src/app/(dashboard)/publicites/page.tsx b/src/app/(dashboard)/publicites/page.tsx
index 932b555..d760255 100644
--- a/src/app/(dashboard)/publicites/page.tsx
+++ b/src/app/(dashboard)/publicites/page.tsx
@@ -1,10 +1,8 @@
-import type { Metadata } from "next";
import { Megaphone } from "lucide-react";
import { PageHeader } from "@/components/ui/page-header";
+import { fetchPage } from "@/lib/rpc";
+import { usePageData, usePageSearchParams } from "@/lib/page-data";
import { PublicitesClient } from "./client";
-import { cachedFF } from "@/lib/ff-cache";
-
-export const metadata: Metadata = { title: "Publicités" };
export interface Publicite {
tcr_code: string;
@@ -44,80 +42,30 @@ export interface PubliciteHistorique {
qte_totale: number;
}
-const FF_API_BASE = process.env.FF_API_BASE_URL ?? "https://api.ffnancy.fr";
-const PAGE_SIZE = 50;
-/** Délai maximal d'un appel à l'API FF : sans lui, une API muette figeait la page. */
-const FF_API_TIMEOUT_MS = 15_000;
/**
- * Réponses de l'API gardées 10 minutes (les erreurs ne le sont jamais) : la liste
- * et l'historique étaient re-téléchargés à chaque clic sur un filtre ou une page.
+ * Données de la page, lues par le serveur sur l'API FF (réponses gardées
+ * 10 minutes, jamais les erreurs) : une API en panne est signalée dans
+ * `erreurPublicites` / `erreurHistorique`, pas par une exception.
*/
-const PUB_CACHE_TTL_MS = 10 * 60 * 1000;
-
-type PublicitesResult = { data: Publicite[]; total: number; pages: number; error?: string };
-
-function fetchPublicites(statut: string, page: number): Promise
{
- return cachedFF(`publicites:${statut}:${page}`, () => fetchPublicitesApi(statut, page), {
- ttlMs: PUB_CACHE_TTL_MS,
- cacheIf: (r) => !r.error,
- });
+interface DonneesPublicites {
+ publicites: Publicite[];
+ total: number;
+ pages: number;
+ erreurPublicites?: string;
+ historique: PubliciteHistorique[];
+ erreurHistorique?: string;
+ pageSize: number;
}
-async function fetchPublicitesApi(statut: string, page: number): Promise {
- const params = new URLSearchParams({ page: String(page), limit: String(PAGE_SIZE) });
- if (statut && statut !== "toutes") params.set("statut", statut);
- try {
- const res = await fetch(`${FF_API_BASE}/api/publicites?${params}`, {
- cache: "no-store",
- signal: AbortSignal.timeout(FF_API_TIMEOUT_MS),
- });
- if (!res.ok) return { data: [], total: 0, pages: 0, error: `Erreur API: ${res.status} ${res.statusText}` };
- const json = await res.json();
- return {
- data: (json.publicites ?? []) as Publicite[],
- total: Number(json.total ?? 0),
- pages: Number(json.pages ?? 0),
- };
- } catch (e: unknown) {
- return { data: [], total: 0, pages: 0, error: `Impossible de joindre l'API: ${e instanceof Error ? e.message : String(e)}` };
- }
-}
-
-type HistoriqueResult = { data: PubliciteHistorique[]; error?: string };
-
-function fetchHistorique(): Promise {
- return cachedFF("publicites-historique", fetchHistoriqueApi, {
- ttlMs: PUB_CACHE_TTL_MS,
- cacheIf: (r) => !r.error,
- });
-}
-
-async function fetchHistoriqueApi(): Promise {
- try {
- const res = await fetch(`${FF_API_BASE}/api/publicites/historique`, {
- cache: "no-store",
- signal: AbortSignal.timeout(FF_API_TIMEOUT_MS),
- });
- if (!res.ok) return { data: [], error: `Erreur historique: ${res.status}` };
- const json = await res.json();
- return { data: (json.publicites ?? []) as PubliciteHistorique[] };
- } catch (e: unknown) {
- return { data: [], error: `Impossible de joindre l'API: ${e instanceof Error ? e.message : String(e)}` };
- }
-}
-
-export default async function PublicitesPage(props: {
- searchParams: Promise>;
-}) {
- const searchParams = await props.searchParams;
+export default function PublicitesPage() {
+ const searchParams = usePageSearchParams();
const vue = String(searchParams.vue ?? "publicites");
const statut = String(searchParams.statut ?? "toutes");
const page = Math.max(1, Number(searchParams.page) || 1);
- const [pubResult, histoResult] = await Promise.all([
- fetchPublicites(statut, page),
- fetchHistorique(),
- ]);
+ const donnees = usePageData(`publicites?${statut}:${page}`, () =>
+ fetchPage("publicites", { statut, page }),
+ );
return (
@@ -130,13 +78,13 @@ export default async function PublicitesPage(props: {
vueInitiale={vue === "historique" ? "historique" : "publicites"}
statut={statut}
page={page}
- pageSize={PAGE_SIZE}
- publicites={pubResult.data}
- total={pubResult.total}
- pages={pubResult.pages}
- erreurPublicites={pubResult.error}
- historique={histoResult.data}
- erreurHistorique={histoResult.error}
+ pageSize={donnees.pageSize}
+ publicites={donnees.publicites}
+ total={donnees.total}
+ pages={donnees.pages}
+ erreurPublicites={donnees.erreurPublicites}
+ historique={donnees.historique}
+ erreurHistorique={donnees.erreurHistorique}
/>
);
diff --git a/src/app/(dashboard)/settings/client.tsx b/src/app/(dashboard)/settings/client.tsx
index 6a15b0c..0cb70b7 100644
--- a/src/app/(dashboard)/settings/client.tsx
+++ b/src/app/(dashboard)/settings/client.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useCallback, useEffect, useState, type ReactNode } from "react";
import {
AlertCircle,
diff --git a/src/app/(dashboard)/settings/page.tsx b/src/app/(dashboard)/settings/page.tsx
index b6997ea..de20149 100644
--- a/src/app/(dashboard)/settings/page.tsx
+++ b/src/app/(dashboard)/settings/page.tsx
@@ -1,21 +1,19 @@
-import type { Metadata } from "next";
-import { redirect } from "next/navigation";
-import { verifierAdmin } from "@/lib/authz";
+import { AdminOnly } from "@/components/shared/admin-only";
+import { usePageSearchParams } from "@/lib/page-data";
import { ParametresClient } from "./client";
-export const metadata: Metadata = { title: "Paramètres" };
-
/**
* Paramètres (administrateurs) : connexions aux sources de données, comptes
* utilisateurs, accès à l'API et journal serveur, rangés en onglets.
*
- * Composant serveur minimal : il lit l'onglet demandé (`?onglet=`) pour que le
- * lien se partage et survive au rechargement, puis rend la page cliente.
+ * Page minimale : elle lit l'onglet demandé (`?onglet=`) pour que le lien se
+ * partage et survive au rechargement, puis rend la page cliente.
*/
-export default async function SettingsPage(props: { searchParams: Promise<{ onglet?: string }> }) {
- // Le middleware filtre déjà sur le rôle du jeton ; ici, rôle relu en base.
- if (!(await verifierAdmin()).ok) redirect("/dashboard");
-
- const { onglet } = await props.searchParams;
- return ;
+export default function SettingsPage() {
+ const { onglet } = usePageSearchParams();
+ return (
+
+
+
+ );
}
diff --git a/src/app/(dashboard)/snapshots/page.tsx b/src/app/(dashboard)/snapshots/page.tsx
index 5b117e0..dbf24df 100644
--- a/src/app/(dashboard)/snapshots/page.tsx
+++ b/src/app/(dashboard)/snapshots/page.tsx
@@ -1,6 +1,6 @@
-import { redirect } from "next/navigation";
+import { Navigate } from "react-router";
/** Ancienne adresse, conservée pour les favoris : voir /historique. */
export default function SnapshotsPage() {
- redirect("/historique");
+ return ;
}
diff --git a/src/app/(dashboard)/stock-negatif/client.tsx b/src/app/(dashboard)/stock-negatif/client.tsx
index 995d440..14e95c0 100644
--- a/src/app/(dashboard)/stock-negatif/client.tsx
+++ b/src/app/(dashboard)/stock-negatif/client.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useRouter } from "next/navigation";
import { useState, useMemo, useEffect, useTransition, type ReactNode } from "react";
import { Loader2 } from "lucide-react";
diff --git a/src/app/(dashboard)/stock-negatif/page.tsx b/src/app/(dashboard)/stock-negatif/page.tsx
index 19d70a4..dabe050 100644
--- a/src/app/(dashboard)/stock-negatif/page.tsx
+++ b/src/app/(dashboard)/stock-negatif/page.tsx
@@ -1,8 +1,8 @@
-import type { Metadata } from "next";
import Link from "next/link";
import { PackageMinus, RotateCcw } from "lucide-react";
-import { pgGetStockNegatif, PgStockNegatifRow, pgGetStockSansVente, PgStockSansVenteRow, pgGetSansVente6Mois, PgSansVente6MoisRow } from "@/lib/pg-ff-client";
-import { cachedFF } from "@/lib/ff-cache";
+import type { PgStockNegatifRow, PgStockSansVenteRow, PgSansVente6MoisRow } from "@/types/ff";
+import { fetchPage } from "@/lib/rpc";
+import { usePageResult, usePageSearchParams } from "@/lib/page-data";
import { PageHeader } from "@/components/ui/page-header";
import { ErrorState } from "@/components/ui/states";
import { Button } from "@/components/ui/button";
@@ -10,36 +10,23 @@ import { GestionStockClient } from "./client";
export type { PgStockNegatifRow, PgStockSansVenteRow, PgSansVente6MoisRow };
-export const metadata: Metadata = { title: "Stocks à surveiller" };
-
interface DonneesStock {
rowsNegatif: PgStockNegatifRow[];
rowsSansVente: PgStockSansVenteRow[];
rowsSansVente6Mois: PgSansVente6MoisRow[];
}
-export default async function GestionStockPage(props: {
- searchParams: Promise>;
-}) {
- const searchParams = await props.searchParams;
- const magasin = (searchParams.magasin as string) || "";
- const tab = (searchParams.tab as string) || "negatif";
+export default function GestionStockPage() {
+ const searchParams = usePageSearchParams();
+ const magasin = searchParams.magasin || "";
+ const tab = searchParams.tab || "negatif";
- // Données FF recopiées chaque nuit : mises en cache (cf. lib/ff-cache.ts).
- const site = magasin || undefined;
- let donnees: DonneesStock | null = null;
- let erreur: string | null = null;
- try {
- const [rowsNegatif, rowsSansVente, rowsSansVente6Mois] = await Promise.all([
- cachedFF(`stock-negatif:${magasin}`, () => pgGetStockNegatif(site)),
- cachedFF(`stock-sans-vente:${magasin}`, () => pgGetStockSansVente(site)),
- cachedFF(`stock-sans-vente-6-mois:${magasin}`, () => pgGetSansVente6Mois(site)),
- ]);
- donnees = { rowsNegatif, rowsSansVente, rowsSansVente6Mois };
- } catch (e) {
- console.error("[stock-negatif] chargement impossible :", e);
- erreur = e instanceof Error ? e.message : String(e);
- }
+ // Données FF recopiées chaque nuit : mises en cache par le serveur.
+ const resultat = usePageResult(`stock-negatif?${magasin}`, () =>
+ fetchPage("stock-negatif", { magasin }),
+ );
+ const donnees: DonneesStock | null = resultat.ok ? resultat.data : null;
+ const erreur: string | null = resultat.ok ? null : resultat.error;
const params = new URLSearchParams();
if (magasin) params.set("magasin", magasin);
diff --git a/src/app/api/admin/grid-warmup/route.ts b/src/app/api/admin/grid-warmup/route.ts
deleted file mode 100644
index 6e56bbd..0000000
--- a/src/app/api/admin/grid-warmup/route.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { adminOuReponse } from "@/lib/authz";
-import { pgGetFournisseurs } from "@/lib/pg-ff-client";
-import { getProductRows } from "@/features/grid/api/get-product-rows";
-import { listGridSuppliers } from "@/lib/grid-store";
-
-// Le préchauffage parcourt tous les fournisseurs : c'est long par nature. On rend la
-// main immédiatement et le client interroge GET pour suivre l'avancement.
-export const maxDuration = 300;
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * Préchauffage de l'instantané de grille (`grid_rows`).
- *
- * L'API `/api/v1` ne calcule jamais : elle lit un instantané écrit quand la Grille est
- * ouverte dans l'application. Sans préchauffage, un consommateur externe (ChatGPT) ne
- * verrait donc que les fournisseurs déjà consultés à la main.
- *
- * Ce job calcule chaque fournisseur une fois, séquentiellement — la persistance se fait
- * en effet de bord de `getProductRows()`. Séquentiel volontairement : le calcul est
- * lourd en SQL, le paralléliser saturerait PostgreSQL.
- */
-type WarmupStatus = "idle" | "running" | "success" | "error";
-
-interface WarmupJob {
- status: WarmupStatus;
- total: number;
- done: number;
- skipped: number;
- failed: number;
- currentFournisseur?: string;
- startedAt: string;
- finishedAt?: string;
- error?: string;
- lastErrors: string[];
-}
-
-let job: WarmupJob | null = null;
-
-function publicJob(j: WarmupJob | null) {
- if (!j) {
- return { status: "idle" as const, total: 0, done: 0, skipped: 0, failed: 0, lastErrors: [] };
- }
- return j;
-}
-
-async function runWarmup(j: WarmupJob, staleHours: number): Promise {
- try {
- const fournisseurs = await pgGetFournisseurs();
- // Les fournisseurs déjà calculés récemment sont sautés : un second passage
- // coûte alors quasiment rien, ce qui rend le bouton rejouable sans crainte.
- const existing = await listGridSuppliers();
- const freshLimit = Date.now() - staleHours * 3600_000;
- const fresh = new Set(
- existing
- .filter((s) => s.computedAt && new Date(s.computedAt).getTime() > freshLimit)
- .map((s) => s.codeFournisseur),
- );
-
- j.total = fournisseurs.length;
- console.log(`[grid-warmup] ${fournisseurs.length} fournisseurs, ${fresh.size} déjà à jour (< ${staleHours}h)`);
-
- for (const f of fournisseurs) {
- if (fresh.has(f.code)) {
- j.skipped++;
- continue;
- }
- j.currentFournisseur = `${f.code} — ${f.nom}`;
- try {
- await getProductRows({ codeFournisseur: f.code, magasin: "TOTAL", forceRefresh: true });
- j.done++;
- } catch (e) {
- j.failed++;
- const msg = `${f.code}: ${e instanceof Error ? e.message.slice(0, 120) : String(e)}`;
- // On garde une trace des derniers échecs sans faire exploser la mémoire.
- if (j.lastErrors.length < 10) j.lastErrors.push(msg);
- console.error("[grid-warmup]", msg);
- }
- }
-
- j.currentFournisseur = undefined;
- j.status = "success";
- j.finishedAt = new Date().toISOString();
- console.log(`[grid-warmup] terminé — ${j.done} calculés, ${j.skipped} à jour, ${j.failed} en échec`);
- } catch (e) {
- j.status = "error";
- j.error = e instanceof Error ? e.message : String(e);
- j.finishedAt = new Date().toISOString();
- console.error("[grid-warmup] échec global:", j.error);
- }
-}
-
-/** GET /api/admin/grid-warmup — avancement du préchauffage. */
-export async function GET() {
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
- return NextResponse.json({ success: true, ...publicJob(job) });
-}
-
-/**
- * POST /api/admin/grid-warmup?staleHours=24
- * Démarre le préchauffage en arrière-plan et répond immédiatement.
- */
-export async function POST(req: NextRequest) {
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- if (job?.status === "running") {
- return NextResponse.json({ success: true, ...publicJob(job) });
- }
-
- const raw = Number(req.nextUrl.searchParams.get("staleHours"));
- const staleHours = Number.isFinite(raw) ? Math.min(720, Math.max(0, raw)) : 24;
-
- job = {
- status: "running",
- total: 0,
- done: 0,
- skipped: 0,
- failed: 0,
- startedAt: new Date().toISOString(),
- lastErrors: [],
- };
- const current = job;
- console.log(`[grid-warmup] démarré (staleHours=${staleHours})`);
-
- void runWarmup(current, staleHours).catch((e) => {
- current.status = "error";
- current.error = e instanceof Error ? e.message : String(e);
- current.finishedAt = new Date().toISOString();
- });
-
- return NextResponse.json({ success: true, ...publicJob(job) });
-}
diff --git a/src/app/api/admin/sync/fournisseurs/route.ts b/src/app/api/admin/sync/fournisseurs/route.ts
deleted file mode 100644
index 292557e..0000000
--- a/src/app/api/admin/sync/fournisseurs/route.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { z } from "zod";
-import { asc, eq, inArray, sql } from "drizzle-orm";
-import { adminOuReponse } from "@/lib/authz";
-import { db } from "@/db";
-import { syncFournisseurs } from "@/db/schema";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * GET — la liste complète des fournisseurs paramétrés, avec l'état de leur
- * dernière synchronisation.
- *
- * Pas de pagination : quelques centaines de lignes tout au plus, et l'admin a
- * besoin de la vue d'ensemble pour décider qui cadencer.
- */
-export async function GET() {
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- const rows = await db
- .select()
- .from(syncFournisseurs)
- .orderBy(asc(sql`coalesce(${syncFournisseurs.nomFournisseur}, ${syncFournisseurs.codeFournisseur})`));
-
- return NextResponse.json({
- success: true,
- fournisseurs: rows,
- resume: {
- total: rows.length,
- actifsSql: rows.filter((r) => r.actifSql).length,
- actifsQlik: rows.filter((r) => r.actifQlik).length,
- desactivesAuto: rows.filter((r) => r.desactiveMotif).length,
- enEchecSql: rows.filter((r) => r.dernierSqlStatut === "echec").length,
- enEchecQlik: rows.filter((r) => r.dernierQlikStatut === "echec").length,
- jamaisSql: rows.filter((r) => !r.dernierSqlAt).length,
- },
- });
-}
-
-const patchSchema = z.object({
- /** Codes visés. Permet d'activer ou désactiver en masse depuis la page. */
- codes: z.array(z.string().min(1)).min(1).max(2000),
- actifSql: z.boolean().optional(),
- actifQlik: z.boolean().optional(),
-}).refine((v) => v.actifSql !== undefined || v.actifQlik !== undefined, {
- message: "Préciser au moins actifSql ou actifQlik",
-});
-
-/**
- * PATCH — active ou désactive des fournisseurs, pour l'une ou l'autre source.
- *
- * Réactiver lève le motif de désactivation automatique : sans cela, un
- * fournisseur remis en service par l'admin garderait un « aucun article »
- * trompeur, alors même qu'il vient d'être rouvert volontairement.
- */
-export async function PATCH(req: NextRequest) {
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- let body: unknown;
- try {
- body = await req.json();
- } catch {
- return NextResponse.json({ error: "Corps JSON invalide" }, { status: 400 });
- }
- const parsed = patchSchema.safeParse(body);
- if (!parsed.success) {
- return NextResponse.json(
- { error: "Paramètres invalides", details: parsed.error.issues.map((i) => i.message) },
- { status: 400 },
- );
- }
- const { codes, actifSql, actifQlik } = parsed.data;
-
- const reactivation = actifSql === true || actifQlik === true;
- const rows = await db
- .update(syncFournisseurs)
- .set({
- ...(actifSql !== undefined ? { actifSql } : {}),
- ...(actifQlik !== undefined ? { actifQlik } : {}),
- ...(reactivation ? { desactiveMotif: null } : {}),
- updatedAt: new Date(),
- })
- .where(codes.length === 1 ? eq(syncFournisseurs.codeFournisseur, codes[0]) : inArray(syncFournisseurs.codeFournisseur, codes))
- .returning({ code: syncFournisseurs.codeFournisseur });
-
- console.log(`[api/admin/sync] ${rows.length} fournisseur(s) mis à jour (sql=${actifSql} qlik=${actifQlik})`);
- return NextResponse.json({ success: true, misAJour: rows.length });
-}
diff --git a/src/app/api/admin/sync/route.ts b/src/app/api/admin/sync/route.ts
deleted file mode 100644
index 9989685..0000000
--- a/src/app/api/admin/sync/route.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { z } from "zod";
-import { adminOuReponse } from "@/lib/authz";
-import { readSyncSettings, saveSyncSettings } from "@/features/admin/api/sync-settings";
-import {
- getSyncSchedulerState,
- lancerRound,
- demanderArret,
- debutFenetre,
- seedSyncFournisseurs,
-} from "@/features/admin/api/sync-scheduler";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-// Un lancement manuel peut enchaîner plusieurs fournisseurs.
-export const maxDuration = 300;
-
-/** GET — réglages, état courant, et prochaine ouverture de fenêtre. */
-export async function GET() {
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- const settings = await readSyncSettings();
- const maintenant = new Date();
- const debut = debutFenetre(settings, maintenant);
-
- return NextResponse.json({
- success: true,
- settings,
- state: getSyncSchedulerState(),
- /** true = on est actuellement dans la fenêtre nocturne. */
- dansLaFenetre: debut !== null,
- fenetreDebutAt: debut?.toISOString() ?? null,
- maintenant: maintenant.toISOString(),
- });
-}
-
-const settingsSchema = z.object({
- actif: z.boolean().optional(),
- heureDebut: z.coerce.number().int().min(0).max(23).optional(),
- heureFin: z.coerce.number().int().min(0).max(23).optional(),
- qlikParNuit: z.coerce.number().int().min(0).max(200).optional(),
- sqlParQlik: z.coerce.number().int().min(1).max(500).optional(),
- qlikMinJours: z.coerce.number().int().min(0).max(365).optional(),
-});
-
-/** PATCH — met à jour les réglages. */
-export async function PATCH(req: NextRequest) {
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- let body: unknown;
- try {
- body = await req.json();
- } catch {
- return NextResponse.json({ error: "Corps JSON invalide" }, { status: 400 });
- }
- const parsed = settingsSchema.safeParse(body);
- if (!parsed.success) {
- return NextResponse.json(
- { error: "Paramètres invalides", details: parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`) },
- { status: 400 },
- );
- }
-
- const settings = await saveSyncSettings(parsed.data);
- return NextResponse.json({ success: true, settings });
-}
-
-const actionSchema = z.object({
- action: z.enum(["start", "stop", "seed"]),
- /**
- * Lancement manuel hors de la fenêtre nocturne. Réservé à l'admin qui sait
- * ce qu'il fait : en pleine journée, la charge est visible par les magasins.
- */
- forcer: z.boolean().optional(),
-});
-
-/** POST — démarre un round manuellement, l'arrête, ou resynchronise la liste. */
-export async function POST(req: NextRequest) {
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- let body: unknown;
- try {
- body = await req.json();
- } catch {
- return NextResponse.json({ error: "Corps JSON invalide" }, { status: 400 });
- }
- const parsed = actionSchema.safeParse(body);
- if (!parsed.success) {
- return NextResponse.json({ error: "Action inconnue (start, stop ou seed)" }, { status: 400 });
- }
-
- if (parsed.data.action === "seed") {
- const n = await seedSyncFournisseurs();
- return NextResponse.json({ success: true, fournisseurs: n });
- }
-
- if (parsed.data.action === "stop") {
- demanderArret();
- return NextResponse.json({ success: true, state: getSyncSchedulerState() });
- }
-
- const etat = getSyncSchedulerState();
- if (etat.enCours) {
- return NextResponse.json({ error: "Un round est déjà en cours.", state: etat }, { status: 409 });
- }
-
- // Fire-and-forget : le round dure des minutes, le client suit via GET.
- void lancerRound("manuel", parsed.data.forcer === true).catch((e) => {
- console.error("[api/admin/sync] round manuel en échec :", e instanceof Error ? e.message : String(e));
- });
-
- return NextResponse.json({ success: true, state: getSyncSchedulerState() });
-}
diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts
deleted file mode 100644
index 73228a0..0000000
--- a/src/app/api/auth/[...nextauth]/route.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-import { handlers } from "@/lib/auth";
-export const { GET, POST } = handlers;
diff --git a/src/app/api/commandes-auto/route.ts b/src/app/api/commandes-auto/route.ts
deleted file mode 100644
index 8a7cf2b..0000000
--- a/src/app/api/commandes-auto/route.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { sessionOuReponse } from "@/lib/authz";
-
-const FF_API_BASE = process.env.FF_API_BASE_URL ?? "https://api.ffnancy.fr";
-
-/**
- * GET /api/commandes-auto[?site=292&codefou=N009]
- *
- * Proxy vers https://api.ffnancy.fr/api/commandes-auto
- * Transfère les query params site et codefou si présents.
- */
-export async function GET(req: NextRequest) {
- const acces = await sessionOuReponse();
- if (acces instanceof Response) return acces;
-
- try {
- const { searchParams } = req.nextUrl;
- const params = new URLSearchParams();
- if (searchParams.get("site")) params.set("site", searchParams.get("site")!);
- if (searchParams.get("codefou")) params.set("codefou", searchParams.get("codefou")!);
-
- const qs = params.toString();
- const url = `${FF_API_BASE}/api/commandes-auto${qs ? `?${qs}` : ""}`;
-
- const res = await fetch(url, { cache: "no-store" });
- if (!res.ok) {
- return NextResponse.json({ error: `API upstream HTTP ${res.status}` }, { status: res.status });
- }
- const data = await res.json();
- return NextResponse.json(data);
- } catch (e) {
- console.error("[api/commandes-auto]", e);
- return NextResponse.json({ error: "Erreur serveur" }, { status: 500 });
- }
-}
diff --git a/src/app/api/diag/route.ts b/src/app/api/diag/route.ts
deleted file mode 100644
index 6f6c796..0000000
--- a/src/app/api/diag/route.ts
+++ /dev/null
@@ -1,294 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { db } from "@/db";
-import { sql } from "drizzle-orm";
-import { adminOuReponse } from "@/lib/authz";
-
-const FF_API_BASE = process.env.FF_API_BASE_URL ?? "https://api.ffnancy.fr";
-
-async function probe(url: string) {
- try {
- const res = await fetch(url, { cache: "no-store" });
- const text = await res.text();
- let parsed: unknown = null;
- try { parsed = JSON.parse(text); } catch { parsed = text.slice(0, 800); }
- let summary: unknown = parsed;
- if (Array.isArray(parsed)) {
- summary = { count: parsed.length, firstKeys: parsed[0] ? Object.keys(parsed[0]) : [], sample: parsed.slice(0, 2) };
- } else if (parsed && typeof parsed === "object") {
- const keys = Object.keys(parsed as object);
- const firstArrayKey = keys.find(k => Array.isArray((parsed as Record)[k]));
- if (firstArrayKey) {
- const arr = (parsed as Record)[firstArrayKey];
- summary = { wrapper: firstArrayKey, count: arr.length, firstKeys: arr[0] ? Object.keys(arr[0] as object) : [], sample: arr.slice(0, 2) };
- } else {
- // Objet simple : montrer toutes les clés et le contenu complet
- summary = { keys, full: parsed };
- }
- }
- return { status: res.status, url, summary };
- } catch (e) {
- return { error: String(e), url };
- }
-}
-
-export async function GET(req: NextRequest) {
- const acces = await adminOuReponse();
- if (acces instanceof Response) return acces;
-
- const { searchParams } = new URL(req.url);
-
- // Date range: 12 derniers mois
- const now = new Date();
- const dateFin = new Date(now.getFullYear(), now.getMonth(), 0).toISOString().slice(0, 10);
- const dateDebut = new Date(now.getFullYear(), now.getMonth() - 12, 1).toISOString().slice(0, 10);
-
- // Récupérer un codefou réel + un codein réel depuis l'API
- let codefou = searchParams.get("codefou");
- let firstCodein: string | null = searchParams.get("codein");
- const forcedNoid = searchParams.get("noid"); // ex: ?noid=129632
-
- if (!codefou) {
- try {
- const res = await fetch(`${FF_API_BASE}/api/fournisseurs?limit=1`, { cache: "no-store" });
- const data = await res.json();
- const list = Array.isArray(data) ? data : (Object.values(data).find(v => Array.isArray(v)) as unknown[] ?? []);
- if (list.length > 0) codefou = (list[0] as Record).codefou as string ?? null;
- } catch { /* ignore */ }
- codefou ??= "D005";
- }
-
- if (!firstCodein) {
- try {
- const res = await fetch(`${FF_API_BASE}/api/articles?codefou=${encodeURIComponent(codefou)}&limit=1`, { cache: "no-store" });
- const data = await res.json();
- const list = Array.isArray(data) ? data : (Object.values(data).find(v => Array.isArray(v)) as unknown[] ?? []);
- if (list.length > 0) firstCodein = (list[0] as Record).codein as string ?? null;
- } catch { /* ignore */ }
- }
-
- // Si un noid est forcé, on probe directement mensuel + referentiel pour cet article
- const mensuelNoidForced = forcedNoid
- ? probe(`${FF_API_BASE}/api/articles/${encodeURIComponent(forcedNoid)}/mensuel?dateDebut=${dateDebut}&dateFin=${dateFin}`)
- : Promise.resolve({ skipped: "no ?noid= param" });
- const referentielNoidForced = forcedNoid
- ? probe(`${FF_API_BASE}/api/articles/${encodeURIComponent(forcedNoid)}/referentiel`)
- : Promise.resolve({ skipped: "no ?noid= param" });
-
- const [
- fournisseurs,
- articles,
- mvt_dateDebut,
- mensuel_noid,
- referentiel,
- mensuel_forced,
- referentiel_forced,
- ] = await Promise.all([
- probe(`${FF_API_BASE}/api/fournisseurs?limit=2`),
- probe(`${FF_API_BASE}/api/articles?codefou=${encodeURIComponent(codefou)}&limit=2`),
- probe(`${FF_API_BASE}/api/mouvements/articles?codefou=${encodeURIComponent(codefou)}&dateDebut=${dateDebut}&dateFin=${dateFin}&limit=2`),
- // Test mensuel avec no_id auto-résolu
- firstCodein
- ? (async () => {
- try {
- const res = await fetch(`${FF_API_BASE}/api/articles?codefou=${encodeURIComponent(codefou)}&limit=1`, { cache: "no-store" });
- const data = await res.json();
- const list = Array.isArray(data) ? data : (Object.values(data).find(v => Array.isArray(v)) as unknown[] ?? []);
- const noid = list[0] ? (list[0] as Record).no_id as string : null;
- if (noid) return probe(`${FF_API_BASE}/api/articles/${encodeURIComponent(noid)}/mensuel?dateDebut=${dateDebut}&dateFin=${dateFin}`);
- } catch { /* ignore */ }
- return { skipped: "no no_id available" };
- })()
- : Promise.resolve({ skipped: "no article" }),
- // Referentiel complet (nomenclature + gamme + stock + prix)
- firstCodein
- ? (async () => {
- try {
- const res = await fetch(`${FF_API_BASE}/api/articles?codefou=${encodeURIComponent(codefou)}&limit=5`, { cache: "no-store" });
- const data = await res.json();
- const list = Array.isArray(data) ? data : (Object.values(data).find(v => Array.isArray(v)) as unknown[] ?? []);
- const art = (list[4] ?? list[0]) as Record | undefined;
- const noId = art?.no_id as string ?? null;
- if (noId) return probe(`${FF_API_BASE}/api/articles/${encodeURIComponent(noId)}/referentiel`);
- } catch { /* ignore */ }
- return { skipped: "no no_id" };
- })()
- : Promise.resolve({ skipped: "no codefou" }),
- mensuelNoidForced,
- referentielNoidForced,
- ]);
-
- // Test PostgreSQL + diagnostic ventesProduits
- let postgresql: unknown;
- let ventesProduitsDiag: unknown;
- try {
- const r = await db.execute(sql`SELECT COUNT(*) as count FROM session_snapshots`);
-
- // Diagnostic ventesProduits : cherche par les 2 codes possibles d'AUXENCE
- const vpByName = await db.execute(sql`
- SELECT code_fournisseur, COUNT(*) as nb_rows,
- COUNT(code_gamme) as nb_gamme,
- COUNT(code_gamme_init) as nb_gamme_init,
- COUNT(code3) as nb_code3
- FROM ventes_produits
- WHERE code_fournisseur IN ('AUXENCE', 'A025', ${codefou})
- GROUP BY code_fournisseur
- `);
-
- // Sample de quelques codeins dans ventesProduits pour ce fournisseur
- const vpSample = await db.execute(sql`
- SELECT codein, code_fournisseur, code_gamme, code_gamme_init, code3, libelle3
- FROM ventes_produits
- WHERE code_fournisseur IN ('AUXENCE', 'A025', ${codefou})
- LIMIT 3
- `);
-
- postgresql = {
- ok: true,
- snapshots: Number(r.rows[0]?.count ?? 0),
- };
- ventesProduitsDiag = {
- byFournisseur: vpByName.rows,
- sample: vpSample.rows,
- };
- } catch (e) {
- postgresql = { ok: false, error: String(e) };
- ventesProduitsDiag = { error: String(e) };
- }
-
- // Diagnostic analytics CA TTC
- let mvtartDiag: unknown;
- try {
- // 1. Totaux mars 2025 avec mntmvtht et mntmvtttc pour comparer avec API (HT=225k, TTC=269k)
- const totaux = await db.execute(sql`
- SELECT site,
- ABS(SUM(mntmvtht))::float AS sum_ht,
- ABS(SUM(mntmvtttc))::float AS sum_ttc,
- COUNT(*) AS nb_lignes
- FROM mvtart
- WHERE genremvt = 3
- AND TO_CHAR(datmvt, 'YYYY-MM') = '2025-03'
- AND site IN ('292', '579')
- GROUP BY site
- `);
- // 2. Distribution des valeurs de preference dans artfou1
- const prefDist = await db.execute(sql`
- SELECT preference, COUNT(*) AS nb
- FROM artfou1
- GROUP BY preference
- ORDER BY preference
- `);
- // 3. Ventes mars 2025 non attribuées (aucune ligne artfou1 avec preference=1)
- const sansPreference = await db.execute(sql`
- SELECT COUNT(DISTINCT m.artnoid) AS nb_articles_sans_pref
- FROM mvtart m
- JOIN articles a ON a.no_id = m.artnoid
- WHERE m.genremvt = 3
- AND TO_CHAR(m.datmvt, 'YYYY-MM') = '2025-03'
- AND m.site IN ('292','579')
- AND NOT EXISTS (
- SELECT 1 FROM artfou1 af
- WHERE af.art_no_id = a.no_id AND af.preference = 1
- )
- `);
- mvtartDiag = {
- totaux_202503: totaux.rows,
- artfou1_preference_distribution: prefDist.rows,
- articles_vendus_sans_pref1: sansPreference.rows,
- };
- } catch (e) {
- mvtartDiag = { error: String(e) };
- }
-
- // Diagnostic franco : colonnes DB avec "franco" + sample fouident + raw commandes-auto
- let francoDiag: unknown;
- try {
- const francoColumns = await db.execute(sql`
- SELECT table_name, column_name, data_type
- FROM information_schema.columns
- WHERE column_name ILIKE '%franco%'
- OR column_name ILIKE '%min_cmd%'
- OR column_name ILIKE '%mincde%'
- OR column_name ILIKE '%min_commande%'
- ORDER BY table_name, column_name
- `);
- // Sample des 3 premières lignes de fouident pour voir toutes les colonnes
- const fouidentSample = await db.execute(sql`SELECT * FROM fouident LIMIT 3`);
- const foucadSample = await db.execute(sql`SELECT * FROM foucad LIMIT 5`);
- francoDiag = {
- francoColumns: francoColumns.rows,
- fouidentColumns: fouidentSample.rows.length > 0 ? Object.keys(fouidentSample.rows[0] as object) : [],
- fouidentSample: fouidentSample.rows,
- foucadColumns: foucadSample.rows.length > 0 ? Object.keys(foucadSample.rows[0] as object) : [],
- foucadSample: foucadSample.rows,
- };
- } catch (e) {
- francoDiag = { error: String(e) };
- }
-
- // Raw commandes-auto : récupère toutes les lignes et filtre celles avec franco_ht manquant
- let commandesAutoFrancoAudit: unknown;
- try {
- const caRes = await fetch(`${FF_API_BASE}/api/commandes-auto`, { cache: "no-store" });
- const caData = await caRes.json();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const caRows: any[] = Array.isArray(caData) ? caData : (caData?.propositions ?? caData?.data ?? []);
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const withFranco = caRows.filter((r: any) => r.franco_ht != null && Number(r.franco_ht) > 0);
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const withoutFranco = caRows.filter((r: any) => r.franco_ht == null || Number(r.franco_ht) === 0);
- commandesAutoFrancoAudit = {
- total: caRows.length,
- avecFranco: withFranco.length,
- sansFranco: withoutFranco.length,
- lignesSansFranco: withoutFranco.map((r: any) => ({
- site: r.site, codefou: r.codefou, nom_fou: r.nom_fou,
- franco_ht: r.franco_ht, franco_atteint: r.franco_atteint,
- })),
- };
- } catch (e) {
- commandesAutoFrancoAudit = { error: String(e) };
- }
-
- // Probe des fournisseurs N/A pour trouver où est leur franco
- const [
- detailM036_292,
- detailM030_579,
- fournisseurM036,
- fournisseurM030,
- ] = await Promise.all([
- probe(`${FF_API_BASE}/api/commandes-auto/M036?site=292`),
- probe(`${FF_API_BASE}/api/commandes-auto/M030?site=579`),
- probe(`${FF_API_BASE}/api/fournisseurs/M036`),
- probe(`${FF_API_BASE}/api/fournisseurs/M030`),
- ]);
- const francoNaProbe = { detailM036_292, detailM030_579, fournisseurM036, fournisseurM030 };
-
- // Raw commandes-auto (premier fournisseur) pour voir les champs réels retournés par l'API
- const rawCommandesAuto = await probe(`${FF_API_BASE}/api/commandes-auto`);
-
- return NextResponse.json({
- timestamp: new Date().toISOString(),
- dateRange: { dateDebut, dateFin },
- codefouTested: codefou,
- firstCodeinTested: firstCodein,
- forcedNoid: forcedNoid ?? "(none — pass ?noid=129632 to test a specific article)",
- fournisseurs,
- articles,
- mouvements_dateDebut: mvt_dateDebut,
- endpoints_auto: {
- "articles/:no_id/mensuel": mensuel_noid,
- "articles/:no_id/referentiel": referentiel,
- },
- endpoints_forced_noid: {
- "articles/:noid/mensuel": mensuel_forced,
- "articles/:noid/referentiel": referentiel_forced,
- },
- postgresql,
- ventesProduitsDiag,
- mvtartDiag,
- francoDiag,
- rawCommandesAuto,
- commandesAutoFrancoAudit,
- francoNaProbe,
- });
-}
diff --git a/src/app/api/diag/stock-fournisseur/route.ts b/src/app/api/diag/stock-fournisseur/route.ts
deleted file mode 100644
index 44aa7c4..0000000
--- a/src/app/api/diag/stock-fournisseur/route.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { NextResponse } from "next/server";
-import { pgDiagFournisseurDerniereEntree } from "@/lib/pg-ff-client";
-import { adminOuReponse } from "@/lib/authz";
-
-export const dynamic = "force-dynamic";
-
-/**
- * Diagnostic de l'attribution « fournisseur de la dernière entrée » utilisée par
- * la page Gestion de Stock.
- *
- * `colonneDetectee: null` signifie que `mvtart` ne porte aucune des colonnes
- * fournisseur connues : la page retombe alors sur `artfou1.preference = 1`.
- * `colonnesMvtart` liste ce qui existe réellement, pour compléter la liste
- * blanche `MVTART_FOU_CANDIDATES` si le nom diffère.
- */
-export async function GET() {
- const acces = await adminOuReponse();
- if (acces instanceof Response) return acces;
-
- try {
- return NextResponse.json(await pgDiagFournisseurDerniereEntree());
- } catch (e) {
- return NextResponse.json({ error: String(e) }, { status: 500 });
- }
-}
diff --git a/src/app/api/export/excel/route.ts b/src/app/api/export/excel/route.ts
deleted file mode 100644
index 7eace0c..0000000
--- a/src/app/api/export/excel/route.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import ExcelJS from "exceljs";
-import { z } from "zod";
-import { sessionOuReponse } from "@/lib/authz";
-
-const ExportSchema = z.object({
- nomFournisseur: z.string(),
- rows: z.array(z.object({
- codein: z.string(),
- libelle1: z.string(),
- code3: z.string(),
- libelle3: z.string(),
- codeGamme: z.string().nullable(),
- totalQuantite: z.number(),
- totalCa: z.number(),
- tauxMarge: z.number(),
- // Before gamme for delta
- gammeAvant: z.string().nullable().optional(),
- })),
-});
-
-export async function POST(req: NextRequest) {
- const acces = await sessionOuReponse();
- if (acces instanceof Response) return acces;
-
- const body = await req.json();
- const parsed = ExportSchema.safeParse(body);
- if (!parsed.success) {
- return NextResponse.json({ error: "Invalid payload" }, { status: 400 });
- }
-
- const { nomFournisseur, rows } = parsed.data;
- const workbook = new ExcelJS.Workbook();
- workbook.creator = "CollectFlow";
- workbook.created = new Date();
-
- const sheet = workbook.addWorksheet("Assortiment", {
- views: [{ state: "frozen", ySplit: 1 }],
- });
-
- // Header style
- const headerStyle: Partial = {
- font: { bold: true, color: { argb: "FFFFFFFF" } },
- fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FF0F172A" } },
- alignment: { horizontal: "center" },
- border: { bottom: { style: "thin", color: { argb: "FF334155" } } },
- };
-
- sheet.columns = [
- { header: "Code", key: "codein", width: 14 },
- { header: "Désignation", key: "libelle1", width: 40 },
- { header: "Nomenclature", key: "libelle3", width: 25 },
- { header: "Gamme Avant", key: "gammeAvant", width: 14 },
- { header: "Gamme Après", key: "codeGamme", width: 14 },
- { header: "Delta", key: "delta", width: 10 },
- { header: "Vol. 12m", key: "totalQuantite", width: 12 },
- { header: "CA 12m (€)", key: "totalCa", width: 14 },
- { header: "Marge (%)", key: "tauxMarge", width: 12 },
- ];
-
- // Apply header style
- sheet.getRow(1).eachCell((cell) => { Object.assign(cell, headerStyle); });
- sheet.getRow(1).height = 22;
-
- // Gamme colours
- const GAMME_COLORS: Record = {
- A: "FF064E3B", B: "FF1E3A5F", C: "FF78350F", Z: "FF4C0519",
- };
-
- for (const row of rows) {
- const delta = row.gammeAvant !== row.codeGamme ? `${row.gammeAvant ?? "—"} → ${row.codeGamme ?? "—"}` : "";
- const excelRow = sheet.addRow({
- codein: row.codein,
- libelle1: row.libelle1,
- libelle3: row.libelle3,
- gammeAvant: row.gammeAvant ?? "—",
- codeGamme: row.codeGamme ?? "—",
- delta,
- totalQuantite: Math.round(row.totalQuantite),
- totalCa: parseFloat(row.totalCa.toFixed(2)),
- tauxMarge: parseFloat(row.tauxMarge.toFixed(2)),
- });
-
- // Colour the "Gamme Après" cell
- const gammeCell = excelRow.getCell("codeGamme");
- if (row.codeGamme && GAMME_COLORS[row.codeGamme]) {
- gammeCell.fill = { type: "pattern", pattern: "solid", fgColor: { argb: GAMME_COLORS[row.codeGamme] } };
- gammeCell.font = { bold: true, color: { argb: "FFFFFFFF" } };
- }
-
- // Highlight changed rows
- if (delta) {
- excelRow.getCell("delta").font = { bold: true, color: { argb: "FFFBBF24" } };
- }
-
- // Format numbers
- excelRow.getCell("totalCa").numFmt = '#,##0.00 "€"';
- excelRow.getCell("tauxMarge").numFmt = '0.00"%"';
- }
-
- // Generate buffer
- const buffer = await workbook.xlsx.writeBuffer();
-
- const filename = `Assortiment_${nomFournisseur.replace(/\s+/g, "_")}_${new Date().toISOString().slice(0, 10)}.xlsx`;
-
- return new NextResponse(buffer, {
- headers: {
- "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- "Content-Disposition": `attachment; filename="${filename}"`,
- },
- });
-}
diff --git a/src/app/api/export/modified-gammes/route.ts b/src/app/api/export/modified-gammes/route.ts
deleted file mode 100644
index 600817f..0000000
--- a/src/app/api/export/modified-gammes/route.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import ExcelJS from "exceljs";
-import { z } from "zod";
-import { sessionOuReponse } from "@/lib/authz";
-
-const ExportModifiedGammesSchema = z.object({
- nomFournisseur: z.string(),
- changes: z.array(z.object({
- codein: z.string(),
- gtin: z.string(),
- codeFournisseur: z.string().optional(),
- gamme: z.string(),
- })),
-});
-
-export async function POST(req: NextRequest) {
- const acces = await sessionOuReponse();
- if (acces instanceof Response) return acces;
-
- const body = await req.json();
- const parsed = ExportModifiedGammesSchema.safeParse(body);
- if (!parsed.success) {
- return NextResponse.json({ error: "Invalid payload" }, { status: 400 });
- }
-
- const { nomFournisseur, changes } = parsed.data;
- const workbook = new ExcelJS.Workbook();
- workbook.creator = "CollectFlow";
- workbook.created = new Date();
-
- const sheet = workbook.addWorksheet("Gammes Modifiées", {
- views: [{ state: "frozen", ySplit: 1 }],
- });
-
- // Header style
- const headerStyle: Partial = {
- font: { bold: true, color: { argb: "FFFFFFFF" } },
- fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FF0F172A" } },
- alignment: { horizontal: "center" },
- border: { bottom: { style: "thin", color: { argb: "FF334155" } } },
- };
-
- sheet.columns = [
- { header: "CODE FOURNISSEUR", key: "codeFournisseur", width: 22 },
- { header: "CODEIN", key: "codein", width: 18 },
- { header: "GAMME", key: "gamme", width: 12 },
- ];
-
- // Apply header style
- sheet.getRow(1).eachCell((cell) => { Object.assign(cell, headerStyle); });
- sheet.getRow(1).height = 22;
-
- for (const row of changes) {
- sheet.addRow({
- codeFournisseur: row.codeFournisseur || "—",
- codein: row.codein || "—",
- gamme: row.gamme || "—",
- });
- }
-
- // Centrer la colonne Gamme
- const gammeCol = sheet.getColumn("gamme");
- gammeCol.alignment = { horizontal: "center" };
-
- // Format en texte pour eviter la notation scientifique excel
- sheet.getColumn("codeFournisseur").numFmt = "@";
- sheet.getColumn("codein").numFmt = "@";
-
- // Generate buffer
- const buffer = await workbook.xlsx.writeBuffer();
-
- const filename = `Modifications_Gammes_${nomFournisseur.replace(/\s+/g, "_")}_${new Date().toISOString().slice(0, 10)}.xlsx`;
-
- return new NextResponse(buffer, {
- headers: {
- "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- "Content-Disposition": `attachment; filename="${filename}"`,
- },
- });
-}
diff --git a/src/app/api/ff-status/route.ts b/src/app/api/ff-status/route.ts
deleted file mode 100644
index 02dbe50..0000000
--- a/src/app/api/ff-status/route.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { NextResponse } from "next/server";
-import { diagnostiquerApiFf } from "@/features/settings/ff-api-diagnostic";
-import { sessionOuReponse } from "@/lib/authz";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/ff-status — état de l'API REST FF Nancy.
- *
- * S'appuie sur le même diagnostic que le bouton « Tester » des Paramètres, afin
- * qu'un échec dise *pourquoi* (DNS, connexion refusée, délai dépassé, code HTTP)
- * et *quelle adresse* a été appelée. L'ancienne version renvoyait un 503 sans
- * détail, impossible à distinguer d'une simple erreur d'URL.
- */
-export async function GET() {
- const acces = await sessionOuReponse();
- if (acces instanceof Response) return acces;
-
- const res = await diagnostiquerApiFf();
- if (!res.success) {
- return NextResponse.json(
- { error: "API FF Nancy non disponible", url: res.url, detail: res.error },
- { status: 503 },
- );
- }
- return NextResponse.json(res.status);
-}
diff --git a/src/app/api/grid/rows/route.ts b/src/app/api/grid/rows/route.ts
deleted file mode 100644
index a12e9d6..0000000
--- a/src/app/api/grid/rows/route.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import { NextRequest } from "next/server";
-import { getProductRows } from "@/features/grid/api/get-product-rows";
-import { sessionOuReponse } from "@/lib/authz";
-import type { GridFilters } from "@/types/grid";
-
-export const dynamic = "force-dynamic";
-
-const encoder = new TextEncoder();
-
-function writeNdjson(controller: ReadableStreamDefaultController, value: unknown) {
- controller.enqueue(encoder.encode(`${JSON.stringify(value)}\n`));
-}
-
-export async function GET(request: NextRequest) {
- const acces = await sessionOuReponse();
- if (acces instanceof Response) return acces;
-
- const searchParams = request.nextUrl.searchParams;
- const codeFournisseur = searchParams.get("fournisseur");
-
- if (!codeFournisseur) {
- return Response.json({ error: "Missing fournisseur" }, { status: 400 });
- }
-
- const magasin = searchParams.get("magasin") ?? "TOTAL";
- const chunkSize = Math.max(50, Math.min(500, Number(searchParams.get("chunkSize") ?? 150)));
- // `code3` n'est volontairement pas lu : la Grille applique ce filtre en local
- // (getProductRows ne s'en sert pas) et il accepte désormais plusieurs valeurs.
- const filters: Partial = {
- code1: searchParams.get("code1"),
- code2: searchParams.get("code2"),
- };
- const forceRefresh = searchParams.get("refresh") === "1";
-
- // Client parti (changement de fournisseur, page quittée) : on arrête de
- // sérialiser et d'envoyer. Le calcul lui-même continue — il est partagé et
- // mis en cache, la prochaine ouverture en profitera.
- let cancelled = false;
- request.signal.addEventListener("abort", () => { cancelled = true; });
-
- const stream = new ReadableStream({
- cancel() {
- cancelled = true;
- },
- async start(controller) {
- try {
- writeNdjson(controller, { type: "start", loaded: 0, total: null });
- const rows = await getProductRows({ codeFournisseur, magasin, filters, forceRefresh });
- if (cancelled) return;
- const total = rows.length;
-
- for (let start = 0; start < total; start += chunkSize) {
- if (cancelled) return;
- const chunk = rows.slice(start, start + chunkSize);
- writeNdjson(controller, {
- type: "chunk",
- rows: chunk,
- loaded: Math.min(start + chunk.length, total),
- total,
- });
- await new Promise((resolve) => setTimeout(resolve, 0));
- }
-
- writeNdjson(controller, { type: "done", loaded: total, total });
- } catch (error) {
- if (cancelled) return;
- writeNdjson(controller, {
- type: "error",
- error: error instanceof Error ? error.message : "Unknown error",
- });
- } finally {
- try {
- controller.close();
- } catch {
- /* flux déjà fermé côté client */
- }
- }
- },
- });
-
- return new Response(stream, {
- headers: {
- "Content-Type": "application/x-ndjson; charset=utf-8",
- "Cache-Control": "no-store",
- "X-Accel-Buffering": "no",
- },
- });
-}
diff --git a/src/app/api/grid/rows/store-patch/route.ts b/src/app/api/grid/rows/store-patch/route.ts
deleted file mode 100644
index 35b2263..0000000
--- a/src/app/api/grid/rows/store-patch/route.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { NextRequest } from "next/server";
-import { getStorePatch } from "@/features/grid/api/get-product-rows";
-import { MAGASINS } from "@/lib/magasins";
-import { sessionOuReponse } from "@/lib/authz";
-
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/grid/rows/store-patch?fournisseur=…&magasin=…
- *
- * Complément de l'API FF pour un magasin (cf. `features/grid/lib/store-patch.ts`).
- * La Grille charge toujours les lignes « tous magasins » et applique ce
- * complément à son arrivée : le changement de magasin n'attend plus rien.
- */
-export async function GET(request: NextRequest) {
- const acces = await sessionOuReponse();
- if (acces instanceof Response) return acces;
-
- const codeFournisseur = request.nextUrl.searchParams.get("fournisseur");
- const magasin = request.nextUrl.searchParams.get("magasin") ?? "";
- // Un code inconnu ferait de chaque article un candidat : autant d'appels
- // inutiles à l'API FF. « Tous magasins » n'a pas de complément.
- if (!codeFournisseur || !MAGASINS.some((m) => m.code === magasin)) {
- return Response.json({ error: "Paramètres fournisseur et magasin requis." }, { status: 400 });
- }
-
- try {
- const patch = await getStorePatch(codeFournisseur, magasin);
- return Response.json(patch, { headers: { "Cache-Control": "no-store" } });
- } catch (error) {
- console.error(`[store-patch] ${codeFournisseur}/${magasin} KO:`, (error as Error).message?.slice(0, 200));
- return Response.json({ error: "Complément indisponible." }, { status: 502 });
- }
-}
diff --git a/src/app/api/logs/route.ts b/src/app/api/logs/route.ts
deleted file mode 100644
index 56adf2d..0000000
--- a/src/app/api/logs/route.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * CollectFlow — Journaux serveur des jobs (liste + téléchargement).
- *
- * `GET /api/logs` → liste des journaux disponibles (JSON)
- * `GET /api/logs?id=` → le journal complet en pièce jointe (text/plain)
- *
- * Réservé aux admins : un journal d'extraction contient les diagnostics internes
- * du modèle Qlik et les codes articles manipulés. Aucun secret n'y transite —
- * l'extracteur ne journalise que le NOM du cookie de session, jamais sa valeur,
- * et jamais le mot de passe Qlik.
- */
-
-import { NextRequest, NextResponse } from "next/server";
-import { adminOuReponse } from "@/lib/authz";
-import { listCaptures, readCapture } from "@/lib/log-capture";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-export async function GET(req: NextRequest) {
- const refus = await adminOuReponse();
- if (refus instanceof Response) return refus;
-
- const id = req.nextUrl.searchParams.get("id");
- if (!id) {
- return NextResponse.json({ success: true, logs: await listCaptures() });
- }
-
- const contenu = await readCapture(id);
- if (contenu == null) {
- return NextResponse.json({ error: "Journal introuvable ou expiré" }, { status: 404 });
- }
-
- // Nom de fichier assaini : l'id vient d'un job interne, mais il finit dans
- // un en-tête HTTP.
- const nom = `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.log`;
- return new NextResponse(contenu, {
- status: 200,
- headers: {
- "Content-Type": "text/plain; charset=utf-8",
- "Content-Disposition": `attachment; filename="${nom}"`,
- "Cache-Control": "no-store",
- },
- });
-}
diff --git a/src/app/api/produits/opportunites/route.ts b/src/app/api/produits/opportunites/route.ts
deleted file mode 100644
index 9d2ecea..0000000
--- a/src/app/api/produits/opportunites/route.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { sessionOuReponse } from "@/lib/authz";
-import { pgGetOpportunitesFamille } from "@/lib/pg-ff-client";
-import { buildLast12MonthsRange } from "@/lib/api-ff-client";
-
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/produits/opportunites?nomNoId=123
- *
- * Produits de la même nomenclature, classés par écart entre performance réseau
- * et performance locale (quantités par magasin). Chargé à la demande depuis la
- * fiche produit : la requête agrège `mvtart` sur 12 mois pour toute la famille,
- * on ne veut pas la payer au chargement de la page.
- */
-export async function GET(req: NextRequest) {
- const acces = await sessionOuReponse();
- if (acces instanceof Response) return acces;
-
- const raw = req.nextUrl.searchParams.get("nomNoId");
- const nomNoId = Number(raw);
- if (!raw || !Number.isInteger(nomNoId) || nomNoId <= 0) {
- return NextResponse.json({ error: "Param 'nomNoId' invalide" }, { status: 400 });
- }
-
- try {
- const { dateDebut, dateFin } = buildLast12MonthsRange();
- const rows = await pgGetOpportunitesFamille(nomNoId, dateDebut, dateFin);
- return NextResponse.json({ success: true, rows });
- } catch (e) {
- console.error("[api/produits/opportunites]", (e as Error).message?.slice(0, 250));
- return NextResponse.json({ error: "Erreur serveur" }, { status: 500 });
- }
-}
diff --git a/src/app/api/produits/search/route.ts b/src/app/api/produits/search/route.ts
deleted file mode 100644
index d282d95..0000000
--- a/src/app/api/produits/search/route.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { sessionOuReponse } from "@/lib/authz";
-import { demarrerRecherche, etatRecherche } from "@/features/produits/api/search-produits";
-
-// Les réponses sont immédiates (le travail Qlik tourne en tâche de fond), mais on
-// garde le runtime Node.js : Playwright/Chromium ne tourne pas en edge, et l'état
-// des jobs vit dans la mémoire du process.
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * Recherche produit **Qlik d'abord** — API asynchrone.
- *
- * `POST /api/produits/search?q=[&force=1]` démarre la recherche et rend la
- * main tout de suite. `GET /api/produits/search?q=` renvoie l'avancement,
- * puis le résultat.
- *
- * Pourquoi asynchrone : une recherche enchaîne deux allers-retours Qlik (dont une
- * extraction mensuelle) et peut dépasser la minute. Une requête HTTP maintenue
- * aussi longtemps se fait couper par le reverse proxy, qui répond une page
- * d'erreur **HTML** — le client échouait alors sur « Unexpected token '<' … is
- * not valid JSON ». Même schéma que `POST /api/qlik/sync`.
- *
- * Contrôle de session explicite en plus du middleware : il répond ici en JSON,
- * et relit le compte en base (cf. lib/authz).
- */
-
-function lireTerme(req: NextRequest): string | null {
- const q = (req.nextUrl.searchParams.get("q") ?? "").trim();
- return q.length >= 3 ? q : null;
-}
-
-export async function POST(req: NextRequest) {
- const denied = await sessionOuReponse();
- if (denied instanceof Response) return denied;
-
- const q = lireTerme(req);
- if (!q) return NextResponse.json({ error: "Saisissez au moins 3 caractères" }, { status: 400 });
-
- const force = req.nextUrl.searchParams.get("force") === "1";
- try {
- const job = demarrerRecherche(q, { force });
- return NextResponse.json({ success: true, ...job });
- } catch (e) {
- const message = (e as Error).message ?? String(e);
- console.error("[api/produits/search] POST", message.slice(0, 300));
- return NextResponse.json({ error: message.slice(0, 300) }, { status: 500 });
- }
-}
-
-export async function GET(req: NextRequest) {
- const denied = await sessionOuReponse();
- if (denied instanceof Response) return denied;
-
- const q = lireTerme(req);
- if (!q) return NextResponse.json({ error: "Saisissez au moins 3 caractères" }, { status: 400 });
-
- try {
- return NextResponse.json({ success: true, ...etatRecherche(q) });
- } catch (e) {
- const message = (e as Error).message ?? String(e);
- console.error("[api/produits/search] GET", message.slice(0, 300));
- return NextResponse.json({ error: message.slice(0, 300) }, { status: 500 });
- }
-}
diff --git a/src/app/api/qlik/sync/route.ts b/src/app/api/qlik/sync/route.ts
deleted file mode 100644
index b223f63..0000000
--- a/src/app/api/qlik/sync/route.ts
+++ /dev/null
@@ -1,429 +0,0 @@
-import { NextRequest, NextResponse } from "next/server";
-import { adminOuReponse, sessionOuReponse } from "@/lib/authz";
-import { fetchNetworkMetricsPlaywright } from "@/lib/qlik-playwright";
-import { upsertNetworkMetrics } from "@/lib/qlik-network-cache";
-import { pgGetArticlesByFournisseur } from "@/lib/pg-ff-client";
-import {
- buildGridNetworkQlikDateFilter,
- QLIK_MONTHS_BACK_DEFAULT,
-} from "@/lib/qlik-date-range";
-import { startCapture, stopCapture } from "@/lib/log-capture";
-
-// Tâche d'extraction Qlik potentiellement très longue (hypercube paginé).
-// On accepte quand même 5 min côté plateforme Next.js, mais on rend la main au
-// client tout de suite via le state job ci-dessous.
-export const maxDuration = 300;
-// Forcer le runtime Node.js : Playwright/Chromium ne tourne pas en edge et on a
-// besoin d'un process persistant pour conserver l'état de job en mémoire.
-export const runtime = "nodejs";
-// Toujours exécuter dynamiquement (sinon Next peut essayer de cacher des POST).
-export const dynamic = "force-dynamic";
-
-/** État d'un job de sync Qlik pour un fournisseur donné. */
-type QlikSyncStatus = "idle" | "running" | "success" | "error";
-
-interface QlikSyncJob {
- jobId: string;
- /** Code fournisseur (mode fournisseur) — chaîne vide en mode produit. */
- fournisseur: string;
- /** Code centrale (mode produit) — absent en mode fournisseur. */
- codeCentrale?: string;
- status: QlikSyncStatus;
- requested: number;
- fetched: number;
- upserted: number;
- periode?: string;
- dateDebut?: string;
- dateFin?: string;
- startedAt: string;
- finishedAt?: string;
- error?: string;
- message?: string;
-}
-
-/**
- * Store en mémoire au niveau module. Une Map par fournisseur car on ne lance
- * qu'une extraction à la fois par fournisseur. C'est volontairement simple :
- * si le process redémarre, les jobs en cours sont perdus → GET renverra idle
- * et l'utilisateur pourra relancer. Suffisant pour corriger le bug UX.
- */
-const jobs = new Map();
-
-/**
- * Clé de job. Le mode fournisseur garde sa clé historique (le code fournisseur
- * brut) ; le mode produit est préfixé pour ne jamais entrer en collision.
- */
-function jobKeyForProduct(codeCentrale: string): string {
- return `cc:${codeCentrale.toUpperCase()}`;
-}
-
-/**
- * Nombre maximum d'extractions produit simultanées.
- *
- * Le mode produit est ouvert à tous les utilisateurs connectés (contrairement au
- * mode fournisseur, réservé aux admins). Une extraction sur 1 seul code est très
- * légère, mais le serveur Qlik est sujet aux saturations mémoire : on plafonne
- * la concurrence plutôt que de lui laisser prendre N requêtes en parallèle.
- */
-const MAX_CONCURRENT_PRODUCT_JOBS = 3;
-
-/** Compte les extractions produit actuellement en cours. */
-function runningProductJobs(): number {
- let n = 0;
- for (const [key, job] of jobs) {
- if (key.startsWith("cc:") && job.status === "running") n++;
- }
- return n;
-}
-
-/** Construit un jobId court et lisible. */
-function newJobId(): string {
- return `qlik_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
-}
-
-/** Sérialise un job pour la réponse HTTP. */
-function publicJob(job: QlikSyncJob) {
- return {
- jobId: job.jobId,
- fournisseur: job.fournisseur,
- codeCentrale: job.codeCentrale,
- status: job.status,
- requested: job.requested,
- fetched: job.fetched,
- upserted: job.upserted,
- periode: job.periode,
- dateDebut: job.dateDebut,
- dateFin: job.dateFin,
- startedAt: job.startedAt,
- finishedAt: job.finishedAt,
- error: job.error,
- message: job.message,
- };
-}
-
-/** État "idle" sérialisé (pas de job connu pour cette cible). */
-function idleJob(fournisseur: string, codeCentrale?: string) {
- return {
- jobId: null,
- fournisseur,
- codeCentrale,
- status: "idle" as const,
- requested: 0,
- fetched: 0,
- upserted: 0,
- periode: undefined,
- dateDebut: undefined,
- dateFin: undefined,
- startedAt: undefined,
- finishedAt: undefined,
- error: undefined,
- message: undefined,
- };
-}
-
-/**
- * Regex de validation d'un code centrale "raisonnable".
- *
- * Format attendu d'après l'API FF : préfixe `10000` + 6 chiffres (ex `10000167303`),
- * donc 11 caractères alphanumériques. Pour rester large et ne pas casser
- * d'éventuels codes alphanumériques fournisseur (refs internes), on autorise
- * - longueur 2..30
- * - jeu `[A-Z0-9_-]`
- * - premier caractère alphanumérique (pas `_` ni `-`)
- *
- * But : éviter d'envoyer à Qlik des chaînes vides, des `-`, des espaces
- * parasites, ou des entrées manifestement invalides qui déclenchent des
- * codes d'erreur Engine ou du gaspillage réseau. **Volontairement simple** :
- * on ne touche pas au mapping ; on filtre seulement ce qui ne ressemble à
- * aucun code plausible.
- */
-const CENTRAL_CODE_REGEX = /^[A-Z0-9][A-Z0-9_-]{1,29}$/i;
-
-/**
- * Filtre strict des codes centraux avant d'envoyer à Qlik.
- * - trim + drop vides
- * - drop "-" (placeholder déjà exclu côté agrégation mais on double-check)
- * - drop doublons (préserve l'ordre, comparaison insensible à la casse)
- * - drop codes ne matchant pas CENTRAL_CODE_REGEX (longueur / charset)
- *
- * Renvoie `{ accepted, rejected, deduped }`. Les logs n'exposent que les
- * compteurs, jamais les valeurs des codes.
- */
-function filterCentralCodes(rawCodes: Array): {
- accepted: string[];
- rejected: number;
- deduped: number;
-} {
- const seen = new Set();
- const accepted: string[] = [];
- let rejected = 0;
- let deduped = 0;
- for (const raw of rawCodes) {
- if (raw == null) {
- rejected++;
- continue;
- }
- const code = String(raw).trim();
- const key = code.toUpperCase();
- if (!code || code === "-" || code === "_") {
- rejected++;
- continue;
- }
- if (seen.has(key)) {
- deduped++;
- continue;
- }
- if (!CENTRAL_CODE_REGEX.test(code)) {
- rejected++;
- continue;
- }
- seen.add(key);
- accepted.push(code);
- }
- return { accepted, rejected, deduped };
-}
-
-/**
- * Exécute réellement l'extraction + l'upsert, en mettant à jour le job
- * au fur et à mesure (compteur fetched, puis upserted, puis finishedAt).
- */
-async function runJob(job: QlikSyncJob): Promise {
- // Journal téléchargeable depuis Paramètres. Ouvert AVANT le premier log du
- // job pour ne pas perdre l'entête (choix des champs, carte du modèle Qlik) —
- // c'est précisément la partie qu'un terminal tronque.
- startCapture(job.jobId, `sync fournisseur=${job.fournisseur} démarrée le ${job.startedAt}`);
- try {
- const articles = await pgGetArticlesByFournisseur(job.fournisseur);
- // Filtre strict des codes (trim, dedupe, exclusion vides/`-`/codes trop suspects).
- const { accepted: codes, rejected: codesRejected, deduped: codesDeduped } = filterCentralCodes(
- articles.map((a) => a.codeCentrale),
- );
- job.requested = codes.length;
- console.log(
- `[api/qlik/sync] job=${job.jobId} fournisseur=${job.fournisseur} — ${articles.length} articles, ${codes.length} codes centraux retenus, ${codesRejected} rejetés (vide/-/anormaux), ${codesDeduped} doublons supprimés`,
- );
- if (codes.length === 0) {
- job.status = "success";
- job.message = "Aucun code centrale valide pour ce fournisseur";
- job.finishedAt = new Date().toISOString();
- return;
- }
-
- // Contrat métier strict : toujours 12 mois complets glissants.
- // Une variable d'environnement ne doit pas pouvoir raccourcir la série.
- const dateFilter = buildGridNetworkQlikDateFilter(new Date(), QLIK_MONTHS_BACK_DEFAULT);
- job.periode = dateFilter.label;
- job.dateDebut = dateFilter.dateDebut;
- job.dateFin = dateFilter.dateFin;
- console.log(
- `[api/qlik/sync] job=${job.jobId} → extraction Qlik pour ${codes.length} codes — 12 mois complets ${dateFilter.label} (${dateFilter.dateDebut} → ${dateFilter.dateFin})…`,
- );
- // Le code fournisseur est transmis en plus des codes : s'il désigne dans
- // Qlik le même périmètre (couverture vérifiée côté extracteur), une seule
- // sélection remplace les dizaines de milliers de `SelectValues` par code.
- // Les codes restent le repli et le contrôle de couverture.
- const metrics = await fetchNetworkMetricsPlaywright(codes, undefined, dateFilter, job.fournisseur);
- job.fetched = metrics.size;
- console.log(`[api/qlik/sync] job=${job.jobId} ← Qlik a renvoyé ${metrics.size} produits réseau`);
- const count = await upsertNetworkMetrics([...metrics.values()]);
- job.upserted = count;
- console.log(`[api/qlik/sync] job=${job.jobId} ${count} lignes upsert dans le cache`);
- job.status = "success";
- job.finishedAt = new Date().toISOString();
- } catch (e) {
- applyJobError(job, e);
- } finally {
- await stopCapture(job.jobId, `statut final=${job.status}${job.error ? ` — ${job.error}` : ""}`);
- }
-}
-
-/**
- * Inscrit une erreur dans le job, en traduisant la saturation mémoire du
- * serveur Qlik en message actionnable (ce n'est PAS un bug CollectFlow :
- * l'app Qlik ne se charge même pas).
- */
-function applyJobError(job: QlikSyncJob, e: unknown): void {
- const msg = e instanceof Error ? e.message : String(e);
- console.error(`[api/qlik/sync] job=${job.jobId}`, msg);
- job.status = "error";
- const lower = msg.toLowerCase();
- if (lower.includes("out of memory") || lower.includes("not enough memory") || lower.includes("file corrupted") || lower.includes('"code":6') || lower.includes('"code":3002')) {
- job.error = "Serveur Qlik saturé : mémoire insuffisante pour charger l'application. Réessayez plus tard (ou faites libérer / augmenter la RAM du serveur Qlik).";
- } else {
- job.error = msg;
- }
- job.finishedAt = new Date().toISOString();
-}
-
-/**
- * Extraction Qlik pour UN seul code centrale (fiche produit).
- *
- * Beaucoup plus légère que la sync fournisseur : un seul code au lieu de
- * plusieurs centaines, sur la même fenêtre 12 mois glissants. Réutilise
- * exactement le même extracteur, donc le même détail mensuel.
- */
-async function runProductJob(job: QlikSyncJob): Promise {
- startCapture(job.jobId, `sync produit=${job.codeCentrale} démarrée le ${job.startedAt}`);
- try {
- const code = job.codeCentrale!;
- job.requested = 1;
-
- const dateFilter = buildGridNetworkQlikDateFilter(new Date(), QLIK_MONTHS_BACK_DEFAULT);
- job.periode = dateFilter.label;
- job.dateDebut = dateFilter.dateDebut;
- job.dateFin = dateFilter.dateFin;
- console.log(
- `[api/qlik/sync] job=${job.jobId} → extraction Qlik produit (1 code) — fenêtre ${dateFilter.label} (${dateFilter.dateDebut} → ${dateFilter.dateFin})…`,
- );
-
- const metrics = await fetchNetworkMetricsPlaywright([code], undefined, dateFilter);
- job.fetched = metrics.size;
- if (metrics.size === 0) {
- job.status = "success";
- job.message = "Ce code centrale est inconnu de Qlik (aucune vente réseau sur la période)";
- job.finishedAt = new Date().toISOString();
- return;
- }
- const count = await upsertNetworkMetrics([...metrics.values()]);
- job.upserted = count;
- job.status = "success";
- job.message = "Données réseau récupérées";
- job.finishedAt = new Date().toISOString();
- console.log(`[api/qlik/sync] job=${job.jobId} produit ${code} — ${count} ligne(s) upsert`);
- } catch (e) {
- applyJobError(job, e);
- } finally {
- await stopCapture(job.jobId, `statut final=${job.status}${job.error ? ` — ${job.error}` : ""}`);
- }
-}
-
-/**
- * GET /api/qlik/sync?fournisseur=XXX ou ?codeCentrale=YYY
- * Retourne l'état courant du job pour cette cible. Si aucun job n'est
- * connu, renvoie un état "idle" (avec un message explicite). Permet au
- * frontend de reprendre l'état après un reload et de poller en arrière-plan.
- */
-export async function GET(req: NextRequest) {
- const codeCentrale = req.nextUrl.searchParams.get("codeCentrale");
- const fournisseur = req.nextUrl.searchParams.get("fournisseur");
-
- // Mode produit : ouvert à tout utilisateur connecté.
- if (codeCentrale) {
- const denied = await sessionOuReponse();
- if (denied instanceof Response) return denied;
- const job = jobs.get(jobKeyForProduct(codeCentrale));
- if (!job) {
- return NextResponse.json({ success: true, ...idleJob("", codeCentrale) });
- }
- return NextResponse.json({ success: true, ...publicJob(job) });
- }
-
- // Mode fournisseur : admin uniquement (inchangé).
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- if (!fournisseur) {
- return NextResponse.json({ error: "Param 'fournisseur' ou 'codeCentrale' requis" }, { status: 400 });
- }
- const job = jobs.get(fournisseur);
- if (!job) {
- return NextResponse.json({ success: true, ...idleJob(fournisseur) });
- }
- return NextResponse.json({ success: true, ...publicJob(job) });
-}
-
-/**
- * POST /api/qlik/sync?fournisseur=XXX
- * Démarre (ou réutilise si déjà running) un job d'extraction en arrière-plan
- * et retourne *immédiatement* { success, status, jobId, ... }. Le client doit
- * ensuite poller GET pour suivre l'avancement et être notifié de la fin.
- */
-export async function POST(req: NextRequest) {
- const codeCentraleParam = req.nextUrl.searchParams.get("codeCentrale");
-
- // ─── Mode produit : 1 code centrale, ouvert à tout utilisateur connecté ───
- if (codeCentraleParam) {
- const denied = await sessionOuReponse();
- if (denied instanceof Response) return denied;
-
- // Même validation que la sync fournisseur (trim, rejet des vides / "-" /
- // codes hors charset) pour ne jamais envoyer de saleté à l'Engine Qlik.
- const { accepted } = filterCentralCodes([codeCentraleParam]);
- if (accepted.length === 0) {
- return NextResponse.json({ error: "Code centrale invalide" }, { status: 400 });
- }
- const code = accepted[0];
- const key = jobKeyForProduct(code);
-
- const existingProduct = jobs.get(key);
- if (existingProduct && existingProduct.status === "running") {
- return NextResponse.json({ success: true, ...publicJob(existingProduct) });
- }
-
- if (runningProductJobs() >= MAX_CONCURRENT_PRODUCT_JOBS) {
- return NextResponse.json(
- { error: "Trop d'extractions Qlik en cours. Réessayez dans quelques instants." },
- { status: 429 },
- );
- }
-
- const productJob: QlikSyncJob = {
- jobId: newJobId(),
- fournisseur: "",
- codeCentrale: code,
- status: "running",
- requested: 0,
- fetched: 0,
- upserted: 0,
- startedAt: new Date().toISOString(),
- };
- jobs.set(key, productJob);
- console.log(`[api/qlik/sync] job=${productJob.jobId} démarré pour codeCentrale=${code}`);
-
- void runProductJob(productJob).catch((e) => applyJobError(productJob, e));
-
- return NextResponse.json({ success: true, ...publicJob(productJob) });
- }
-
- // ─── Mode fournisseur : admin uniquement (inchangé) ──────────────────────
- const denied = await adminOuReponse();
- if (denied instanceof Response) return denied;
-
- const fournisseur = req.nextUrl.searchParams.get("fournisseur");
- if (!fournisseur) {
- return NextResponse.json({ error: "Param 'fournisseur' ou 'codeCentrale' requis" }, { status: 400 });
- }
-
- const existing = jobs.get(fournisseur);
- if (existing && existing.status === "running") {
- // Un job tourne déjà pour ce fournisseur : on le réutilise.
- return NextResponse.json({ success: true, ...publicJob(existing) });
- }
-
- const job: QlikSyncJob = {
- jobId: newJobId(),
- fournisseur,
- status: "running",
- requested: 0,
- fetched: 0,
- upserted: 0,
- startedAt: new Date().toISOString(),
- };
- jobs.set(fournisseur, job);
- console.log(`[api/qlik/sync] job=${job.jobId} démarré pour fournisseur=${fournisseur}`);
-
- // Lancement fire-and-forget. On ne `await` PAS l'extraction ici : on
- // renvoie tout de suite au client et il polle GET. Les erreurs sont
- // capturées dans runJob et inscrites dans le job.
- void runJob(job).catch((e) => {
- // Filet de sécurité (runJob ne devrait pas throw, mais on ne veut
- // jamais qu'une exception non capturée crashe le process).
- const msg = e instanceof Error ? e.message : String(e);
- console.error(`[api/qlik/sync] job=${job.jobId} crash non géré`, msg);
- job.status = "error";
- job.error = msg;
- job.finishedAt = new Date().toISOString();
- });
-
- return NextResponse.json({ success: true, ...publicJob(job) });
-}
diff --git a/src/app/api/test-db/route.ts b/src/app/api/test-db/route.ts
deleted file mode 100644
index 35dbc20..0000000
--- a/src/app/api/test-db/route.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { NextResponse } from 'next/server';
-import { db } from '@/db';
-import { sql } from 'drizzle-orm';
-import { pgGetStockForCodeins } from '@/lib/pg-ff-client';
-import { adminOuReponse } from '@/lib/authz';
-
-export async function GET(request: Request) {
- const acces = await adminOuReponse();
- if (acces instanceof Response) return acces;
-
- try {
- const { searchParams } = new URL(request.url);
- const codein = searchParams.get('codein') || '334152';
-
- const map = await pgGetStockForCodeins([codein]);
-
- const fouResult = await db.execute(sql`
- SELECT
- a.codein::text AS codein,
- COALESCE(fi.nom, af.code, 'Sans fournisseur')::text AS fournisseur
- FROM articles a
- LEFT JOIN artfou1 af ON af.art_no_id = a.no_id AND af.preference = 1
- LEFT JOIN fouident fi ON fi.code = af.code
- WHERE a.codein::text = ${codein}
- `);
-
- return NextResponse.json({
- stock: Object.fromEntries(map),
- fou: fouResult.rows,
- });
- } catch (e) {
- // Pas de pile d'appels dans la réponse : elle reste dans les journaux du serveur.
- console.error('[api/test-db]', e);
- return NextResponse.json({ error: (e as Error).message }, { status: 500 });
- }
-}
diff --git a/src/app/api/v1/fournisseurs/route.ts b/src/app/api/v1/fournisseurs/route.ts
deleted file mode 100644
index 44aba51..0000000
--- a/src/app/api/v1/fournisseurs/route.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail } from "@/lib/api-response";
-import { fournisseursQuerySchema } from "@/lib/api-schemas";
-import { listGridSuppliers } from "@/lib/grid-store";
-import { pgGetFournisseurs } from "@/lib/pg-ff-client";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/v1/fournisseurs?search=…&withData=1
- *
- * Liste des fournisseurs. Par défaut, tout le référentiel (`fouident`), enrichi de la
- * fraîcheur de l'instantané de grille quand il existe — ce qui permet à l'appelant de
- * savoir d'avance quels fournisseurs `/api/v1/grid` peut servir immédiatement.
- *
- * `withData=1` restreint aux seuls fournisseurs déjà présents dans l'instantané.
- */
-export async function GET(req: NextRequest) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const parsed = fournisseursQuerySchema.safeParse(Object.fromEntries(req.nextUrl.searchParams));
- if (!parsed.success) {
- return fail("bad_request", "Paramètres invalides.", parsed.error.issues);
- }
- const { search, withData } = parsed.data;
-
- const snapshot = await listGridSuppliers();
- const byCode = new Map(snapshot.map((s) => [s.codeFournisseur, s]));
-
- if (withData === "1") {
- const term = search?.toLowerCase();
- const data = snapshot
- .filter((s) => !term
- || s.codeFournisseur.toLowerCase().includes(term)
- || (s.nomFournisseur ?? "").toLowerCase().includes(term))
- .map((s) => ({
- code: s.codeFournisseur,
- nom: s.nomFournisseur,
- hasSnapshot: true,
- rowCount: s.rowCount,
- computedAt: s.computedAt,
- }));
- return ok(data, { meta: { total: data.length, scope: "instantané uniquement" } });
- }
-
- const fournisseurs = await pgGetFournisseurs(search);
- const data = fournisseurs.map((f) => {
- const snap = byCode.get(f.code);
- return {
- code: f.code,
- nom: f.nom,
- hasSnapshot: Boolean(snap),
- rowCount: snap?.rowCount ?? 0,
- computedAt: snap?.computedAt ?? null,
- };
- });
-
- return ok(data, { meta: { total: data.length, withSnapshot: byCode.size } });
-}
diff --git a/src/app/api/v1/gammes/route.ts b/src/app/api/v1/gammes/route.ts
deleted file mode 100644
index 1c3d019..0000000
--- a/src/app/api/v1/gammes/route.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail } from "@/lib/api-response";
-import { gammesBatchBodySchema } from "@/lib/api-schemas";
-import { affecterGammes, lireCorpsJson } from "@/lib/api-gammes";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-// Idem /api/v1/grid : le calcul à la demande peut prendre plusieurs secondes.
-export const maxDuration = 300;
-
-/**
- * POST /api/v1/gammes { "fournisseur": "…", "changes": [{ "codein": "…", "gamme": "A" }, …] }
- *
- * Propose la gamme de plusieurs articles d'un fournisseur en un appel. Les
- * propositions restent **à valider** dans la Grille (cf. lib/api-gammes).
- * Tout ou rien : un article inconnu chez le fournisseur fait échouer l'appel (404).
- */
-export async function POST(req: NextRequest) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const corps = await lireCorpsJson(req);
- if (corps instanceof Response) return corps;
- const parsed = gammesBatchBodySchema.safeParse(corps);
- if (!parsed.success) {
- return fail("bad_request", "Corps de requête invalide.", parsed.error.issues);
- }
- const { fournisseur, changes, compute } = parsed.data;
-
- const res = await affecterGammes({
- codeFournisseur: fournisseur,
- changes,
- compute,
- auteur: authCtx.subject,
- });
- if (res instanceof Response) return res;
-
- return ok(res.resultats, {
- meta: {
- codeFournisseur: res.codeFournisseur,
- nomFournisseur: res.nomFournisseur,
- demandes: res.resultats.length,
- modifies: res.resultats.filter((r) => r.modifie).length,
- aValider: res.resultats.filter((r) => r.statut === "a_valider").length,
- enregistreLe: new Date().toISOString(),
- },
- });
-}
diff --git a/src/app/api/v1/grid/route.ts b/src/app/api/v1/grid/route.ts
deleted file mode 100644
index 5409d5b..0000000
--- a/src/app/api/v1/grid/route.ts
+++ /dev/null
@@ -1,223 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail, buildPagination } from "@/lib/api-response";
-import { gridQuerySchema, pickFields, toSortKey } from "@/lib/api-schemas";
-import { queryGridRows, getGridFreshness } from "@/lib/grid-store";
-import { enrichRows } from "@/lib/api-enrich";
-import { getProductRows } from "@/features/grid/api/get-product-rows";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-// Le calcul à la demande (premier appel sur un fournisseur inconnu) enchaîne
-// plusieurs requêtes SQL sur la base miroir FF : on laisse de la marge.
-export const maxDuration = 300;
-
-/**
- * GET /api/v1/grid?fournisseur=…&gamme=&code1..3=&search=&sort=&order=&page=&limit=&fields=&compute=
- *
- * Lignes de grille d'un fournisseur, filtrées / triées / paginées **en SQL** depuis
- * l'instantané persisté (`grid_rows`).
- *
- * Si le fournisseur n'a pas encore d'instantané, l'endpoint le **calcule à la demande**
- * (`compute=1`, défaut) : sans cela, un appelant externe ne pourrait consulter que les
- * fournisseurs déjà ouverts dans la Grille par un humain. Le calcul est protégé par le
- * cache et le verrou anti-concurrence de `getProductRows()`, et il persiste l'instantané
- * au passage — les appels suivants repassent donc par le chemin rapide.
- *
- * `compute=0` restaure le comportement strict : échec immédiat en `202 not_ready`.
- */
-export async function GET(req: NextRequest) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const parsed = gridQuerySchema.safeParse(Object.fromEntries(req.nextUrl.searchParams));
- if (!parsed.success) {
- return fail("bad_request", "Paramètres invalides.", parsed.error.issues);
- }
- const q = parsed.data;
-
- // Distingue « fournisseur jamais calculé » de « filtres sans résultat » (200 vide).
- let freshness = await getGridFreshness(q.fournisseur);
- let computedOnDemand = false;
-
- if (!freshness) {
- if (q.compute === "0") {
- return fail(
- "not_ready",
- `Aucun instantané pour le fournisseur « ${q.fournisseur} ». Relancez sans « compute=0 » pour le calculer à la demande.`,
- { fournisseur: q.fournisseur },
- );
- }
-
- console.log(`[api/v1/grid] instantané absent pour ${q.fournisseur} — calcul à la demande (via ${authCtx.via})`);
- try {
- // magasin TOTAL : c'est la seule variante persistée par getProductRows,
- // et ProductRow embarque déjà les ventilations par magasin.
- await getProductRows({ codeFournisseur: q.fournisseur, magasin: "TOTAL" });
- } catch (e) {
- const msg = e instanceof Error ? e.message : String(e);
- console.error(`[api/v1/grid] calcul à la demande KO pour ${q.fournisseur}:`, msg);
- return fail(
- "internal_error",
- `Le calcul de la grille a échoué pour le fournisseur « ${q.fournisseur} ».`,
- { fournisseur: q.fournisseur },
- );
- }
-
- freshness = await getGridFreshness(q.fournisseur);
- if (!freshness) {
- // Calcul réussi mais aucune ligne : le code fournisseur n'existe pas, ou
- // il n'a aucun article. À distinguer d'une panne.
- return fail(
- "not_found",
- `Aucun article pour le fournisseur « ${q.fournisseur} ». Vérifiez le code auprès de /api/v1/fournisseurs.`,
- { fournisseur: q.fournisseur },
- );
- }
- computedOnDemand = true;
- }
-
- const filtres = {
- codeFournisseur: q.fournisseur,
- gamme: q.gamme,
- code1: q.code1,
- code2: q.code2,
- code3: q.code3,
- nomenclature: q.nomenclature,
- search: q.search,
- sort: toSortKey(q.sort),
- order: q.order,
- };
-
- // Sans `limit`, la réponse peut porter tout un fournisseur — et certains en
- // comptent plus de 130 000. Tout charger puis tout sérialiser d'un bloc ferait
- // exploser la mémoire du processus : on diffuse par lots, à mémoire constante.
- if (q.limit == null) {
- return streamAllRows(req, filtres, q, freshness, computedOnDemand);
- }
-
- const result = await queryGridRows({ ...filtres, page: q.page, limit: q.limit });
-
- // Métriques Qlik et gamme serveur relues au moment de l'appel (voir api-enrich).
- const rows = q.enrich === "1" ? await enrichRows(result.rows) : result.rows;
-
- const pagination = buildPagination(q.page, q.limit, result.total);
-
- return ok(
- rows.map((r) => pickFields(r, q.fields)),
- {
- pagination,
- meta: {
- fournisseur: q.fournisseur,
- computedAt: result.computedAt,
- snapshotComputedAt: freshness.computedAt,
- snapshotRowCount: freshness.rowCount,
- enrichi: q.enrich === "1",
- /** true = l'instantané n'existait pas et vient d'être calculé par cet appel. */
- computedOnDemand,
- /**
- * true = cette réponse contient **toutes** les lignes du fournisseur.
- * Dit explicitement à un appelant — en particulier un agent — s'il
- * peut s'arrêter là, au lieu de le laisser déduire d'une pagination
- * qu'il risque d'ignorer.
- */
- complet: !pagination.hasMore,
- ...(pagination.hasMore
- ? {
- avertissement:
- `Réponse partielle : ${rows.length} lignes sur ${result.total}, parce que « limit » a été précisé. `
- + `Retirez « limit » pour obtenir tout le fournisseur en un appel, ou passez à page=${q.page + 1}.`,
- }
- : {}),
- },
- },
- );
-}
-
-/** Lots internes : compromis entre nombre d'allers-retours SQL et mémoire retenue. */
-const STREAM_BATCH = 1000;
-
-type Filtres = Parameters[0];
-
-/**
- * Diffuse **toutes** les lignes du fournisseur en une seule réponse JSON, sans
- * jamais la construire entièrement en mémoire.
- *
- * La forme reste celle des autres réponses (`{ data, pagination, meta }`) : un
- * client existant ne voit aucune différence, il reçoit simplement les octets au
- * fil de l'eau. `pagination` et `meta` sont écrits en dernier, une fois le total
- * connu — l'ordre des clés n'a aucune importance en JSON.
- *
- * Une erreur survenant après les premiers octets ne peut plus changer le code
- * HTTP : on ferme alors le document avec `meta.erreur`, pour que l'appelant
- * détecte une réponse tronquée au lieu de la croire complète.
- */
-function streamAllRows(
- req: NextRequest,
- filtres: Filtres,
- q: { enrich: string; fields?: string; fournisseur: string },
- freshness: { rowCount: number; computedAt: string | null },
- computedOnDemand: boolean,
-): Response {
- const encoder = new TextEncoder();
-
- const stream = new ReadableStream({
- async start(controller) {
- const write = (s: string) => controller.enqueue(encoder.encode(s));
- let envoyees = 0;
- let total = 0;
- let computedAt: string | null = null;
- let erreur: string | null = null;
-
- write('{"data":[');
- try {
- for (let page = 1; ; page++) {
- const lot = await queryGridRows({ ...filtres, page, limit: STREAM_BATCH });
- if (page === 1) {
- total = lot.total;
- computedAt = lot.computedAt;
- }
- if (lot.rows.length === 0) break;
-
- const enrichies = q.enrich === "1" ? await enrichRows(lot.rows) : lot.rows;
- for (const r of enrichies) {
- write((envoyees === 0 ? "" : ",") + JSON.stringify(pickFields(r, q.fields)));
- envoyees++;
- }
- if (lot.rows.length < STREAM_BATCH) break;
- }
- } catch (e) {
- erreur = e instanceof Error ? e.message : String(e);
- console.error(`[api/v1/grid] diffusion interrompue pour ${q.fournisseur} après ${envoyees} lignes:`, erreur);
- }
-
- const complet = erreur === null && envoyees === total;
- write("]," + JSON.stringify({
- pagination: { page: 1, limit: envoyees, total, totalPages: 1, hasMore: !complet },
- meta: {
- fournisseur: q.fournisseur,
- computedAt,
- snapshotComputedAt: freshness.computedAt,
- snapshotRowCount: freshness.rowCount,
- enrichi: q.enrich === "1",
- computedOnDemand,
- diffuse: true,
- complet,
- ...(erreur
- ? { erreur: `Diffusion interrompue après ${envoyees} lignes sur ${total} : ${erreur}` }
- : {}),
- },
- }).slice(1));
- controller.close();
- },
- });
-
- return new Response(stream, {
- headers: {
- "Content-Type": "application/json; charset=utf-8",
- "Cache-Control": "no-store",
- // Empêche un proxy de tamponner la réponse entière avant de la relayer.
- "X-Accel-Buffering": "no",
- },
- });
-}
diff --git a/src/app/api/v1/network/[codeCentrale]/route.ts b/src/app/api/v1/network/[codeCentrale]/route.ts
deleted file mode 100644
index ae715b1..0000000
--- a/src/app/api/v1/network/[codeCentrale]/route.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail } from "@/lib/api-response";
-import { getNetworkMetricsByCodeCentrale } from "@/lib/qlik-network-cache";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/v1/network/:codeCentrale
- *
- * Métriques réseau Qlik d'un produit (CA, quantité, nombre de magasins, CA/magasin,
- * marge %) et sa courbe de quantités mensuelles sur 12 mois glissants.
- *
- * Lecture **exclusive** de la table `qlik_network_metrics` : aucun appel à Qlik n'est
- * déclenché. Pour interroger Qlik en direct (y compris sur des produits que nous ne
- * référençons pas), c'est la page Produits — bien plus lente, et volontairement
- * séparé de cette API.
- */
-export async function GET(
- req: NextRequest,
- ctx: { params: Promise<{ codeCentrale: string }> },
-) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const { codeCentrale } = await ctx.params;
- if (!codeCentrale) return fail("bad_request", "Paramètre 'codeCentrale' requis.");
-
- const metrics = await getNetworkMetricsByCodeCentrale([codeCentrale]);
- const found = metrics.get(codeCentrale);
- if (!found) {
- return fail(
- "not_found",
- `Aucune donnée réseau en cache pour le code centrale « ${codeCentrale} ». Lancez une synchronisation Qlik ou une recherche réseau.`,
- );
- }
-
- return ok({ codeCentrale, ...found }, { meta: { fetchedAt: found.fetchedAt, source: "cache" } });
-}
diff --git a/src/app/api/v1/nomenclatures/route.ts b/src/app/api/v1/nomenclatures/route.ts
deleted file mode 100644
index c760406..0000000
--- a/src/app/api/v1/nomenclatures/route.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail } from "@/lib/api-response";
-import { nomenclaturesQuerySchema } from "@/lib/api-schemas";
-import { listGridNomenclatures, getGridFreshness } from "@/lib/grid-store";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/v1/nomenclatures?fournisseur=…&niveau=1|2|3&parent=…
- *
- * Répartition des articles d'un fournisseur par poste de nomenclature, avec le
- * nombre d'articles et le CA de chacun.
- *
- * C'est la porte d'entrée pour traiter un gros fournisseur : certains dépassent
- * 130 000 articles, et tout récupérer d'un coup n'a de sens ni pour une IA ni
- * pour une application. On liste d'abord les postes — quelques dizaines de
- * lignes — puis on interroge `/grid?fournisseur=…&nomenclature=…` poste par poste.
- *
- * Les codes sont hiérarchiques par préfixe (6 chiffres, de 31xxxx à 40xxxx) :
- * niveau 1 = « 32 », niveau 2 = « 3202 », niveau 3 = « 320211 ». `parent` accepte
- * un préfixe pour descendre l'arborescence sans tout charger.
- */
-export async function GET(req: NextRequest) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const parsed = nomenclaturesQuerySchema.safeParse(Object.fromEntries(req.nextUrl.searchParams));
- if (!parsed.success) {
- return fail("bad_request", "Paramètres invalides.", parsed.error.issues);
- }
- const { fournisseur, niveau, parent } = parsed.data;
-
- // Même distinction que /grid : « pas encore calculé » n'est pas « vide ».
- const freshness = await getGridFreshness(fournisseur);
- if (!freshness) {
- return fail(
- "not_ready",
- `Aucun instantané pour le fournisseur « ${fournisseur} ». Appelez /api/v1/grid?fournisseur=${fournisseur} une fois pour le calculer.`,
- { fournisseur },
- );
- }
-
- const postes = await listGridNomenclatures(fournisseur, niveau, parent);
- const nbArticles = postes.reduce((s, p) => s + p.nbArticles, 0);
-
- return ok(postes, {
- meta: {
- fournisseur,
- niveau,
- parent: parent ?? null,
- nbPostes: postes.length,
- /** Total couvert par les postes listés — à rapprocher de snapshotRowCount. */
- nbArticles,
- snapshotRowCount: freshness.rowCount,
- snapshotComputedAt: freshness.computedAt,
- /**
- * Le paramètre de /grid à utiliser avec les `code` renvoyés ci-dessus.
- * `nomenclature` filtre par préfixe et fonctionne aux trois niveaux.
- */
- filtreGrid: "nomenclature",
- },
- });
-}
diff --git a/src/app/api/v1/openapi.json/route.ts b/src/app/api/v1/openapi.json/route.ts
deleted file mode 100644
index 3b2588d..0000000
--- a/src/app/api/v1/openapi.json/route.ts
+++ /dev/null
@@ -1,537 +0,0 @@
-import { NextRequest } from "next/server";
-import { GRID_SORT_KEYS } from "@/lib/grid-store";
-import { GAMMES } from "@/lib/gammes";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/v1/openapi.json — spécification OpenAPI 3.1 de l'API CollectFlow.
- *
- * **Volontairement accessible sans authentification.** Le document ne décrit que la
- * structure de l'API (chemins, paramètres, schémas) et ne contient aucune donnée
- * métier ; or ChatGPT et les autres plateformes d'agents importent le schéma par URL,
- * avant même que la clé ne soit configurée. Exiger une clé ici rendrait l'import
- * impossible.
- *
- * `servers` est construit depuis l'hôte appelant (ou COLLECTFLOW_PUBLIC_URL) : les
- * Actions ChatGPT exigent une URL **absolue**, une URL relative étant rejetée.
- */
-export async function GET(req: NextRequest) {
- const configured = process.env.COLLECTFLOW_PUBLIC_URL?.trim().replace(/\/+$/, "");
- const origin = configured || req.nextUrl.origin;
-
- const paginationParams = [
- { name: "page", in: "query", schema: { type: "integer", minimum: 1, default: 1 }, description: "Numéro de page." },
- { name: "limit", in: "query", schema: { type: "integer", minimum: 1 }, description: "Lignes par page, sans plafond. Sur /grid, OMETTRE ce paramètre renvoie toutes les lignes du fournisseur en un seul appel — c'est le mode recommandé. Sur les autres endpoints, le défaut est 100." },
- ];
- const sortParams = [
- { name: "sort", in: "query", schema: { type: "string", enum: GRID_SORT_KEYS }, description: "Colonne de tri." },
- { name: "order", in: "query", schema: { type: "string", enum: ["asc", "desc"], default: "desc" }, description: "Sens du tri." },
- {
- name: "fields",
- in: "query",
- schema: { type: "string" },
- description:
- "Colonnes à retourner, séparées par des virgules (ex. « codein,libelle1,totalCa »). "
- + "À utiliser systématiquement : une ligne complète contient les séries mensuelles et les "
- + "ventilations par magasin, ce qui est très volumineux. `codein` est toujours inclus.",
- },
- {
- name: "enrich",
- in: "query",
- schema: { type: "string", enum: ["0", "1"], default: "1" },
- description:
- "1 (défaut) : relit les métriques réseau Qlik (`network`) et la gamme serveur "
- + "(`codeGammeServeur`) au moment de l'appel. 0 : sert l'instantané brut.",
- },
- ];
-
- const codesGamme = GAMMES.map((g) => g.code);
- const legendeGammes = GAMMES.map((g) => `${g.code} (${g.nom})`).join(", ");
- const erreur = (description: string) => ({
- description,
- content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } },
- });
-
- const spec = {
- openapi: "3.1.0",
- info: {
- title: "CollectFlow API",
- version: "1.0.0",
- description:
- "Données de la grille CollectFlow : ventes sur 12 mois par magasin, stock, marges, "
- + "gammes et métriques du réseau Qlik (~270 magasins Foir'Fouille), plus la recherche de produits.\n\n"
- + "**N'importe quel fournisseur peut être interrogé directement.** Les réponses sont servies "
- + "depuis un instantané persisté ; si le fournisseur demandé n'en a pas encore, `/grid` le calcule "
- + "à la demande. Ce premier appel prend alors plusieurs secondes, les suivants sont immédiats. "
- + "Passez `compute=0` pour refuser ce calcul et obtenir un `202 not_ready` immédiat.\n\n"
- + "**Aucun endpoint ne contacte Qlik en direct** : les métriques réseau viennent d'un cache "
- + "alimenté par une synchronisation séparée.\n\n"
- + "Deux informations sont relues à chaque appel car elles évoluent indépendamment : les métriques "
- + "réseau Qlik (`network`, `null` s'il n'y en a pas) et la gamme serveur non modifiée "
- + "(`codeGammeServeur`).\n\n"
- + "**Gammes** : `PUT /products/{codein}/gamme` (un article) et `POST /gammes` (plusieurs) "
- + "**proposent** une gamme. La proposition reste **à valider** : elle apparaît dans la Grille "
- + "comme une modification non enregistrée, pour voir quels produits changent de gamme, et "
- + "n'est appliquée qu'une fois validée par un utilisateur (« Enregistrer »). D'ici là, "
- + "`codeGamme` est inchangée et la proposition figure dans `gammeAValider`. Une fois validée, "
- + "`codeGammeServeur` reste la gamme en base FF jusqu'à l'import des gammes modifiées.",
- },
- servers: [{ url: `${origin}/api/v1`, description: "API CollectFlow" }],
- security: [{ ApiKeyAuth: [] }],
- components: {
- securitySchemes: {
- ApiKeyAuth: { type: "apiKey", in: "header", name: "X-API-Key" },
- },
- schemas: {
- Error: {
- type: "object",
- properties: {
- error: {
- type: "object",
- properties: {
- code: {
- type: "string",
- enum: ["unauthorized", "forbidden", "bad_request", "not_found", "not_ready", "internal_error"],
- },
- message: { type: "string" },
- },
- },
- },
- },
- Pagination: {
- type: "object",
- properties: {
- page: { type: "integer" },
- limit: { type: "integer" },
- total: { type: "integer" },
- totalPages: { type: "integer" },
- hasMore: { type: "boolean", description: "true = il reste des pages. Sur /grid, meta.complet dit la même chose en positif." },
- },
- },
- Fournisseur: {
- type: "object",
- properties: {
- code: { type: "string", description: "Code fournisseur, à passer au paramètre `fournisseur`." },
- nom: { type: ["string", "null"] },
- hasSnapshot: { type: "boolean", description: "false = données pas encore disponibles pour ce fournisseur." },
- rowCount: { type: "integer" },
- computedAt: { type: ["string", "null"], format: "date-time" },
- },
- },
- NetworkMetrics: {
- type: ["object", "null"],
- description: "Métriques du réseau Qlik. `null` quand le produit n'a pas de données réseau.",
- properties: {
- caReseau: { type: "number" },
- qteReseau: { type: "number" },
- nbMagasinsReseau: { type: "integer", description: "Nombre de magasins du réseau vendant le produit (sur ~270)." },
- caParMagasinReseau: { type: "number", description: "CA moyen par magasin : normalise la présence, préférable au CA brut pour comparer." },
- margePctReseau: { type: "number", description: "Taux de marge, ratio brut (0.32 = 32 %)." },
- qteByMonth: { type: ["object", "null"], description: "Quantités vendues par mois, clés « YYYY-MM »." },
- fetchedAt: { type: ["string", "null"], format: "date-time" },
- },
- },
- Product: {
- type: "object",
- description:
- "Ligne de grille : un article chez un fournisseur. La liste de propriétés ci-dessous "
- + "n'est pas exhaustive — la réponse contient l'intégralité de la ligne (une soixantaine "
- + "de champs). Utilisez `fields` pour n'en garder qu'une partie.",
- properties: {
- codein: { type: "string", description: "Identifiant interne de l'article." },
- codeFournisseur: { type: "string" },
- nomFournisseur: { type: "string" },
- libelle1: { type: "string", description: "Libellé de l'article." },
- gtin: { type: "string" },
- reference: { type: "string" },
- codeCentrale: { type: "string", description: "Code centrale — clé de jointure avec le réseau Qlik." },
- codeGammeServeur: {
- type: ["string", "null"],
- description:
- "Gamme **non modifiée**, telle qu'elle existe en base. C'est celle à utiliser pour "
- + "raisonner. `null` = aucune gamme. Valeurs : " + legendeGammes + ".",
- },
- codeGamme: { type: ["string", "null"], description: "Gamme courante, modifications validées dans CollectFlow comprises." },
- gammeAValider: { type: ["string", "null"], description: "Gamme proposée par l'API et pas encore validée dans la Grille. `null` = aucune proposition en attente." },
- totalCa: { type: "number", description: "CA sur 12 mois, nos magasins." },
- totalQuantite: { type: "number" },
- totalMarge: { type: "number" },
- tauxMarge: { type: "number" },
- stockActuel: { type: "number" },
- pcb: { type: "number", description: "Conditionnement (nombre d'unités par colis)." },
- prixAchat: { type: "number" },
- prixVente: { type: "number" },
- derniereVente: { type: "string", format: "date" },
- nbJoursDerniereVente: { type: "integer" },
- sales12m: { type: "object", description: "Quantités vendues par mois, clés « YYYYMM »." },
- stock12m: { type: "object", description: "Stock de fin de mois, clés « YYYYMM »." },
- receptions12m: { type: "object", description: "Quantités reçues par mois, clés « YYYYMM »." },
- sales12mByStore: { type: "object", description: "Ventes par magasin (292, 579) puis par mois." },
- stock12mByStore: { type: "object", description: "Stock de fin de mois par magasin puis par mois." },
- receptions12mByStore: { type: "object", description: "Réceptions par magasin puis par mois." },
- qteReseauByMonth: { type: ["object", "null"], description: "Quantités vendues par le réseau, clés « YYYY-MM » — série derrière la tendance." },
- network: { $ref: "#/components/schemas/NetworkMetrics" },
- trend: { $ref: "#/components/schemas/Trend" },
- },
- },
- ResultatGamme: {
- type: "object",
- properties: {
- codein: { type: "string" },
- gamme: { type: "string", enum: codesGamme, description: "Gamme proposée." },
- gammePrecedente: { type: ["string", "null"], description: "Gamme enregistrée au moment de l'appel." },
- codeGammeServeur: { type: ["string", "null"], description: "Gamme en base FF, non modifiée par l'API." },
- modifie: { type: "boolean", description: "true = proposition déposée, à valider dans la Grille. false = l'article a déjà cette gamme (une proposition en attente pour lui est retirée)." },
- statut: { type: "string", enum: ["a_valider", "inchangee"], description: "`a_valider` : en attente de validation dans la Grille." },
- },
- },
- Trend: {
- type: ["object", "null"],
- description:
- "Tendance réseau sur 12 mois, par régression linéaire — la même que la colonne "
- + "« Tendance » de l'application. `null` si aucune série mensuelle n'est disponible.",
- properties: {
- direction: { type: "string", enum: ["up", "down", "flat"], description: "Seuil à ±8 % de variation modélisée." },
- pct: { type: ["number", "null"], description: "Variation modélisée sur la période (0.23 = +23 %)." },
- label: { type: "string", description: "Libellé prêt à afficher : « Forte hausse », « Stable »…" },
- monthsUsed: { type: "integer", description: "Nombre de mois réellement utilisés (12 au maximum)." },
- },
- },
- },
- },
- paths: {
- "/fournisseurs": {
- get: {
- operationId: "listerFournisseurs",
- summary: "Lister les fournisseurs",
- description:
- "Renvoie les fournisseurs et indique, via `hasSnapshot`, lesquels ont des données "
- + "immédiatement disponibles. À appeler en premier quand le code fournisseur est inconnu.",
- parameters: [
- { name: "search", in: "query", schema: { type: "string" }, description: "Filtre sur le nom ou le code." },
- { name: "withData", in: "query", schema: { type: "string", enum: ["0", "1"] }, description: "1 = uniquement ceux dont les données sont disponibles." },
- ],
- responses: {
- "200": {
- description: "Liste des fournisseurs",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: {
- data: { type: "array", items: { $ref: "#/components/schemas/Fournisseur" } },
- meta: { type: "object" },
- },
- },
- },
- },
- },
- "401": { description: "Clé d'API absente, invalide ou révoquée", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- },
- },
- },
- "/nomenclatures": {
- get: {
- operationId: "listerNomenclaturesFournisseur",
- summary: "Postes de nomenclature d'un fournisseur",
- description:
- "Répartition des articles d'un fournisseur par poste de nomenclature, avec le nombre "
- + "d'articles et le CA de chacun. **À utiliser avant /grid sur un gros fournisseur** : "
- + "certains dépassent 130 000 articles. On liste les postes (quelques dizaines de lignes), "
- + "puis on interroge /grid poste par poste avec le filtre indiqué par `meta.filtreGrid` "
- + "(code1, code2 ou code3).",
- parameters: [
- { name: "fournisseur", in: "query", required: true, schema: { type: "string" } },
- { name: "niveau", in: "query", schema: { type: "integer", enum: [1, 2, 3], default: 1 }, description: "1 = univers, 2 = famille, 3 = sous-famille." },
- { name: "parent", in: "query", schema: { type: "string" }, description: "Préfixe du poste parent, ex. « 32 » pour lister ses familles." },
- ],
- responses: {
- "200": {
- description: "Postes de nomenclature",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: {
- data: {
- type: "array",
- items: {
- type: "object",
- properties: {
- code: { type: "string", description: "À passer au filtre code1/code2/code3 de /grid." },
- libelle: { type: ["string", "null"] },
- nbArticles: { type: "integer" },
- totalCa: { type: "number" },
- totalQuantite: { type: "number" },
- },
- },
- },
- meta: { type: "object" },
- },
- },
- },
- },
- },
- "202": { description: "Fournisseur pas encore calculé", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- "400": { description: "Paramètres invalides", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- },
- },
- },
- "/grid": {
- get: {
- operationId: "listerProduitsFournisseur",
- summary: "Lister les produits d'un fournisseur",
- description:
- "Lignes de grille d'un fournisseur : ventes 12 mois, stock, marges, gammes et métriques "
- + "réseau. Fonctionne pour **n'importe quel** fournisseur : si ses données n'ont jamais été "
- + "calculées, l'API les calcule à la demande (premier appel de quelques secondes, "
- + "`meta.computedOnDemand = true`). Un `404` signifie que le code fournisseur n'existe pas "
- + "ou n'a aucun article — le signaler plutôt que de conclure à une panne.",
- parameters: [
- { name: "fournisseur", in: "query", required: true, schema: { type: "string" }, description: "Code fournisseur (voir listerFournisseurs)." },
- { name: "gamme", in: "query", schema: { type: "string" }, description: `Filtre sur la gamme (${codesGamme.join(", ")}).` },
- { name: "code1", in: "query", schema: { type: "string" }, description: "Filtre nomenclature niveau 1." },
- { name: "code2", in: "query", schema: { type: "string" }, description: "Filtre nomenclature niveau 2." },
- { name: "code3", in: "query", schema: { type: "string" }, description: "Filtre nomenclature niveau 3 (code exact)." },
- { name: "nomenclature", in: "query", schema: { type: "string" }, description: "Préfixe de nomenclature renvoyé par listerNomenclaturesFournisseur : 32, 3202 ou 320211. À préférer à code1/code2, qui peuvent être vides." },
- { name: "search", in: "query", schema: { type: "string" }, description: "Filtre texte : libellé, codein, GTIN, référence ou code centrale." },
- {
- name: "compute",
- in: "query",
- schema: { type: "string", enum: ["0", "1"], default: "1" },
- description:
- "1 (défaut) : calcule les données du fournisseur si elles n'existent pas encore. "
- + "0 : refuse le calcul et répond immédiatement 202 not_ready.",
- },
- ...sortParams,
- ...paginationParams,
- ],
- responses: {
- "200": {
- description: "Produits du fournisseur",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: {
- data: { type: "array", items: { $ref: "#/components/schemas/Product" } },
- pagination: { $ref: "#/components/schemas/Pagination" },
- meta: { type: "object" },
- },
- },
- },
- },
- },
- "202": { description: "Données pas encore calculées (uniquement avec compute=0)", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- "400": { description: "Paramètres invalides", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- "401": { description: "Clé d'API absente, invalide ou révoquée", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- "404": { description: "Fournisseur inconnu ou sans article", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- },
- },
- },
- "/products/search": {
- get: {
- operationId: "rechercherProduits",
- summary: "Rechercher des produits, tous fournisseurs confondus",
- description:
- "Recherche sur le libellé, le codein, le GTIN, la référence et le code centrale, sans "
- + "avoir à connaître le fournisseur. À utiliser dès qu'un produit est désigné par son nom.",
- parameters: [
- { name: "q", in: "query", required: true, schema: { type: "string", maxLength: 120 }, description: "Termes recherchés." },
- { name: "fournisseur", in: "query", schema: { type: "string" }, description: "Restreint à un fournisseur." },
- { name: "gamme", in: "query", schema: { type: "string" }, description: "Filtre sur la gamme." },
- ...sortParams,
- ...paginationParams,
- ],
- responses: {
- "200": {
- description: "Produits correspondants",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: {
- data: { type: "array", items: { $ref: "#/components/schemas/Product" } },
- pagination: { $ref: "#/components/schemas/Pagination" },
- meta: { type: "object" },
- },
- },
- },
- },
- },
- "401": { description: "Clé d'API absente, invalide ou révoquée", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- },
- },
- },
- "/products/{codein}": {
- get: {
- operationId: "obtenirProduit",
- summary: "Fiche complète d'un produit",
- description: "Toutes les données d'un article : séries mensuelles, ventilation par magasin, stock, marges, gammes et métriques réseau.",
- parameters: [
- { name: "codein", in: "path", required: true, schema: { type: "string" }, description: "Identifiant interne de l'article." },
- { name: "fournisseur", in: "query", schema: { type: "string" }, description: "Lève l'ambiguïté d'un article référencé chez plusieurs fournisseurs." },
- ],
- responses: {
- "200": {
- description: "Fiche produit",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: { data: { $ref: "#/components/schemas/Product" }, meta: { type: "object" } },
- },
- },
- },
- },
- "404": { description: "Produit absent de l'instantané", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- "401": { description: "Clé d'API absente, invalide ou révoquée", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- },
- },
- },
- "/products/{codein}/gamme": {
- put: {
- operationId: "changerGammeProduit",
- summary: "Proposer la gamme d'un produit (à valider)",
- description:
- "Propose une gamme pour un article. Elle reste à valider dans la Grille, où elle apparaît "
- + "comme une modification non enregistrée. Valeurs : " + legendeGammes + ". "
- + "`fournisseur` n'est requis que si l'article est référencé chez plusieurs fournisseurs "
- + "(réponse 400 listant les fournisseurs) ou s'il n'a encore jamais été calculé. "
- + "Pour plusieurs articles d'un même fournisseur, préférer changerGammes.",
- parameters: [
- { name: "codein", in: "path", required: true, schema: { type: "string" }, description: "Identifiant interne de l'article." },
- ],
- requestBody: {
- required: true,
- content: {
- "application/json": {
- schema: {
- type: "object",
- required: ["gamme"],
- properties: {
- gamme: { type: "string", enum: codesGamme },
- fournisseur: { type: "string", description: "Code fournisseur de l'article." },
- compute: { type: "boolean", default: true, description: "Calcule le fournisseur à la demande s'il n'a jamais été calculé." },
- },
- },
- },
- },
- },
- responses: {
- "200": {
- description: "Gamme proposée, à valider",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: {
- data: {
- allOf: [
- { $ref: "#/components/schemas/ResultatGamme" },
- { type: "object", properties: { codeFournisseur: { type: "string" }, nomFournisseur: { type: ["string", "null"] } } },
- ],
- },
- meta: { type: "object" },
- },
- },
- },
- },
- },
- "400": erreur("Gamme invalide, ou article chez plusieurs fournisseurs sans « fournisseur »"),
- "401": erreur("Clé d'API absente, invalide ou révoquée"),
- "404": erreur("Article introuvable chez ce fournisseur"),
- },
- },
- },
- "/gammes": {
- post: {
- operationId: "changerGammes",
- summary: "Proposer la gamme de plusieurs produits (à valider)",
- description:
- "Propose en un appel les gammes de plusieurs articles d'un même fournisseur, à valider "
- + "dans la Grille. Tout ou rien : si un article est inconnu chez le fournisseur, rien n'est proposé "
- + "et la réponse 404 liste les articles en cause dans `error.details.inconnus`. "
- + "Valeurs : " + legendeGammes + ".",
- requestBody: {
- required: true,
- content: {
- "application/json": {
- schema: {
- type: "object",
- required: ["fournisseur", "changes"],
- properties: {
- fournisseur: { type: "string", description: "Code fournisseur." },
- changes: {
- type: "array",
- minItems: 1,
- maxItems: 10000,
- items: {
- type: "object",
- required: ["codein", "gamme"],
- properties: {
- codein: { type: "string" },
- gamme: { type: "string", enum: codesGamme },
- },
- },
- },
- compute: { type: "boolean", default: true, description: "Calcule le fournisseur à la demande s'il n'a jamais été calculé." },
- },
- },
- },
- },
- },
- responses: {
- "200": {
- description: "Gammes proposées, à valider",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: {
- data: { type: "array", items: { $ref: "#/components/schemas/ResultatGamme" } },
- meta: { type: "object" },
- },
- },
- },
- },
- },
- "400": erreur("Corps de requête invalide"),
- "401": erreur("Clé d'API absente, invalide ou révoquée"),
- "404": erreur("Un ou plusieurs articles introuvables chez ce fournisseur"),
- },
- },
- },
- "/network/{codeCentrale}": {
- get: {
- operationId: "obtenirMetriquesReseau",
- summary: "Métriques du réseau Qlik pour un produit",
- description: "Performances du produit sur l'ensemble du réseau Foir'Fouille (~270 magasins) et courbe des quantités sur 12 mois glissants.",
- parameters: [
- { name: "codeCentrale", in: "path", required: true, schema: { type: "string" }, description: "Code centrale du produit (format 10000XXXXXX)." },
- ],
- responses: {
- "200": {
- description: "Métriques réseau",
- content: {
- "application/json": {
- schema: {
- type: "object",
- properties: { data: { $ref: "#/components/schemas/NetworkMetrics" }, meta: { type: "object" } },
- },
- },
- },
- },
- "404": { description: "Aucune donnée réseau pour ce code centrale", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- "401": { description: "Clé d'API absente, invalide ou révoquée", content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } },
- },
- },
- },
- },
- };
-
- // CORS ouvert en lecture : le schéma est public et peut être chargé par un outil tiers.
- return Response.json(spec, { headers: { "Access-Control-Allow-Origin": "*" } });
-}
diff --git a/src/app/api/v1/products/[codein]/gamme/route.ts b/src/app/api/v1/products/[codein]/gamme/route.ts
deleted file mode 100644
index 926ffc3..0000000
--- a/src/app/api/v1/products/[codein]/gamme/route.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail } from "@/lib/api-response";
-import { productGammeBodySchema } from "@/lib/api-schemas";
-import { listGridSuppliersForCodein } from "@/lib/grid-store";
-import { affecterGammes, lireCorpsJson } from "@/lib/api-gammes";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-// Idem /api/v1/grid : le calcul à la demande peut prendre plusieurs secondes.
-export const maxDuration = 300;
-
-/**
- * PUT /api/v1/products/:codein/gamme { "gamme": "A", "fournisseur"?: "…" }
- *
- * Propose une gamme pour un article. La proposition reste **à valider** : elle
- * apparaît dans la Grille comme une modification non enregistrée, et `codeGamme`
- * ne change qu'une fois validée (« Enregistrer » dans la Grille).
- *
- * `fournisseur` n'est requis que si l'article est référencé chez plusieurs
- * fournisseurs, ou s'il n'apparaît pas encore dans l'instantané.
- */
-export async function PUT(
- req: NextRequest,
- ctx: { params: Promise<{ codein: string }> },
-) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const { codein } = await ctx.params;
- if (!codein) return fail("bad_request", "Paramètre 'codein' requis.");
-
- const corps = await lireCorpsJson(req);
- if (corps instanceof Response) return corps;
- const parsed = productGammeBodySchema.safeParse(corps);
- if (!parsed.success) {
- return fail("bad_request", "Corps de requête invalide.", parsed.error.issues);
- }
- const { gamme, compute } = parsed.data;
-
- let fournisseur = parsed.data.fournisseur;
- if (!fournisseur) {
- const fournisseurs = await listGridSuppliersForCodein(codein);
- if (fournisseurs.length === 0) {
- return fail(
- "not_found",
- `Aucun instantané pour le produit « ${codein} ». Ajoutez « fournisseur » au corps de la requête pour que l'API calcule le lot à la demande.`,
- );
- }
- if (fournisseurs.length > 1) {
- return fail(
- "bad_request",
- `Le produit « ${codein} » est référencé chez plusieurs fournisseurs : précisez « fournisseur ».`,
- { fournisseurs },
- );
- }
- fournisseur = fournisseurs[0].codeFournisseur;
- }
-
- const res = await affecterGammes({
- codeFournisseur: fournisseur,
- changes: [{ codein, gamme }],
- compute,
- auteur: authCtx.subject,
- });
- if (res instanceof Response) return res;
-
- return ok(
- { ...res.resultats[0], codeFournisseur: res.codeFournisseur, nomFournisseur: res.nomFournisseur },
- { meta: { enregistreLe: new Date().toISOString() } },
- );
-}
diff --git a/src/app/api/v1/products/[codein]/route.ts b/src/app/api/v1/products/[codein]/route.ts
deleted file mode 100644
index d52cb5f..0000000
--- a/src/app/api/v1/products/[codein]/route.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail } from "@/lib/api-response";
-import { productDetailSchema } from "@/lib/api-schemas";
-import { getGridRowByCodein } from "@/lib/grid-store";
-import { enrichRows } from "@/lib/api-enrich";
-import { getProductRows } from "@/features/grid/api/get-product-rows";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-// Idem /api/v1/grid : le calcul à la demande peut prendre plusieurs secondes.
-export const maxDuration = 300;
-
-/**
- * GET /api/v1/products/:codein?fournisseur=…
- *
- * Fiche complète d'un produit : le `ProductRow` intégral (séries mensuelles,
- * ventilations par magasin, stock, marges, gammes) enrichi des métriques réseau Qlik
- * lues **en cache** (`qlik_network_metrics`) — aucun appel à Qlik.
- *
- * `fournisseur` lève l'ambiguïté d'un article référencé chez plusieurs fournisseurs ;
- * sans lui, l'instantané le plus récent est renvoyé.
- */
-export async function GET(
- req: NextRequest,
- ctx: { params: Promise<{ codein: string }> },
-) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const { codein } = await ctx.params;
- if (!codein) return fail("bad_request", "Paramètre 'codein' requis.");
-
- const parsed = productDetailSchema.safeParse(Object.fromEntries(req.nextUrl.searchParams));
- if (!parsed.success) {
- return fail("bad_request", "Paramètres invalides.", parsed.error.issues);
- }
-
- let found = await getGridRowByCodein(codein, parsed.data.fournisseur);
-
- // Absent de l'instantané : on peut le calculer, mais seulement si l'appelant a
- // précisé le fournisseur — le calcul se fait par lot fournisseur, pas par article.
- if (!found && parsed.data.compute === "1" && parsed.data.fournisseur) {
- console.log(`[api/v1/products] ${codein} absent — calcul du lot ${parsed.data.fournisseur} à la demande`);
- try {
- await getProductRows({ codeFournisseur: parsed.data.fournisseur, magasin: "TOTAL" });
- found = await getGridRowByCodein(codein, parsed.data.fournisseur);
- } catch (e) {
- console.error(`[api/v1/products] calcul KO pour ${parsed.data.fournisseur}:`, e instanceof Error ? e.message : String(e));
- }
- }
-
- if (!found) {
- return fail(
- "not_found",
- parsed.data.fournisseur
- ? `Produit « ${codein} » introuvable chez le fournisseur « ${parsed.data.fournisseur} ».`
- : `Aucun instantané pour le produit « ${codein} ». Ajoutez « fournisseur=… » pour que l'API calcule le lot à la demande.`,
- );
- }
-
- // Métriques réseau + gamme serveur relues maintenant : le payload date du dernier
- // calcul de la grille, alors que ces deux données évoluent indépendamment.
- const [enriched] = await enrichRows([found.row]);
-
- return ok(enriched, {
- meta: {
- computedAt: found.computedAt,
- networkFetchedAt: enriched.network?.fetchedAt ?? null,
- hasNetwork: enriched.network !== null,
- },
- });
-}
diff --git a/src/app/api/v1/products/search/route.ts b/src/app/api/v1/products/search/route.ts
deleted file mode 100644
index 352a5f8..0000000
--- a/src/app/api/v1/products/search/route.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { NextRequest } from "next/server";
-import { requireApiAuth } from "@/lib/api-auth";
-import { ok, fail, buildPagination } from "@/lib/api-response";
-import { productSearchSchema, pickFields, toSortKey } from "@/lib/api-schemas";
-import { queryGridRows } from "@/lib/grid-store";
-import { enrichRows } from "@/lib/api-enrich";
-
-export const runtime = "nodejs";
-export const dynamic = "force-dynamic";
-
-/**
- * GET /api/v1/products/search?q=…&fournisseur=&gamme=&sort=&order=&page=&limit=&fields=
- *
- * **Recherche transversale** sur libellé, codein, GTIN, référence et code centrale —
- * tous fournisseurs confondus. C'est ce qu'aucune route existante ne sait faire :
- * `getProductRows()` exige un fournisseur, donc chercher un produit sans le connaître
- * était impossible.
- *
- * Lit uniquement l'instantané `grid_rows` : un fournisseur jamais ouvert dans la
- * Grille n'apparaît pas encore dans les résultats.
- */
-export async function GET(req: NextRequest) {
- const authCtx = await requireApiAuth(req);
- if (authCtx instanceof Response) return authCtx;
-
- const parsed = productSearchSchema.safeParse(Object.fromEntries(req.nextUrl.searchParams));
- if (!parsed.success) {
- return fail("bad_request", "Paramètres invalides.", parsed.error.issues);
- }
- const q = parsed.data;
-
- const result = await queryGridRows({
- codeFournisseur: q.fournisseur,
- gamme: q.gamme,
- search: q.q,
- sort: toSortKey(q.sort),
- order: q.order,
- page: q.page,
- limit: q.limit,
- });
-
- // Métriques Qlik et gamme serveur relues au moment de l'appel (voir api-enrich).
- const rows = q.enrich === "1" ? await enrichRows(result.rows) : result.rows;
-
- return ok(
- rows.map((r) => pickFields(r, q.fields)),
- {
- pagination: buildPagination(q.page, q.limit, result.total),
- meta: {
- query: q.q,
- computedAt: result.computedAt,
- scope: q.fournisseur ? `fournisseur:${q.fournisseur}` : "tous fournisseurs",
- enrichi: q.enrich === "1",
- },
- },
- );
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
deleted file mode 100644
index adec33a..0000000
--- a/src/app/layout.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import type { Metadata } from "next";
-import "./globals.css";
-import { Providers } from "./providers";
-
-export const metadata: Metadata = {
- title: { default: "CollectFlow", template: "%s · CollectFlow" },
- description: "Révision d'assortiment et suivi des ventes des magasins",
-};
-
-export default function RootLayout({
- children,
-}: Readonly<{
- children: React.ReactNode;
-}>) {
- return (
-
-
- {/* Inter chargé côté navigateur (et non au build) pour éviter toute
- dépendance réseau à Google Fonts pendant `next build` (Docker). */}
-
-
- {/* eslint-disable-next-line @next/next/no-page-custom-font */}
-
-
-
-
- {children}
-
-
-
- );
-}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 9ef1235..89ea8fd 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,5 +1,5 @@
-import { redirect } from "next/navigation";
+import { Navigate } from "react-router";
export default function HomePage() {
- redirect("/dashboard");
+ return ;
}
diff --git a/src/app/providers.tsx b/src/app/providers.tsx
index 74e9a73..2959cfc 100644
--- a/src/app/providers.tsx
+++ b/src/app/providers.tsx
@@ -1,21 +1,24 @@
-"use client";
-
import { SessionProvider } from "next-auth/react";
import { ThemeProvider } from "@/components/shared/theme-provider";
import { TooltipProvider } from "@/components/ui/tooltip";
import { FeedbackHost } from "@/components/ui/feedback";
+import { RefreshProvider } from "@/lib/page-data";
export function Providers({ children }: { children: React.ReactNode }) {
return (
- // La session n'est pas relue à chaque retour sur l'onglet : elle repartait
- // sur le réseau et redessinait toute la page (Grille comprise) à chaque fois.
-
-
-
- {children}
-
-
-
-
+ // Compteur de rafraîchissement (`router.refresh()`) : relu par les données
+ // des pages et par la session.
+
+ {/* La session n'est pas relue à chaque retour sur l'onglet : elle repartait
+ sur le réseau et redessinait toute la page (Grille comprise) à chaque fois. */}
+
+
+
+ {children}
+
+
+
+
+
);
}
diff --git a/src/components/shared/admin-only.tsx b/src/components/shared/admin-only.tsx
new file mode 100644
index 0000000..463a0a1
--- /dev/null
+++ b/src/components/shared/admin-only.tsx
@@ -0,0 +1,14 @@
+import type { ReactNode } from "react";
+import { Navigate } from "react-router";
+import { useSessionResolue } from "next-auth/react";
+
+/**
+ * Pages réservées aux administrateurs : le serveur filtre déjà l'accès direct
+ * (rôle relu en base) ; ici, la même règle pour une navigation dans
+ * l'application — retour à l'accueil sinon.
+ */
+export function AdminOnly({ children }: { children: ReactNode }) {
+ const session = useSessionResolue();
+ if (session?.user.role !== "admin") return ;
+ return <>{children}>;
+}
diff --git a/src/components/shared/header.tsx b/src/components/shared/header.tsx
index 3a9bc0d..c591376 100644
--- a/src/components/shared/header.tsx
+++ b/src/components/shared/header.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { ChevronDown, LogOut, Moon, Rows3, Sun, User as UserIcon } from "lucide-react";
import { usePathname } from "next/navigation";
import { useTheme } from "next-themes";
diff --git a/src/components/shared/route-error-boundary.tsx b/src/components/shared/route-error-boundary.tsx
new file mode 100644
index 0000000..4810cb5
--- /dev/null
+++ b/src/components/shared/route-error-boundary.tsx
@@ -0,0 +1,42 @@
+import { Component, type ErrorInfo, type ReactNode } from "react";
+import { refreshPage } from "@/lib/page-data";
+
+interface Props {
+ /** Rendu à la place de la page en erreur ; `reset` relance son chargement. */
+ fallback: (error: Error, reset: () => void) => ReactNode;
+ children: ReactNode;
+}
+
+interface State {
+ error: Error | null;
+}
+
+/**
+ * Frontière d'erreur d'une page (équivalent de `error.tsx`) : le menu et
+ * l'en-tête restent utilisables. Elle est remontée à chaque changement de page
+ * (clé posée par le routeur), comme celle de Next.js.
+ */
+export class RouteErrorBoundary extends Component {
+ state: State = { error: null };
+
+ static getDerivedStateFromError(error: unknown): State {
+ return { error: error instanceof Error ? error : new Error(String(error)) };
+ }
+
+ componentDidCatch(error: Error, info: ErrorInfo): void {
+ void error;
+ void info;
+ }
+
+ private reset = () => {
+ // Nouvelle clé de données (sans transition : la silhouette s'affiche),
+ // puis nouvel essai de rendu de la page.
+ refreshPage({ transition: false });
+ this.setState({ error: null });
+ };
+
+ render(): ReactNode {
+ if (this.state.error) return this.props.fallback(this.state.error, this.reset);
+ return this.props.children;
+ }
+}
diff --git a/src/components/shared/sidebar.tsx b/src/components/shared/sidebar.tsx
index c355d18..0e068db 100644
--- a/src/components/shared/sidebar.tsx
+++ b/src/components/shared/sidebar.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { ChevronLeft, ChevronRight, Package } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
diff --git a/src/components/shared/theme-provider.tsx b/src/components/shared/theme-provider.tsx
index b7556ec..4d51e2f 100644
--- a/src/components/shared/theme-provider.tsx
+++ b/src/components/shared/theme-provider.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { ThemeProvider as NextThemesProvider } from "next-themes";
export function ThemeProvider({ children }: { children: React.ReactNode }) {
diff --git a/src/components/ui/data-table.tsx b/src/components/ui/data-table.tsx
index b12a722..9aea8bb 100644
--- a/src/components/ui/data-table.tsx
+++ b/src/components/ui/data-table.tsx
@@ -1,5 +1,3 @@
-"use client";
-
/**
* Tableau de données commun : recherche, filtres, tri par colonne, pagination,
* export, état vide et ligne de totaux — identiques sur toutes les pages.
diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx
index bf9459c..42c9ea8 100644
--- a/src/components/ui/dialog.tsx
+++ b/src/components/ui/dialog.tsx
@@ -1,5 +1,3 @@
-"use client"
-
import * as React from "react"
import { XIcon } from "lucide-react"
import { Dialog as DialogPrimitive } from "radix-ui"
diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx
index 1c9880c..ecc78c4 100644
--- a/src/components/ui/dropdown-menu.tsx
+++ b/src/components/ui/dropdown-menu.tsx
@@ -1,5 +1,3 @@
-"use client"
-
import * as React from "react"
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
diff --git a/src/components/ui/feedback.tsx b/src/components/ui/feedback.tsx
index 43214f0..b20b49d 100644
--- a/src/components/ui/feedback.tsx
+++ b/src/components/ui/feedback.tsx
@@ -1,5 +1,3 @@
-"use client";
-
/**
* Retours à l'utilisateur, communs à toute l'application :
* - `toast.succes / toast.erreur / toast.info` : message discret en bas à droite,
diff --git a/src/components/ui/form-controls.tsx b/src/components/ui/form-controls.tsx
index 8e9b6f8..eddc738 100644
--- a/src/components/ui/form-controls.tsx
+++ b/src/components/ui/form-controls.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import type { InputHTMLAttributes, ReactNode, SelectHTMLAttributes } from "react";
import { Search, X } from "lucide-react";
import { cn } from "@/lib/utils";
diff --git a/src/components/ui/pagination.tsx b/src/components/ui/pagination.tsx
index 9ed0b15..ea471a7 100644
--- a/src/components/ui/pagination.tsx
+++ b/src/components/ui/pagination.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react";
interface PaginationProps {
diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx
index a74d3b3..efdcac2 100644
--- a/src/components/ui/tabs.tsx
+++ b/src/components/ui/tabs.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useState, type ReactNode } from "react";
import type { LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
diff --git a/src/components/ui/tooltip.tsx b/src/components/ui/tooltip.tsx
index a0f0a77..c2e5395 100644
--- a/src/components/ui/tooltip.tsx
+++ b/src/components/ui/tooltip.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import type { ReactNode } from "react";
import { Tooltip as TooltipPrimitive } from "radix-ui";
import { Info } from "lucide-react";
diff --git a/src/db/index.ts b/src/db/index.ts
deleted file mode 100644
index a72a93a..0000000
--- a/src/db/index.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-import { drizzle, NodePgDatabase } from "drizzle-orm/node-postgres";
-import { Pool } from "pg";
-import * as schema from "./schema";
-import fs from "fs";
-import path from "path";
-
-/**
- * Pool unique par processus, rangé dans `globalThis` : l'instrumentation (synchro
- * nocturne) et les routes peuvent être compilées dans des lots distincts, chacun
- * avec sa propre copie de ce module — et donc son propre pool de 20 connexions.
- * Même chose à chaque rechargement à chaud en développement.
- */
-type DbState = { pool: Pool | null; db: NodePgDatabase | null };
-const globalForDb = globalThis as typeof globalThis & { __collectflowDb?: DbState };
-const state: DbState = (globalForDb.__collectflowDb ??= { pool: null, db: null });
-
-export function getPool(): Pool {
- getDb(); // ensure pool is initialized
- return state.pool!;
-}
-
-function maskUrl(url: string | undefined) {
- if (!url) return "undefined";
- return url.replace(/:([^@]+)@/, ":****@");
-}
-
-/**
- * Initializes or returns the current database instance.
- */
-export function getDb() {
- if (state.db) return state.db;
-
- let connectionString = "";
-
- try {
- const CONFIG_PATH = path.join(process.cwd(), "data", ".db-config.json");
- if (fs.existsSync(CONFIG_PATH)) {
- console.log("[DB] Found config file at:", CONFIG_PATH);
- const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
- if (config.url) {
- connectionString = config.url;
- console.log("[DB] Loaded saved database URL from config.");
- }
- }
- } catch (err) {
- console.error("[DB] Error reading config file:", err);
- }
-
- // Use environment variable as fallback if no config is found
- if (!connectionString && process.env.DATABASE_URL) {
- connectionString = process.env.DATABASE_URL;
- console.log("[DB] Using environment variable as fallback.");
- }
-
- console.log("[DB] Initializing connection with:", maskUrl(connectionString));
-
- if (!connectionString) {
- console.error("[DB] CRITICAL: No database connection string available!");
- }
-
- const connectionHostname = connectionString.match(/@([^:/]+)/)?.[1] || "unknown";
- console.log(`[DB] Target Hostname: ${connectionHostname}`);
-
- // Délai maximal par requête : opt-in (les calculs nocturnes des plus gros
- // fournisseurs peuvent être longs), pour qu'une requête emballée ne monopolise
- // pas indéfiniment une des 20 connexions.
- const statementTimeout = Number(process.env.PG_STATEMENT_TIMEOUT_MS) || undefined;
-
- const pool = new Pool({
- connectionString,
- max: 20,
- idleTimeoutMillis: 30000,
- connectionTimeoutMillis: 10000,
- application_name: "collectflow",
- ...(statementTimeout ? { statement_timeout: statementTimeout } : {}),
- });
-
- pool.on('error', (err) => {
- console.error('[DB] Unexpected error on idle client', err);
- });
-
- // Pas de workers parallèles PostgreSQL : ils consomment /dev/shm, trop petit
- // dans le conteneur, et font échouer les grosses agrégations. Réglé une fois
- // par connexion (la requête est mise en file avant toute autre sur ce client)
- // au lieu d'une transaction BEGIN / SET LOCAL / COMMIT autour de chaque requête.
- pool.on('connect', (client) => {
- client.query("SET max_parallel_workers_per_gather = 0").catch((err) => {
- console.error('[DB] SET max_parallel_workers_per_gather failed:', err?.message);
- });
- });
-
- state.pool = pool;
- state.db = drizzle(pool, { schema });
- return state.db;
-}
-
-/**
- * Resets the current database connection.
- * Called when settings are updated via the UI.
- */
-export function refreshDb() {
- console.log("[DB] Refreshing database connection...");
- if (state.pool) {
- state.pool.end().catch(err => console.error("[DB] Error closing pool:", err));
- state.pool = null;
- }
- state.db = null;
-}
-
-/**
- * Proxy for the 'db' instance.
- * Allows existing imports (import { db } from "@/db") to work
- * while the underlying instance can be hot-swapped.
- */
-export const db = new Proxy({} as NodePgDatabase, {
- get(target, prop, receiver) {
- const d = getDb();
- return Reflect.get(d, prop, receiver);
- }
-});
diff --git a/src/db/schema.ts b/src/db/schema.ts
deleted file mode 100644
index a480879..0000000
--- a/src/db/schema.ts
+++ /dev/null
@@ -1,308 +0,0 @@
-import { pgTable, serial, varchar, numeric, smallint, timestamp, uniqueIndex, index, text, jsonb, integer, boolean, primaryKey } from "drizzle-orm/pg-core";
-
-export const ventesProduits = pgTable("ventes_produits", {
- id: serial("id").primaryKey(),
-
- // Identification produit
- codein: varchar("codein", { length: 20 }).notNull(),
- codeFournisseur: varchar("code_fournisseur", { length: 20 }),
- nomFournisseur: varchar("nom_fournisseur", { length: 255 }),
- libelle1: varchar("libelle1", { length: 500 }),
- gtin: varchar("gtin", { length: 30 }),
- reference: varchar("reference", { length: 100 }),
- colisage: numeric("colisage", { precision: 10, scale: 5 }),
-
- // Gamme & Nomenclature
- codeGamme: varchar("code_gamme", { length: 20 }),
- codeGammeInit: varchar("code_gamme_init", { length: 20 }),
- code3: varchar("code3", { length: 20 }),
- libelle3: varchar("libelle3", { length: 500 }),
-
- // Dimension magasin & période
- magasin: varchar("magasin", { length: 20 }).notNull(),
- codeMagasin: varchar("code_magasin", { length: 10 }),
- annee: smallint("annee"),
- mois: smallint("mois"),
- periode: varchar("periode", { length: 10 }).notNull(),
-
- // Métriques
- quantite: numeric("quantite", { precision: 12, scale: 2 }),
- montantMvt: numeric("montant_mvt", { precision: 14, scale: 4 }),
- margeMvt: numeric("marge_mvt", { precision: 14, scale: 4 }),
-
- // Métadonnées
- importedAt: timestamp("imported_at").defaultNow(),
- updatedAt: timestamp("updated_at").defaultNow(),
-}, (table) => {
- return [
- uniqueIndex("uq_ventes_produit_magasin_periode").on(table.codein, table.magasin, table.periode),
- index("idx_ventes_codein").on(table.codein),
- index("idx_ventes_fournisseur").on(table.codeFournisseur),
- index("idx_ventes_gamme").on(table.codeGamme),
- index("idx_ventes_code3").on(table.code3),
- index("idx_ventes_magasin").on(table.magasin),
- index("idx_ventes_periode").on(table.periode),
- index("idx_ventes_annee_mois").on(table.annee, table.mois),
- index("idx_ventes_updated_at").on(table.updatedAt),
- ];
-});
-
-/** User management (Epic 6) */
-export const users = pgTable("users", {
- id: serial("id").primaryKey(),
- username: varchar("username", { length: 50 }).notNull().unique(),
- /** Hashed password */
- passwordHash: text("password_hash").notNull(),
- /** 'admin' or 'user' */
- role: varchar("role", { length: 20 }).default("user").notNull(),
- createdAt: timestamp("created_at").defaultNow(),
-});
-
-/** Snapshot of a complete arbitrage session (Epic 5) */
-export const sessionSnapshots = pgTable("session_snapshots", {
- id: serial("id").primaryKey(),
- /** Link to user who created the snapshot */
- userId: integer("user_id").references(() => users.id),
- codeFournisseur: varchar("code_fournisseur", { length: 20 }).notNull(),
- nomFournisseur: varchar("nom_fournisseur", { length: 255 }),
- magasin: varchar("magasin", { length: 20 }).notNull(),
- /** JSON map of codein → { before: GammeCode, after: GammeCode } */
- changes: jsonb("changes").notNull(),
- /** Summary stats at time of snapshot */
- summaryJson: jsonb("summary_json"),
- /** Label for the snapshot */
- label: text("label"),
- /** snapshot vs export */
- type: varchar("type", { length: 20 }).default("snapshot"),
- createdAt: timestamp("created_at").defaultNow(),
-}, (table) => [
- // Créés par scripts/db-init.js (la migration réellement jouée au démarrage).
- index("idx_snapshots_fournisseur_date").on(table.codeFournisseur, table.createdAt.desc()),
- index("idx_snapshots_user_type_date").on(table.userId, table.type, table.createdAt.desc()),
-]);
-
-/**
- * Cadencier / alertes de commande par fournisseur ET par magasin.
- * Un fournisseur peut être cadencé indépendamment sur chaque site (292/579)
- * avec un intervalle propre (toutes les X semaines). L'échéance est calculée
- * à partir de la dernière commande réelle (FF Nancy) + intervalle.
- */
-export const commandeCadences = pgTable("commande_cadences", {
- id: serial("id").primaryKey(),
- /** Code fournisseur (fouident.code) */
- codeFournisseur: varchar("code_fournisseur", { length: 20 }).notNull(),
- /** Nom fournisseur dénormalisé pour l'affichage */
- nomFournisseur: varchar("nom_fournisseur", { length: 255 }),
- /** Site / magasin : "292" | "579" */
- site: varchar("site", { length: 20 }).notNull(),
- /** Fréquence de commande, en semaines */
- intervalleSemaines: integer("intervalle_semaines").notNull(),
- /** Cadence active ou non */
- actif: boolean("actif").default(true).notNull(),
- createdAt: timestamp("created_at").defaultNow(),
- updatedAt: timestamp("updated_at").defaultNow(),
-}, (table) => {
- return [
- uniqueIndex("uq_cadence_fou_site").on(table.codeFournisseur, table.site),
- index("idx_cadence_site").on(table.site),
- ];
-});
-
-/**
- * Cache des métriques réseau Qlik Sense (~270 magasins La Foir'Fouille).
- * Clé = code centrale (format 10000XXXXXX). Rafraîchi par /api/qlik/sync.
- */
-export const qlikNetworkMetrics = pgTable("qlik_network_metrics", {
- /** Code centrale article (clé jointure Qlik ↔ FF) */
- codeCentrale: varchar("code_centrale", { length: 20 }).primaryKey(),
- /** CA réseau total du produit */
- caReseau: numeric("ca_reseau", { precision: 16, scale: 2 }),
- /** Quantité vendue réseau */
- qteReseau: numeric("qte_reseau", { precision: 14, scale: 2 }),
- /** Nombre de magasins travaillant le produit (sur ~270) */
- nbMagasinsReseau: integer("nb_magasins_reseau"),
- /** CA moyen par magasin (productivité normalisée présence) */
- caParMagasinReseau: numeric("ca_par_magasin_reseau", { precision: 16, scale: 2 }),
- /** Taux de marge réseau (ratio brut Qlik) */
- margePctReseau: numeric("marge_pct_reseau", { precision: 8, scale: 4 }),
- /** Période couverte (libre, ex "12m" ou "2025") */
- periode: varchar("periode", { length: 20 }),
- /** Quantité vendue réseau par mois : { "YYYY-MM": qté } (12 derniers mois). */
- qteByMonth: jsonb("qte_by_month"),
- /**
- * Détail mensuel complet : { "YYYY-MM": { qte, ca, nbMag, caMag, margePct } }.
- * Superset de `qteByMonth`, qui reste maintenu tel quel pour la colonne
- * « Tendance / Réseau » de la Grille.
- */
- metricsByMonth: jsonb("metrics_by_month"),
- /**
- * Libellé de l'article tel que Qlik le renvoie. Renseigné par la recherche
- * produit (qui interroge la dimension libellé) ; la sync fournisseur ne
- * l'écrase pas. Permet d'afficher une fiche pour un produit réseau que le
- * catalogue Nancy ne référence pas.
- */
- libelleReseau: varchar("libelle_reseau", { length: 255 }),
- /** Fournisseur de l'article côté Qlik, même origine que `libelleReseau`. */
- fournisseurReseau: varchar("fournisseur_reseau", { length: 255 }),
- /** Dernière synchro depuis Qlik */
- fetchedAt: timestamp("fetched_at").defaultNow(),
-});
-
-/**
- * Instantané persisté des lignes de grille (une ligne par fournisseur × article).
- *
- * Raison d'être : `getProductRows()` reconstruit la grille en direct et ne la garde
- * qu'en mémoire 10 minutes — perdu à chaque redémarrage. L'API `/api/v1` ne doit
- * jamais déclencher ce calcul, elle lit donc cette table, remplie en effet de bord
- * quand quelqu'un ouvre la Grille. Aucun calcul supplémentaire n'est introduit : on
- * arrête simplement de jeter le résultat.
- *
- * Seul `magasin = TOTAL` est persisté : `payload` embarque déjà les ventilations par
- * magasin (sales12mByStore, caByStore…).
- */
-export const gridRows = pgTable("grid_rows", {
- codeFournisseur: varchar("code_fournisseur", { length: 20 }).notNull(),
- codein: varchar("codein", { length: 20 }).notNull(),
-
- // Colonnes scalaires : servent aux filtres, au tri et à la recherche en SQL.
- nomFournisseur: varchar("nom_fournisseur", { length: 255 }),
- libelle1: varchar("libelle1", { length: 500 }),
- gtin: varchar("gtin", { length: 30 }),
- reference: varchar("reference", { length: 100 }),
- codeCentrale: varchar("code_centrale", { length: 20 }),
- code1: varchar("code1", { length: 20 }),
- code2: varchar("code2", { length: 20 }),
- code3: varchar("code3", { length: 20 }),
- codeGamme: varchar("code_gamme", { length: 20 }),
- codeGammeInit: varchar("code_gamme_init", { length: 20 }),
- totalCa: numeric("total_ca", { precision: 16, scale: 2 }),
- totalQuantite: numeric("total_quantite", { precision: 14, scale: 2 }),
- totalMarge: numeric("total_marge", { precision: 16, scale: 2 }),
- tauxMarge: numeric("taux_marge", { precision: 8, scale: 4 }),
- stockActuel: numeric("stock_actuel", { precision: 14, scale: 2 }),
- caReseau: numeric("ca_reseau", { precision: 16, scale: 2 }),
- qteReseau: numeric("qte_reseau", { precision: 14, scale: 2 }),
- nbMagasinsReseau: integer("nb_magasins_reseau"),
- caParMagasinReseau: numeric("ca_par_magasin_reseau", { precision: 16, scale: 2 }),
- margePctReseau: numeric("marge_pct_reseau", { precision: 8, scale: 4 }),
-
- /** ProductRow complet (séries mensuelles, ventilations par magasin, dates…). */
- payload: jsonb("payload").notNull(),
- /** Date du calcul ayant produit cette ligne — expose la fraîcheur au consommateur. */
- computedAt: timestamp("computed_at").defaultNow().notNull(),
-}, (table) => {
- return [
- uniqueIndex("uq_grid_rows_fou_codein").on(table.codeFournisseur, table.codein),
- index("idx_grid_rows_fournisseur").on(table.codeFournisseur),
- index("idx_grid_rows_codein").on(table.codein),
- index("idx_grid_rows_gamme").on(table.codeGamme),
- index("idx_grid_rows_code_centrale").on(table.codeCentrale),
- index("idx_grid_rows_total_ca").on(table.totalCa),
- index("idx_grid_rows_libelle").on(table.libelle1),
- ];
-});
-
-/**
- * Clés d'API pour les appelants non-navigateur (scripts, outils externes).
- *
- * Seul le hachage SHA-256 est stocké : la clé en clair n'est affichée qu'une fois,
- * à la création. Une clé révoquée conserve sa ligne (traçabilité) via `revokedAt`.
- */
-export const apiKeys = pgTable("api_keys", {
- id: serial("id").primaryKey(),
- /** Nom lisible choisi à la création (ex "Export Excel comptabilité"). */
- name: varchar("name", { length: 100 }).notNull(),
- /** Préfixe en clair (ex "cf_a1b2c3") — sert à identifier la clé dans l'UI. */
- keyPrefix: varchar("key_prefix", { length: 20 }).notNull(),
- /** SHA-256 hexadécimal de la clé complète. */
- keyHash: text("key_hash").notNull().unique(),
- /** 'admin' ou 'user' — même sémantique que users.role. */
- role: varchar("role", { length: 20 }).default("user").notNull(),
- createdBy: varchar("created_by", { length: 50 }),
- createdAt: timestamp("created_at").defaultNow(),
- lastUsedAt: timestamp("last_used_at"),
- revokedAt: timestamp("revoked_at"),
-});
-
-/**
- * Paramétrage et suivi de la synchronisation nocturne, un enregistrement par
- * fournisseur.
- *
- * Deux sources aux coûts très différents, donc deux cadences distinctes :
- * l'instantané SQL prend une minute au pire, l'extraction Qlik jusqu'à huit —
- * et le serveur Qlik abandonne quand on le sollicite trop. D'où `actifSql` et
- * `actifQlik` séparés, et deux dates de dernier passage.
- *
- * L'ordre de passage se déduit de `dernier*At` (le plus ancien d'abord) : la
- * nuit suivante reprend donc naturellement là où la précédente s'est arrêtée,
- * et repart d'elle-même pour un nouveau tour quand tout a été traité. Aucun
- * curseur ni compteur de tour à maintenir.
- */
-export const syncFournisseurs = pgTable("sync_fournisseurs", {
- codeFournisseur: varchar("code_fournisseur", { length: 20 }).primaryKey(),
- nomFournisseur: varchar("nom_fournisseur", { length: 255 }),
- /** Inclus dans la rotation de l'instantané SQL. */
- actifSql: boolean("actif_sql").default(true).notNull(),
- /** Inclus dans la rotation Qlik (beaucoup plus coûteuse). */
- actifQlik: boolean("actif_qlik").default(true).notNull(),
- /**
- * Renseigné quand le planificateur a désactivé le fournisseur de lui-même —
- * typiquement « aucun article ». Évite de réessayer chaque nuit un
- * fournisseur vide, tout en gardant la raison visible pour le réactiver.
- */
- desactiveMotif: text("desactive_motif"),
-
- dernierSqlAt: timestamp("dernier_sql_at"),
- /** 'succes' | 'echec' | 'vide' */
- dernierSqlStatut: varchar("dernier_sql_statut", { length: 20 }),
- dernierSqlLignes: integer("dernier_sql_lignes"),
- dernierSqlErreur: text("dernier_sql_erreur"),
- dernierSqlMs: integer("dernier_sql_ms"),
-
- dernierQlikAt: timestamp("dernier_qlik_at"),
- dernierQlikStatut: varchar("dernier_qlik_statut", { length: 20 }),
- dernierQlikCodes: integer("dernier_qlik_codes"),
- dernierQlikErreur: text("dernier_qlik_erreur"),
- dernierQlikMs: integer("dernier_qlik_ms"),
-
- updatedAt: timestamp("updated_at").defaultNow(),
-}, (table) => {
- return [
- // Index de file d'attente : « le plus ancien d'abord », par source.
- index("idx_sync_fou_sql").on(table.actifSql, table.dernierSqlAt),
- index("idx_sync_fou_qlik").on(table.actifQlik, table.dernierQlikAt),
- ];
-});
-
-/** AI Context rules per supplier (Epic: AI Context) */
-export const aiSupplierContext = pgTable("ai_supplier_context", {
- /** Supplier code serving as the primary key */
- codeFournisseur: varchar("code_fournisseur", { length: 20 }).primaryKey(),
- /** The business rules text provided by the user */
- context: text("context").notNull(),
- /** When it was last updated */
- updatedAt: timestamp("updated_at").defaultNow(),
-});
-
-/**
- * Gammes proposées par l'API `/api/v1`, en attente de validation.
- *
- * L'API n'enregistre plus directement : chaque proposition attend ici qu'un
- * utilisateur l'examine dans la Grille, où elle apparaît comme une modification
- * non enregistrée. « Enregistrer » la valide (snapshot + `grid_rows`), « Annuler
- * les modifications » la rejette ; dans les deux cas la ligne est supprimée.
- * Une seule proposition par article et fournisseur : la dernière l'emporte.
- */
-export const gammesAValider = pgTable("gammes_a_valider", {
- codeFournisseur: varchar("code_fournisseur", { length: 20 }).notNull(),
- codein: varchar("codein", { length: 20 }).notNull(),
- /** Gamme proposée. */
- gamme: varchar("gamme", { length: 20 }).notNull(),
- /** Gamme enregistrée au moment de la proposition. */
- gammePrecedente: varchar("gamme_precedente", { length: 20 }),
- /** Nom de la clé d'API à l'origine de la proposition. */
- auteur: varchar("auteur", { length: 100 }),
- createdAt: timestamp("created_at").defaultNow().notNull(),
-}, (table) => [
- primaryKey({ columns: [table.codeFournisseur, table.codein] }),
-]);
diff --git a/src/features/admin/api/api-key-actions.ts b/src/features/admin/api/api-key-actions.ts
index 4277f26..5e068a4 100644
--- a/src/features/admin/api/api-key-actions.ts
+++ b/src/features/admin/api/api-key-actions.ts
@@ -1,19 +1,14 @@
-"use server";
-
/**
* CollectFlow — Gestion des clés de l'API `/api/v1` (administrateurs).
*
* La clé en clair n'existe qu'une fois : elle est renvoyée par `createApiKey()` et
* jamais restituée ensuite (seul son hachage SHA-256 est stocké). Une clé révoquée
* conserve sa ligne, pour garder la trace de son usage passé.
+ *
+ * Actions exécutées par le serveur Rust : `POST /api/actions/{nom}`.
*/
-import { db } from "@/db";
-import { apiKeys } from "@/db/schema";
-import { desc, eq } from "drizzle-orm";
-import { requireAdmin } from "@/lib/authz";
-import { generateApiKey } from "@/lib/api-auth";
-import { revalidatePath } from "next/cache";
+import { callAction } from "@/lib/rpc";
export interface ApiKeyRow {
id: number;
@@ -28,27 +23,7 @@ export interface ApiKeyRow {
/** Liste les clés. Ne renvoie jamais de secret — seulement le préfixe lisible. */
export async function getApiKeys(): Promise {
- await requireAdmin();
- const rows = await db
- .select({
- id: apiKeys.id,
- name: apiKeys.name,
- keyPrefix: apiKeys.keyPrefix,
- role: apiKeys.role,
- createdBy: apiKeys.createdBy,
- createdAt: apiKeys.createdAt,
- lastUsedAt: apiKeys.lastUsedAt,
- revokedAt: apiKeys.revokedAt,
- })
- .from(apiKeys)
- .orderBy(desc(apiKeys.createdAt));
-
- return rows.map((r) => ({
- ...r,
- createdAt: r.createdAt ? r.createdAt.toISOString() : null,
- lastUsedAt: r.lastUsedAt ? r.lastUsedAt.toISOString() : null,
- revokedAt: r.revokedAt ? r.revokedAt.toISOString() : null,
- }));
+ return callAction("getApiKeys", []);
}
/**
@@ -59,51 +34,15 @@ export async function createApiKey(
name: string,
role: "admin" | "user" = "user",
): Promise<{ success: true; key: string; keyPrefix: string } | { success: false; error: string }> {
- const moi = await requireAdmin();
-
- const trimmed = name.trim();
- if (!trimmed) return { success: false, error: "Le nom de la clé est obligatoire." };
- if (trimmed.length > 100) return { success: false, error: "Nom trop long (100 caractères max)." };
-
- try {
- const { key, keyHash, keyPrefix } = generateApiKey();
- await db.insert(apiKeys).values({
- name: trimmed,
- keyPrefix,
- keyHash,
- role,
- createdBy: moi.username || null,
- });
- revalidatePath("/settings");
- return { success: true, key, keyPrefix };
- } catch (err) {
- console.error("[api-keys] création KO:", err);
- return { success: false, error: "Erreur technique lors de la création de la clé." };
- }
+ return callAction("createApiKey", [name, role]);
}
/** Révoque une clé : elle est refusée dès l'appel suivant, mais reste listée. */
export async function revokeApiKey(id: number): Promise<{ success: boolean; error?: string }> {
- await requireAdmin();
- try {
- await db.update(apiKeys).set({ revokedAt: new Date() }).where(eq(apiKeys.id, id));
- revalidatePath("/settings");
- return { success: true };
- } catch (err) {
- console.error("[api-keys] révocation KO:", err);
- return { success: false, error: "Erreur lors de la révocation." };
- }
+ return callAction("revokeApiKey", [id]);
}
/** Supprime définitivement une clé révoquée (nettoyage de la liste). */
export async function deleteApiKey(id: number): Promise<{ success: boolean; error?: string }> {
- await requireAdmin();
- try {
- await db.delete(apiKeys).where(eq(apiKeys.id, id));
- revalidatePath("/settings");
- return { success: true };
- } catch (err) {
- console.error("[api-keys] suppression KO:", err);
- return { success: false, error: "Erreur lors de la suppression." };
- }
+ return callAction("deleteApiKey", [id]);
}
diff --git a/src/features/admin/api/sync-scheduler.ts b/src/features/admin/api/sync-scheduler.ts
deleted file mode 100644
index 7d80a44..0000000
--- a/src/features/admin/api/sync-scheduler.ts
+++ /dev/null
@@ -1,387 +0,0 @@
-/**
- * CollectFlow — Synchronisation nocturne des fournisseurs.
- *
- * Deux sources aux coûts très différents, donc deux files distinctes :
- * • **SQL** — l'instantané de grille (`getProductRows`), ~43 s sur le plus gros
- * fournisseur du catalogue. Alimente la Grille et `/api/v1`.
- * • **Qlik** — les métriques réseau, jusqu'à 8 min par fournisseur, sur un
- * serveur externe qui abandonne quand on le sollicite trop. Ce sont des
- * agrégats mensuels : les rafraîchir chaque nuit n'apporterait rien.
- *
- * ORDRE DE PASSAGE — le point de conception central. La file est simplement
- * « le plus ancien d'abord », en ignorant ceux déjà traités depuis l'ouverture
- * de la fenêtre courante. Il en découle, sans curseur ni compteur de tour :
- * • la nuit 2 reprend là où la nuit 1 s'est arrêtée (les non-traités sont les
- * plus anciens) ;
- * • quand plus personne n'est en attente, le tour est fini ; la nuit suivante
- * tout le monde redevient éligible et le tour recommence ;
- * • un fournisseur en échec garde une date ancienne, donc il repasse en tête —
- * le rattrapage est automatique.
- *
- * La fenêtre ne peut pas interrompre un fournisseur en cours : elle signifie
- * « ne plus en **démarrer** après l'heure de fin ».
- */
-
-import "server-only";
-
-import { and, asc, eq, isNull, lt, or, sql, type SQL } from "drizzle-orm";
-import { db } from "@/db";
-import { syncFournisseurs } from "@/db/schema";
-import { getProductRows } from "@/features/grid/api/get-product-rows";
-import { pgGetFournisseurs, pgGetArticlesByFournisseur } from "@/lib/pg-ff-client";
-import { fetchNetworkMetricsPlaywright } from "@/lib/qlik-playwright";
-import { upsertNetworkMetrics } from "@/lib/qlik-network-cache";
-import { buildGridNetworkQlikDateFilter, envMonthsBack, QLIK_MONTHS_BACK_DEFAULT } from "@/lib/qlik-date-range";
-import { readSyncSettings, type SyncSettings } from "@/features/admin/api/sync-settings";
-import { invalidateFFCache } from "@/lib/ff-cache";
-
-export type { SyncSettings };
-
-// ─── État courant, en mémoire ────────────────────────────────────────────────
-
-export interface SyncSchedulerState {
- enCours: boolean;
- /** "auto" = déclenché par la fenêtre nocturne, "manuel" = lancé depuis l'admin. */
- origine: "auto" | "manuel" | null;
- debutAt: string | null;
- finAt: string | null;
- fournisseurCourant: string | null;
- etape: "sql" | "qlik" | null;
- sqlFaits: number;
- sqlEchecs: number;
- qlikFaits: number;
- qlikEchecs: number;
- /** Renseigné quand la file s'est vidée : le tour est bouclé. */
- tourTermine: boolean;
- arretDemande: boolean;
- derniereErreur: string | null;
-}
-
-const etat: SyncSchedulerState = {
- enCours: false, origine: null, debutAt: null, finAt: null,
- fournisseurCourant: null, etape: null,
- sqlFaits: 0, sqlEchecs: 0, qlikFaits: 0, qlikEchecs: 0,
- tourTermine: false, arretDemande: false, derniereErreur: null,
-};
-
-export function getSyncSchedulerState(): SyncSchedulerState {
- return { ...etat };
-}
-
-export function demanderArret(): void {
- if (etat.enCours) etat.arretDemande = true;
-}
-
-// ─── Fenêtre horaire ─────────────────────────────────────────────────────────
-
-/**
- * Début de la fenêtre en cours, ou `null` si l'heure courante est en dehors.
- *
- * Gère le passage par minuit (ex. 22h → 5h) : dans ce cas, entre 0h et l'heure
- * de fin, la fenêtre a commencé **la veille**.
- */
-export function debutFenetre(s: SyncSettings, maintenant = new Date()): Date | null {
- const h = maintenant.getHours();
- const debutDuJour = new Date(maintenant);
- debutDuJour.setHours(s.heureDebut, 0, 0, 0);
-
- if (s.heureDebut < s.heureFin) {
- return h >= s.heureDebut && h < s.heureFin ? debutDuJour : null;
- }
- // Fenêtre à cheval sur minuit.
- if (h >= s.heureDebut) return debutDuJour;
- if (h < s.heureFin) {
- const veille = new Date(debutDuJour);
- veille.setDate(veille.getDate() - 1);
- return veille;
- }
- return null;
-}
-
-// ─── Référentiel des fournisseurs ────────────────────────────────────────────
-
-/**
- * Aligne la table de paramétrage sur le référentiel FF : ajoute les nouveaux
- * fournisseurs (actifs par défaut), rafraîchit les noms. Ne supprime rien —
- * l'historique de synchronisation d'un fournisseur disparu reste consultable.
- */
-export async function seedSyncFournisseurs(): Promise {
- const fournisseurs = await pgGetFournisseurs();
- if (fournisseurs.length === 0) return 0;
-
- const CHUNK = 500;
- for (let i = 0; i < fournisseurs.length; i += CHUNK) {
- const lot = fournisseurs.slice(i, i + CHUNK);
- await db
- .insert(syncFournisseurs)
- .values(lot.map((f) => ({ codeFournisseur: f.code, nomFournisseur: f.nom })))
- .onConflictDoUpdate({
- target: syncFournisseurs.codeFournisseur,
- // Seul le nom est réaligné : les choix d'activation appartiennent à l'admin.
- set: { nomFournisseur: sql`excluded.nom_fournisseur` },
- });
- }
- return fournisseurs.length;
-}
-
-// ─── Files d'attente ─────────────────────────────────────────────────────────
-
-/** Le plus ancien fournisseur SQL pas encore traité depuis l'ouverture de la fenêtre. */
-async function prochainSql(depuis: Date) {
- const [row] = await db
- .select()
- .from(syncFournisseurs)
- .where(and(
- eq(syncFournisseurs.actifSql, true),
- or(isNull(syncFournisseurs.dernierSqlAt), lt(syncFournisseurs.dernierSqlAt, depuis)) as SQL,
- ))
- .orderBy(asc(sql`${syncFournisseurs.dernierSqlAt} nulls first`))
- .limit(1);
- return row ?? null;
-}
-
-/** Délai avant de retenter un fournisseur Qlik en échec : la nuit suivante. */
-const QLIK_REPRISE_ECHEC_MS = 18 * 3600 * 1000;
-
-/**
- * Le plus ancien fournisseur Qlik à rafraîchir. Il l'est si :
- * - ses données dépassent `qlikMinJours` (agrégats mensuels : inutile de
- * relancer chaque nuit une extraction de plusieurs minutes) ;
- * - ou elles datent d'avant le mois en cours : la fenêtre de 12 mois a glissé,
- * son dernier mois manque, sa tendance n'est plus à jour ;
- * - ou sa dernière extraction a échoué il y a plus de 18 h. Un échec attendait
- * jusqu'ici `qlikMinJours` (7 jours) avant un nouvel essai, alors que la
- * plupart sont passagers (serveur Qlik chargé, dernier mois pas encore
- * chargé). Le plus ancien passant en premier, un fournisseur qui échoue à
- * chaque fois repart en fin de file et ne bloque personne.
- */
-async function prochainQlik(qlikMinJours: number, maintenant: Date) {
- const seuilAge = new Date(maintenant.getTime() - qlikMinJours * 24 * 3600 * 1000);
- const debutMois = new Date(maintenant.getFullYear(), maintenant.getMonth(), 1);
- const seuil = seuilAge > debutMois ? seuilAge : debutMois;
- const seuilEchec = new Date(maintenant.getTime() - QLIK_REPRISE_ECHEC_MS);
- const [row] = await db
- .select()
- .from(syncFournisseurs)
- .where(and(
- eq(syncFournisseurs.actifQlik, true),
- or(
- isNull(syncFournisseurs.dernierQlikAt),
- lt(syncFournisseurs.dernierQlikAt, seuil),
- and(eq(syncFournisseurs.dernierQlikStatut, "echec"), lt(syncFournisseurs.dernierQlikAt, seuilEchec)),
- ) as SQL,
- ))
- .orderBy(asc(sql`${syncFournisseurs.dernierQlikAt} nulls first`))
- .limit(1);
- return row ?? null;
-}
-
-// ─── Traitement d'un fournisseur ─────────────────────────────────────────────
-
-/**
- * Instantané SQL. `dernierSqlAt` est renseigné **même en cas d'échec** : sans
- * cela, un fournisseur qui échoue resterait éternellement le plus ancien et
- * bloquerait la file derrière lui.
- */
-async function traiterSql(code: string, nom: string | null): Promise {
- const t0 = Date.now();
- etat.fournisseurCourant = `${code}${nom ? ` — ${nom}` : ""}`;
- etat.etape = "sql";
- try {
- const rows = await getProductRows({ codeFournisseur: code, magasin: "TOTAL", forceRefresh: true });
- const vide = rows.length === 0;
- await db.update(syncFournisseurs).set({
- dernierSqlAt: new Date(),
- dernierSqlStatut: vide ? "vide" : "succes",
- dernierSqlLignes: rows.length,
- dernierSqlErreur: null,
- dernierSqlMs: Date.now() - t0,
- // Un fournisseur sans article n'a rien à donner : on le sort des deux
- // files plutôt que de le réessayer chaque nuit. L'admin voit le motif
- // et peut le réactiver.
- ...(vide ? { actifSql: false, actifQlik: false, desactiveMotif: "Aucun article — désactivé automatiquement" } : {}),
- updatedAt: new Date(),
- }).where(eq(syncFournisseurs.codeFournisseur, code));
- if (vide) console.log(`[sync-nuit] ${code} sans article — désactivé automatiquement`);
- else etat.sqlFaits++;
- } catch (e) {
- const msg = e instanceof Error ? e.message : String(e);
- etat.sqlEchecs++;
- etat.derniereErreur = `${code} (SQL) : ${msg}`;
- console.error(`[sync-nuit] SQL ${code} en échec :`, msg);
- await db.update(syncFournisseurs).set({
- dernierSqlAt: new Date(),
- dernierSqlStatut: "echec",
- dernierSqlErreur: msg.slice(0, 500),
- dernierSqlMs: Date.now() - t0,
- updatedAt: new Date(),
- }).where(eq(syncFournisseurs.codeFournisseur, code)).catch(() => { /* le suivi ne doit pas casser la boucle */ });
- }
-}
-
-/** Format d'un code centrale plausible — même filtre que la synchro manuelle. */
-const CODE_CENTRALE = /^[A-Z0-9][A-Z0-9_-]{1,29}$/i;
-
-/** Extraction Qlik. Même politique que le SQL sur l'horodatage en cas d'échec. */
-async function traiterQlik(code: string, nom: string | null): Promise {
- const t0 = Date.now();
- etat.fournisseurCourant = `${code}${nom ? ` — ${nom}` : ""}`;
- etat.etape = "qlik";
- try {
- const articles = await pgGetArticlesByFournisseur(code);
- const codes = [...new Set(
- articles
- .map((a) => String(a.codeCentrale ?? "").trim())
- .filter((c) => c && c !== "-" && CODE_CENTRALE.test(c)),
- )];
-
- if (codes.length === 0) {
- await db.update(syncFournisseurs).set({
- dernierQlikAt: new Date(), dernierQlikStatut: "vide", dernierQlikCodes: 0,
- dernierQlikErreur: null, dernierQlikMs: Date.now() - t0, updatedAt: new Date(),
- }).where(eq(syncFournisseurs.codeFournisseur, code));
- return;
- }
-
- const dateFilter = buildGridNetworkQlikDateFilter(new Date(), envMonthsBack("QLIK_SYNC_MONTHS_BACK", QLIK_MONTHS_BACK_DEFAULT));
- const metrics = await fetchNetworkMetricsPlaywright(codes, undefined, dateFilter, code);
- const n = await upsertNetworkMetrics([...metrics.values()]);
-
- await db.update(syncFournisseurs).set({
- dernierQlikAt: new Date(), dernierQlikStatut: "succes", dernierQlikCodes: n,
- dernierQlikErreur: null, dernierQlikMs: Date.now() - t0, updatedAt: new Date(),
- }).where(eq(syncFournisseurs.codeFournisseur, code));
- etat.qlikFaits++;
- console.log(`[sync-nuit] Qlik ${code} — ${n} codes en ${Math.round((Date.now() - t0) / 1000)} s`);
- } catch (e) {
- const msg = e instanceof Error ? e.message : String(e);
- etat.qlikEchecs++;
- etat.derniereErreur = `${code} (Qlik) : ${msg}`;
- console.error(`[sync-nuit] Qlik ${code} en échec :`, msg);
- await db.update(syncFournisseurs).set({
- dernierQlikAt: new Date(), dernierQlikStatut: "echec",
- dernierQlikErreur: msg.slice(0, 500), dernierQlikMs: Date.now() - t0, updatedAt: new Date(),
- }).where(eq(syncFournisseurs.codeFournisseur, code)).catch(() => { /* idem */ });
- }
-}
-
-// ─── Boucle de travail ───────────────────────────────────────────────────────
-
-/**
- * Traite les files jusqu'à épuisement, sortie de fenêtre, ou demande d'arrêt.
- *
- * Les deux files avancent en parallèle : une extraction Qlik est intercalée
- * tous les `sqlParQlik` fournisseurs SQL. Sans cet entrelacement, Qlik ne
- * démarrerait jamais tant que la file SQL n'est pas vide.
- */
-export async function lancerRound(origine: "auto" | "manuel", forcerHorsFenetre = false): Promise {
- if (etat.enCours) return;
-
- const s = await readSyncSettings();
- const maintenant = new Date();
- const debut = debutFenetre(s, maintenant);
- if (!forcerHorsFenetre && !debut) return;
- // Un lancement manuel hors fenêtre borne la file sur « depuis ce matin ».
- const depuis = debut ?? new Date(new Date(maintenant).setHours(0, 0, 0, 0));
-
- Object.assign(etat, {
- enCours: true, origine, debutAt: maintenant.toISOString(), finAt: null,
- fournisseurCourant: null, etape: null,
- sqlFaits: 0, sqlEchecs: 0, qlikFaits: 0, qlikEchecs: 0,
- tourTermine: false, arretDemande: false, derniereErreur: null,
- });
- console.log(`[sync-nuit] round ${origine} démarré (fenêtre ${s.heureDebut}h-${s.heureFin}h, Qlik ≤ ${s.qlikParNuit})`);
-
- try {
- await seedSyncFournisseurs();
-
- // Garde anti-boucle. L'avancement de la file repose sur l'écriture de
- // `dernier*At`, et cette écriture est volontairement non bloquante en cas
- // d'erreur. Si elle échoue, le fournisseur resterait le plus ancien et
- // serait repris sans fin : on retient donc ce qui a déjà été tenté.
- const tentes = new Set();
-
- let depuisDernierQlik = 0;
- for (;;) {
- if (etat.arretDemande) break;
- if (!forcerHorsFenetre && !debutFenetre(s, new Date())) {
- console.log("[sync-nuit] fin de fenêtre — arrêt après le fournisseur en cours");
- break;
- }
-
- const qlikPossible = etat.qlikFaits + etat.qlikEchecs < s.qlikParNuit;
-
- // Qlik prioritaire quand le quota d'entrelacement est atteint.
- if (qlikPossible && depuisDernierQlik >= s.sqlParQlik) {
- const cible = await prochainQlik(s.qlikMinJours, new Date());
- if (cible && !tentes.has(`qlik:${cible.codeFournisseur}`)) {
- tentes.add(`qlik:${cible.codeFournisseur}`);
- await traiterQlik(cible.codeFournisseur, cible.nomFournisseur);
- depuisDernierQlik = 0;
- continue;
- }
- }
-
- const cibleSql = await prochainSql(depuis);
- if (cibleSql) {
- if (tentes.has(`sql:${cibleSql.codeFournisseur}`)) {
- console.error(
- `[sync-nuit] ${cibleSql.codeFournisseur} ressort de la file après avoir été traité :`
- + " le suivi n'a pas pu être écrit. Arrêt du round pour ne pas boucler.",
- );
- break;
- }
- tentes.add(`sql:${cibleSql.codeFournisseur}`);
- await traiterSql(cibleSql.codeFournisseur, cibleSql.nomFournisseur);
- depuisDernierQlik++;
- continue;
- }
-
- // File SQL vide : on consacre le temps restant à Qlik.
- if (qlikPossible) {
- const cible = await prochainQlik(s.qlikMinJours, new Date());
- if (cible && !tentes.has(`qlik:${cible.codeFournisseur}`)) {
- tentes.add(`qlik:${cible.codeFournisseur}`);
- await traiterQlik(cible.codeFournisseur, cible.nomFournisseur);
- depuisDernierQlik = 0;
- continue;
- }
- }
-
- etat.tourTermine = true;
- console.log("[sync-nuit] plus rien en attente — tour terminé");
- break;
- }
- } catch (e) {
- etat.derniereErreur = e instanceof Error ? e.message : String(e);
- console.error("[sync-nuit] round interrompu :", etat.derniereErreur);
- } finally {
- // Les pages (stock, hit-parade, CA…) relisent la base fraîche au lieu
- // d'attendre la fin de vie de leur cache.
- invalidateFFCache();
- etat.enCours = false;
- etat.fournisseurCourant = null;
- etat.etape = null;
- etat.finAt = new Date().toISOString();
- console.log(
- `[sync-nuit] round terminé — SQL ${etat.sqlFaits} ok / ${etat.sqlEchecs} en échec,`
- + ` Qlik ${etat.qlikFaits} ok / ${etat.qlikEchecs} en échec, tour bouclé=${etat.tourTermine}`,
- );
- }
-}
-
-/**
- * Battement du minuteur : ne fait quelque chose que dans la fenêtre, et jamais
- * deux rounds à la fois. Volontairement silencieux hors fenêtre — il est appelé
- * chaque minute.
- */
-export async function tickScheduler(): Promise {
- try {
- const s = await readSyncSettings();
- if (!s.actif || etat.enCours) return;
- if (!debutFenetre(s)) return;
- await lancerRound("auto");
- } catch (e) {
- console.error("[sync-nuit] tick en erreur :", e instanceof Error ? e.message : String(e));
- }
-}
diff --git a/src/features/admin/api/sync-settings.ts b/src/features/admin/api/sync-settings.ts
deleted file mode 100644
index 541dbac..0000000
--- a/src/features/admin/api/sync-settings.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * CollectFlow — Réglages de la synchronisation nocturne.
- *
- * Rangés dans `data/.db-config.json`, comme les autres réglages de
- * l'application (base, Qlik, API FF), pour qu'il n'y ait qu'un seul endroit à
- * sauvegarder et à monter dans le conteneur.
- *
- * Module **serveur**, pas fichier d'actions : il exporte aussi des valeurs
- * (les défauts, le type), ce que `"use server"` interdit.
- */
-
-import "server-only";
-
-import fs from "fs/promises";
-import path from "path";
-
-const DATA_DIR = path.join(process.cwd(), "data");
-const CONFIG_FILE = path.join(DATA_DIR, ".db-config.json");
-
-export interface SyncSettings {
- /**
- * Désactivé par défaut : un déploiement ne doit pas se mettre à solliciter
- * Qlik et la base la nuit suivante sans que personne l'ait décidé.
- */
- actif: boolean;
- /** Heure d'ouverture de la fenêtre (0-23). */
- heureDebut: number;
- /** Heure de fermeture. Aucun fournisseur n'est **démarré** après. */
- heureFin: number;
- /**
- * Nombre maximum d'extractions Qlik par nuit. Chacune peut prendre 8 minutes
- * et le serveur abandonne quand il est trop sollicité : ce plafond est la
- * principale protection contre une nuit entièrement passée sur Qlik.
- */
- qlikParNuit: number;
- /** Une extraction Qlik est intercalée tous les N fournisseurs SQL. */
- sqlParQlik: number;
- /**
- * Âge minimal des données Qlik avant de les refaire. Ce sont des agrégats
- * mensuels : les rafraîchir toutes les nuits coûterait cher pour rien.
- */
- qlikMinJours: number;
-}
-
-export const SYNC_SETTINGS_DEFAUT: SyncSettings = {
- actif: false,
- heureDebut: 0,
- heureFin: 5,
- qlikParNuit: 6,
- sqlParQlik: 20,
- qlikMinJours: 7,
-};
-
-function borne(v: unknown, min: number, max: number, defaut: number): number {
- const n = Number(v);
- if (!Number.isFinite(n)) return defaut;
- return Math.min(max, Math.max(min, Math.trunc(n)));
-}
-
-/** Normalise ce qui vient du fichier : il est éditable à la main. */
-function normaliser(brut: Partial | undefined): SyncSettings {
- const d = SYNC_SETTINGS_DEFAUT;
- const s: SyncSettings = {
- actif: Boolean(brut?.actif),
- heureDebut: borne(brut?.heureDebut, 0, 23, d.heureDebut),
- heureFin: borne(brut?.heureFin, 0, 23, d.heureFin),
- qlikParNuit: borne(brut?.qlikParNuit, 0, 200, d.qlikParNuit),
- sqlParQlik: borne(brut?.sqlParQlik, 1, 500, d.sqlParQlik),
- qlikMinJours: borne(brut?.qlikMinJours, 0, 365, d.qlikMinJours),
- };
- // Une fenêtre de durée nulle ne s'ouvrirait jamais : on revient au défaut
- // plutôt que de laisser le planificateur muet sans explication.
- if (s.heureDebut === s.heureFin) {
- s.heureDebut = d.heureDebut;
- s.heureFin = d.heureFin;
- }
- return s;
-}
-
-export async function readSyncSettings(): Promise {
- try {
- const raw = await fs.readFile(CONFIG_FILE, "utf-8");
- const cfg = JSON.parse(raw) as { syncNuit?: Partial };
- return normaliser(cfg?.syncNuit);
- } catch {
- return { ...SYNC_SETTINGS_DEFAUT };
- }
-}
-
-export async function saveSyncSettings(patch: Partial): Promise {
- let existant: Record = {};
- try {
- existant = JSON.parse(await fs.readFile(CONFIG_FILE, "utf-8"));
- } catch {
- // Pas encore de fichier : on le crée avec les seuls réglages de synchro.
- }
- const courant = normaliser((existant.syncNuit as Partial) ?? undefined);
- const suivant = normaliser({ ...courant, ...patch });
-
- await fs.mkdir(DATA_DIR, { recursive: true });
- await fs.writeFile(CONFIG_FILE, JSON.stringify({ ...existant, syncNuit: suivant }, null, 2));
- console.log(`[sync-nuit] réglages enregistrés : ${JSON.stringify(suivant)}`);
- return suivant;
-}
diff --git a/src/features/admin/api/sync-timer.ts b/src/features/admin/api/sync-timer.ts
deleted file mode 100644
index ae1acd6..0000000
--- a/src/features/admin/api/sync-timer.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * CollectFlow — Minuteur de la synchronisation nocturne.
- *
- * Démarré une fois au boot par `src/instrumentation.ts`. Il bat chaque minute
- * et laisse `tickScheduler()` décider s'il y a quelque chose à faire : hors
- * fenêtre, ou si un round tourne déjà, le battement ne coûte rien.
- *
- * Conséquence assumée du choix « minuteur interne » plutôt que cron système :
- * rien ne tourne si l'application est arrêtée. En contrepartie, aucune
- * configuration côté hôte, et le minuteur se réarme tout seul au redémarrage.
- */
-
-import "server-only";
-
-import { tickScheduler } from "@/features/admin/api/sync-scheduler";
-
-const INTERVALLE_MS = 60_000;
-
-/**
- * Garde au niveau du module : en développement, le rechargement à chaud peut
- * réévaluer `register()` plusieurs fois, et on se retrouverait avec autant de
- * minuteurs empilés.
- */
-let minuteur: ReturnType | null = null;
-
-export function startSyncTimer(): void {
- if (minuteur) return;
-
- console.log(`[sync-nuit] minuteur démarré (battement ${INTERVALLE_MS / 1000} s)`);
- minuteur = setInterval(() => {
- // `tickScheduler` capture déjà ses propres erreurs ; ce `catch` ne couvre
- // qu'un rejet inattendu, pour qu'il ne devienne jamais une exception non
- // gérée capable d'abattre le processus.
- void tickScheduler().catch((e) => {
- console.error("[sync-nuit] battement en erreur :", e instanceof Error ? e.message : String(e));
- });
- }, INTERVALLE_MS);
-
- // Ne pas maintenir le processus en vie uniquement pour ce minuteur.
- minuteur.unref?.();
-}
diff --git a/src/features/admin/api/user-actions.ts b/src/features/admin/api/user-actions.ts
index f7a4e89..389957b 100644
--- a/src/features/admin/api/user-actions.ts
+++ b/src/features/admin/api/user-actions.ts
@@ -1,74 +1,46 @@
-"use server";
+/**
+ * Gestion des comptes (administrateurs) — actions exécutées par le serveur
+ * Rust : `POST /api/actions/{nom}`.
+ */
-import { db } from "@/db";
-import { users } from "@/db/schema";
-import { eq } from "drizzle-orm";
-import { hashPassword } from "@/features/auth/logic/auth-logic";
-import { requireAdmin } from "@/lib/authz";
-import { revalidatePath } from "next/cache";
+import { callAction } from "@/lib/rpc";
+
+export interface UtilisateurListe {
+ id: number;
+ username: string;
+ role: string;
+ /** Date ISO de création. */
+ createdAt: string | null;
+}
/**
* Récupère tous les utilisateurs (Admin seulement).
*/
-export async function getUsers() {
- await requireAdmin();
- return db.select({
- id: users.id,
- username: users.username,
- role: users.role,
- createdAt: users.createdAt
- }).from(users);
+export async function getUsers(): Promise {
+ return callAction("getUsers", []);
}
/**
* Crée un nouvel utilisateur.
*/
-export async function createUser(username: string, password: string, role: "admin" | "user" = "user") {
- await requireAdmin();
-
- try {
- await db.insert(users).values({
- username,
- passwordHash: hashPassword(password),
- role,
- });
- revalidatePath("/settings");
- return { success: true };
- } catch (err) {
- console.error("CreateUser Error:", err);
- return { success: false, error: "L'utilisateur existe déjà ou une erreur technique est survenue." };
- }
+export async function createUser(
+ username: string,
+ password: string,
+ role: "admin" | "user" = "user",
+): Promise<{ success: boolean; error?: string }> {
+ return callAction("createUser", [username, password, role]);
}
/**
* Supprime un utilisateur.
*/
-export async function deleteUser(id: number) {
- const moi = await requireAdmin();
- if (Number(moi.id) === id) {
- return { success: false, error: "Vous ne pouvez pas supprimer votre propre compte." };
- }
-
- try {
- await db.delete(users).where(eq(users.id, id));
- revalidatePath("/settings");
- return { success: true };
- } catch {
- return { success: false, error: "Erreur lors de la suppression." };
- }
+export async function deleteUser(id: number): Promise<{ success: boolean; error?: string }> {
+ return callAction("deleteUser", [id]);
}
/**
* Met à jour le mot de passe d'un utilisateur.
*/
-export async function updatePassword(id: number, newPassword: string) {
- await requireAdmin();
- try {
- await db.update(users)
- .set({ passwordHash: hashPassword(newPassword) })
- .where(eq(users.id, id));
- return { success: true };
- } catch {
- return { success: false, error: "Erreur lors de la mise à jour du mot de passe." };
- }
+export async function updatePassword(id: number, newPassword: string): Promise<{ success: boolean; error?: string }> {
+ return callAction("updatePassword", [id, newPassword]);
}
diff --git a/src/features/admin/components/api-connection-info.tsx b/src/features/admin/components/api-connection-info.tsx
index 7aee6bd..643637b 100644
--- a/src/features/admin/components/api-connection-info.tsx
+++ b/src/features/admin/components/api-connection-info.tsx
@@ -1,5 +1,3 @@
-"use client";
-
/**
* CollectFlow — Informations de connexion à l'API `/api/v1`.
*
diff --git a/src/features/admin/components/api-key-management.tsx b/src/features/admin/components/api-key-management.tsx
index dcc6335..8dfd917 100644
--- a/src/features/admin/components/api-key-management.tsx
+++ b/src/features/admin/components/api-key-management.tsx
@@ -1,5 +1,3 @@
-"use client";
-
/**
* CollectFlow — Gestion des clés de l'API `/api/v1`.
*
diff --git a/src/features/admin/components/grid-warmup.tsx b/src/features/admin/components/grid-warmup.tsx
index 614ac3e..73b1fe4 100644
--- a/src/features/admin/components/grid-warmup.tsx
+++ b/src/features/admin/components/grid-warmup.tsx
@@ -1,5 +1,3 @@
-"use client";
-
/**
* CollectFlow — Préchauffage des données exposées par l'API.
*
diff --git a/src/features/admin/components/user-management.tsx b/src/features/admin/components/user-management.tsx
index 13b9d48..75429e0 100644
--- a/src/features/admin/components/user-management.tsx
+++ b/src/features/admin/components/user-management.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { useCallback, useEffect, useState, type FormEvent } from "react";
import { KeyRound, Loader2, Shield, Trash2, User, UserPlus } from "lucide-react";
import { getUsers, createUser, deleteUser, updatePassword } from "../api/user-actions";
diff --git a/src/features/auth/api/login-action.ts b/src/features/auth/api/login-action.ts
deleted file mode 100644
index 9b514f9..0000000
--- a/src/features/auth/api/login-action.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-"use server";
-
-import { signIn } from "@/lib/auth";
-import { AuthError } from "next-auth";
-
-/**
- * Server action to handle user login.
- */
-export async function loginAction(prevState: string | undefined, formData: FormData) {
- try {
- await signIn("credentials", {
- username: formData.get("username"),
- password: formData.get("password"),
- redirectTo: "/dashboard"
- });
- } catch (error) {
- if (error instanceof AuthError) {
- switch (error.type) {
- case "CredentialsSignin":
- return "Utilisateur ou mot de passe incorrect.";
- default:
- return "Une erreur technique est survenue.";
- }
- }
- // Next.js redirect throws a special error that must be rethrown
- throw error;
- }
-}
diff --git a/src/features/auth/components/login-form.tsx b/src/features/auth/components/login-form.tsx
index bd220d5..8aaab14 100644
--- a/src/features/auth/components/login-form.tsx
+++ b/src/features/auth/components/login-form.tsx
@@ -1,11 +1,42 @@
-"use client";
-
import { useActionState } from "react";
-import { loginAction } from "../api/login-action";
import { AlertCircle, Loader2, Lock, ShieldCheck, User } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/form-controls";
+const MESSAGE_IDENTIFIANTS = "Utilisateur ou mot de passe incorrect.";
+const MESSAGE_TECHNIQUE = "Une erreur technique est survenue.";
+
+/**
+ * Connexion : `POST /api/auth/login` (le serveur pose le cookie de session),
+ * puis chargement complet du tableau de bord pour repartir avec la session.
+ * Renvoie le message d'erreur à afficher, ou ne rend jamais la main en cas de
+ * réussite (le bouton reste « Connexion… » jusqu'au changement de page).
+ */
+async function loginAction(_prevState: string | undefined, formData: FormData): Promise {
+ let res: Response;
+ try {
+ res = await fetch("/api/auth/login", {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Accept: "application/json" },
+ credentials: "same-origin",
+ body: JSON.stringify({
+ username: String(formData.get("username") ?? ""),
+ password: String(formData.get("password") ?? ""),
+ }),
+ });
+ } catch {
+ return MESSAGE_TECHNIQUE;
+ }
+ if (!res.ok) {
+ const body = (await res.json().catch(() => null)) as { error?: unknown } | null;
+ if (typeof body?.error === "string" && body.error) return body.error;
+ return res.status === 401 ? MESSAGE_IDENTIFIANTS : MESSAGE_TECHNIQUE;
+ }
+ await res.text().catch(() => "");
+ window.location.assign("/dashboard");
+ return new Promise(() => {});
+}
+
export function LoginForm() {
const [error, action, isPending] = useActionState(loginAction, undefined);
diff --git a/src/features/auth/logic/auth-logic.ts b/src/features/auth/logic/auth-logic.ts
deleted file mode 100644
index 100b79c..0000000
--- a/src/features/auth/logic/auth-logic.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { scryptSync, randomBytes, timingSafeEqual } from "crypto";
-import fs from "fs";
-import path from "path";
-
-const USERS_JSON_PATH = path.join(process.cwd(), "data", "users.json");
-
-export interface UserJson {
- id: string;
- username: string;
- passwordHash: string;
- role: string;
-}
-
-/**
- * Hashes a password using scrypt.
- * Format: salt:hash
- */
-export function hashPassword(password: string): string {
- const salt = randomBytes(16).toString("hex");
- const hash = scryptSync(password, salt, 64).toString("hex");
- return `${salt}:${hash}`;
-}
-
-/**
- * Verifies a password against a stored salt:hash string.
- */
-export function verifyPassword(password: string, storedHash: string): boolean {
- try {
- const [salt, hash] = storedHash.split(":");
- if (!salt || !hash) return false;
-
- const hashBuffer = scryptSync(password, salt, 64);
- const storedHashBuffer = Buffer.from(hash, "hex");
-
- return timingSafeEqual(hashBuffer, storedHashBuffer);
- } catch (e) {
- return false;
- }
-}
-
-/**
- * Reads users from local JSON fallback.
- */
-export function getFallbackUsers(): UserJson[] {
- try {
- if (!fs.existsSync(USERS_JSON_PATH)) {
- // Initial seed if file doesn't exist
- const defaultAdmin: UserJson = {
- id: "0",
- username: "admin",
- passwordHash: hashPassword("admin"),
- role: "admin"
- };
- saveFallbackUsers([defaultAdmin]);
- return [defaultAdmin];
- }
- const data = fs.readFileSync(USERS_JSON_PATH, "utf-8");
- return JSON.parse(data);
- } catch (e) {
- console.error("[AUTH] Error reading users.json:", e);
- return [];
- }
-}
-
-/**
- * Saves users to local JSON fallback.
- */
-export function saveFallbackUsers(users: UserJson[]) {
- try {
- const dir = path.dirname(USERS_JSON_PATH);
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
- fs.writeFileSync(USERS_JSON_PATH, JSON.stringify(users, null, 2));
- } catch (e) {
- console.error("[AUTH] Error writing users.json:", e);
- }
-}
diff --git a/src/features/auth/logic/seed-admin.ts b/src/features/auth/logic/seed-admin.ts
deleted file mode 100644
index 09ae497..0000000
--- a/src/features/auth/logic/seed-admin.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { db } from "@/db";
-import { users } from "@/db/schema";
-import { hashPassword, getFallbackUsers, saveFallbackUsers } from "./auth-logic";
-import { sql } from "drizzle-orm";
-
-/** Amorçage en cours ou réussi pour ce processus (remis à null en cas d'échec). */
-let amorcage: Promise | null = null;
-
-/**
- * Prépare les comptes au premier démarrage, une seule fois par processus.
- *
- * - Base joignable : crée la table `users` si besoin (auto-réparation), puis le
- * compte admin/admin **uniquement si la table est vide**. Un admin supprimé ou
- * renommé n'est donc pas recréé à chaque connexion. Le fichier de secours
- * `data/users.json` n'est pas touché.
- * - Base injoignable (première installation, base pas encore configurée) : on
- * s'assure que le fichier de secours contient un administrateur, et on
- * retentera la base à la prochaine connexion.
- *
- * Renvoie true si le compte admin/admin vient d'être créé en base.
- */
-export function ensureAdminExists(): Promise {
- if (!amorcage) {
- amorcage = amorcer().catch((err: unknown) => {
- // Échec : on retentera à la prochaine connexion.
- amorcage = null;
- console.warn("[AUTH] Database seeding failed (expected if DB not configured yet):", (err as Error)?.message ?? err);
- return false;
- });
- }
- return amorcage;
-}
-
-async function amorcer(): Promise {
- console.log("[AUTH] Testing database connection for seeding...");
- try {
- await db.execute(sql`SELECT 1`);
- } catch (err) {
- assurerAdminDeSecours();
- throw err;
- }
-
- // Auto-repair: Ensure table exists
- await db.execute(sql`
- CREATE TABLE IF NOT EXISTS "users" (
- id SERIAL PRIMARY KEY,
- username VARCHAR(50) NOT NULL UNIQUE,
- password_hash TEXT NOT NULL,
- role VARCHAR(20) NOT NULL DEFAULT 'user',
- created_at TIMESTAMP DEFAULT NOW()
- );
- `);
-
- const [{ nb }] = await db.select({ nb: sql`count(*)::int` }).from(users);
- if (nb > 0) return false;
-
- console.log("[AUTH] Table users vide : création du compte admin/admin.");
- // Si un autre processus l'a créé entre-temps, l'unicité du nom fait échouer
- // l'insertion : on la laisse sans effet plutôt que de relancer l'amorçage.
- const crees = await db.insert(users).values({
- username: "admin",
- passwordHash: hashPassword("admin"),
- role: "admin",
- }).onConflictDoNothing().returning({ id: users.id });
- return crees.length > 0;
-}
-
-/** Base injoignable : le fichier de secours doit contenir au moins un administrateur. */
-function assurerAdminDeSecours() {
- const fallbackUsers = getFallbackUsers();
- if (fallbackUsers.length === 0) {
- console.log("[AUTH] Initializing local JSON fallback with admin/admin...");
- saveFallbackUsers([{
- id: "0",
- username: "admin",
- passwordHash: hashPassword("admin"),
- role: "admin"
- }]);
- }
-}
diff --git a/src/features/commandes-auto/actions.ts b/src/features/commandes-auto/actions.ts
index c4623b2..f9916fe 100644
--- a/src/features/commandes-auto/actions.ts
+++ b/src/features/commandes-auto/actions.ts
@@ -1,11 +1,10 @@
-"use server";
+/**
+ * Cadencier des commandes fournisseurs — actions exécutées par le serveur
+ * Rust : `POST /api/actions/{nom}`.
+ */
-import { revalidatePath } from "next/cache";
-import { and, eq } from "drizzle-orm";
-import { db } from "@/db";
-import { commandeCadences } from "@/db/schema";
-import { getDerniereReceptionCached, getFournisseursCached } from "@/lib/ff-cache";
-import { requireSession, verifierSession } from "@/lib/authz";
+import { callAction } from "@/lib/rpc";
+import { refreshPage } from "@/lib/page-data";
export type CadenceStatut = "a_commander" | "bientot" | "ok" | "inconnu";
@@ -25,21 +24,18 @@ export interface CadenceView {
statut: CadenceStatut;
}
-const MS_PAR_JOUR = 24 * 60 * 60 * 1000;
-/** Seuil (en jours) en dessous duquel une cadence passe en "bientôt à commander" */
-const SEUIL_BIENTOT_JOURS = 7;
-
-function calcStatut(joursRestants: number | null): CadenceStatut {
- if (joursRestants === null) return "inconnu";
- if (joursRestants <= 0) return "a_commander";
- if (joursRestants <= SEUIL_BIENTOT_JOURS) return "bientot";
- return "ok";
+/**
+ * Les actions Next.js de modification appelaient `revalidatePath("/commandes-auto")`,
+ * dont la réponse rafraîchissait la page : même effet ici après une réussite.
+ */
+function rafraichirSiOk(resultat: R): R {
+ if (resultat.ok) refreshPage();
+ return resultat;
}
/** Liste des fournisseurs (référentiel) pour le sélecteur de cadence. */
export async function getFournisseursPourCadence(): Promise<{ code: string; nom: string }[]> {
- await requireSession();
- return getFournisseursCached();
+ return callAction("getFournisseursPourCadence", []);
}
/**
@@ -47,45 +43,7 @@ export async function getFournisseursPourCadence(): Promise<{ code: string; nom:
* de la dernière réception (FF Nancy).
*/
export async function listCadences(): Promise {
- await requireSession();
- let rows: typeof commandeCadences.$inferSelect[] = [];
- let receptions = new Map();
- try {
- rows = await db.select().from(commandeCadences);
- // Réceptions des seuls fournisseurs du cadencier : la lecture sur tout
- // l'historique de tous les fournisseurs était la plus lourde de la page.
- receptions = await getDerniereReceptionCached(rows.map((r) => r.codeFournisseur));
- } catch (e) {
- console.error("[cadence] listCadences error:", (e as Error).message);
- return [];
- }
-
- const now = Date.now();
-
- return rows.map((r) => {
- const receptionIso = receptions.get(`${r.codeFournisseur}|${r.site}`) ?? null;
-
- let echeanceIso: string | null = null;
- let joursRestants: number | null = null;
- if (receptionIso) {
- const echeance = new Date(receptionIso).getTime() + r.intervalleSemaines * 7 * MS_PAR_JOUR;
- echeanceIso = new Date(echeance).toISOString();
- joursRestants = Math.ceil((echeance - now) / MS_PAR_JOUR);
- }
-
- return {
- id: r.id,
- codefou: r.codeFournisseur,
- nomfou: r.nomFournisseur ?? r.codeFournisseur,
- site: r.site,
- intervalleSemaines: r.intervalleSemaines,
- actif: r.actif,
- derniereReception: receptionIso,
- echeance: echeanceIso,
- joursRestants,
- statut: r.actif ? calcStatut(joursRestants) : "inconnu",
- } satisfies CadenceView;
- });
+ return callAction("listCadences", []);
}
export interface UpsertCadenceInput {
@@ -98,76 +56,15 @@ export interface UpsertCadenceInput {
/** Crée ou met à jour la cadence d'un fournisseur sur un site. */
export async function upsertCadence(input: UpsertCadenceInput): Promise<{ ok: boolean; error?: string }> {
- const acces = await verifierSession();
- if (!acces.ok) return { ok: false, error: acces.message };
-
- const codefou = input.codefou?.trim();
- const site = input.site?.trim();
- const intervalle = Math.round(Number(input.intervalleSemaines));
-
- if (!codefou || !site) return { ok: false, error: "Fournisseur et magasin requis." };
- if (!Number.isFinite(intervalle) || intervalle < 1 || intervalle > 104) {
- return { ok: false, error: "L'intervalle doit être compris entre 1 et 104 semaines." };
- }
-
- try {
- await db
- .insert(commandeCadences)
- .values({
- codeFournisseur: codefou,
- nomFournisseur: input.nomfou ?? null,
- site,
- intervalleSemaines: intervalle,
- actif: input.actif ?? true,
- })
- .onConflictDoUpdate({
- target: [commandeCadences.codeFournisseur, commandeCadences.site],
- set: {
- nomFournisseur: input.nomfou ?? null,
- intervalleSemaines: intervalle,
- actif: input.actif ?? true,
- updatedAt: new Date(),
- },
- });
- revalidatePath("/commandes-auto");
- return { ok: true };
- } catch (e) {
- console.error("[cadence] upsertCadence error:", (e as Error).message);
- return { ok: false, error: "Échec de l'enregistrement." };
- }
+ return rafraichirSiOk(await callAction<{ ok: boolean; error?: string }>("upsertCadence", [input]));
}
/** Active / désactive une cadence sans la supprimer. */
export async function toggleCadence(codefou: string, site: string, actif: boolean): Promise<{ ok: boolean; error?: string }> {
- const acces = await verifierSession();
- if (!acces.ok) return { ok: false, error: acces.message };
-
- try {
- await db
- .update(commandeCadences)
- .set({ actif, updatedAt: new Date() })
- .where(and(eq(commandeCadences.codeFournisseur, codefou), eq(commandeCadences.site, site)));
- revalidatePath("/commandes-auto");
- return { ok: true };
- } catch (e) {
- console.error("[cadence] toggleCadence error:", (e as Error).message);
- return { ok: false };
- }
+ return rafraichirSiOk(await callAction<{ ok: boolean; error?: string }>("toggleCadence", [codefou, site, actif]));
}
/** Supprime définitivement une cadence. */
export async function removeCadence(codefou: string, site: string): Promise<{ ok: boolean; error?: string }> {
- const acces = await verifierSession();
- if (!acces.ok) return { ok: false, error: acces.message };
-
- try {
- await db
- .delete(commandeCadences)
- .where(and(eq(commandeCadences.codeFournisseur, codefou), eq(commandeCadences.site, site)));
- revalidatePath("/commandes-auto");
- return { ok: true };
- } catch (e) {
- console.error("[cadence] removeCadence error:", (e as Error).message);
- return { ok: false };
- }
+ return rafraichirSiOk(await callAction<{ ok: boolean; error?: string }>("removeCadence", [codefou, site]));
}
diff --git a/src/features/grid/actions.ts b/src/features/grid/actions.ts
index 80b1fc4..07e4445 100644
--- a/src/features/grid/actions.ts
+++ b/src/features/grid/actions.ts
@@ -1,23 +1,20 @@
-"use server";
+/**
+ * Actions de la Grille (ex-« server actions » Next.js), exécutées par le
+ * serveur Rust : `POST /api/actions/{nom}`.
+ */
-import { getSitesFromApi } from "@/lib/api-ff-client";
-import { getFournisseursCached } from "@/lib/ff-cache";
-import { requireSession } from "@/lib/authz";
+import { callAction } from "@/lib/rpc";
/**
* Get the list of all suppliers from PostgreSQL (fouadr1).
*/
-export async function getFournisseurs() {
- await requireSession();
- // Relu à chaque navigation dans la Grille (changement de fournisseur, de
- // magasin…) : le référentiel ne change qu'avec la recopie nocturne.
- return getFournisseursCached();
+export async function getFournisseurs(): Promise<{ code: string; nom: string }[]> {
+ return callAction("getFournisseurs", []);
}
/**
* Get the list of all stores (sites) from the FF Nancy API.
*/
-export async function getMagasins() {
- await requireSession();
- return getSitesFromApi();
+export async function getMagasins(): Promise<{ code: string; nom: string }[]> {
+ return callAction("getMagasins", []);
}
diff --git a/src/features/grid/api/enregistrer-gammes.ts b/src/features/grid/api/enregistrer-gammes.ts
deleted file mode 100644
index 8c09861..0000000
--- a/src/features/grid/api/enregistrer-gammes.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import "server-only";
-
-import { db } from "@/db";
-import { sessionSnapshots } from "@/db/schema";
-import { eq, desc } from "drizzle-orm";
-import { patchGridRowsCache } from "./get-product-rows";
-import { updateGridRowsGamme } from "@/lib/grid-store";
-
-export interface ChangementGamme {
- codein: string;
- /** Gamme avant la modification (état serveur), conservée pour l'historique. */
- codeGammeBefore: string | null;
- codeGamme: string;
-}
-
-export interface EnregistrementGammes {
- codeFournisseur: string;
- nomFournisseur?: string | null;
- magasin: string;
- changes: ChangementGamme[];
- userId: number | null;
- /** Libellé du snapshot, « Draft — date » par défaut. */
- label?: string;
-}
-
-/**
- * Enregistre des gammes pour un fournisseur — chemin unique de la Grille et de /api/v1.
- *
- * Les changements sont fusionnés par-dessus le dernier snapshot du fournisseur,
- * puis reportés dans le cache mémoire de la Grille et dans l'instantané `grid_rows`.
- * Lève une erreur si l'écriture du snapshot échoue.
- */
-export async function enregistrerGammes(input: EnregistrementGammes): Promise {
- const { codeFournisseur, nomFournisseur, magasin, changes, userId } = input;
- if (changes.length === 0) return 0;
-
- // Charger le dernier snapshot existant pour merger les changements
- const existing = await db
- .select()
- .from(sessionSnapshots)
- .where(eq(sessionSnapshots.codeFournisseur, codeFournisseur))
- .orderBy(desc(sessionSnapshots.createdAt))
- .limit(1);
-
- const prevChanges: Record =
- existing.length > 0
- ? (existing[0].changes as Record)
- : {};
-
- // Merger les nouveaux changements par-dessus l'existant
- const mergedChanges = { ...prevChanges };
- for (const c of changes) {
- mergedChanges[c.codein] = {
- before: c.codeGammeBefore,
- after: c.codeGamme,
- };
- }
-
- // Upsert : insérer un nouveau snapshot "draft" pour ce fournisseur
- await db.insert(sessionSnapshots).values({
- userId,
- codeFournisseur,
- nomFournisseur: nomFournisseur ?? null,
- magasin,
- label: input.label ?? `Draft — ${new Date().toLocaleDateString("fr-FR")}`,
- changes: mergedChanges,
- summaryJson: null,
- type: "snapshot",
- });
-
- // Les lignes en cache reçoivent les nouvelles gammes au lieu d'être jetées :
- // l'invalidation imposait un recalcul complet (jusqu'à ~40 s) à la
- // réouverture suivante. L'instantané lu par /api/v1 suit, sans bloquer.
- patchGridRowsCache(codeFournisseur, changes);
- void updateGridRowsGamme(codeFournisseur, changes).catch((e) =>
- console.error("[enregistrerGammes] mise à jour grid_rows KO:", (e as Error).message?.slice(0, 200)),
- );
-
- return changes.length;
-}
diff --git a/src/features/grid/api/gammes-a-valider-actions.ts b/src/features/grid/api/gammes-a-valider-actions.ts
index 0a7a8f9..227923d 100644
--- a/src/features/grid/api/gammes-a-valider-actions.ts
+++ b/src/features/grid/api/gammes-a-valider-actions.ts
@@ -1,37 +1,21 @@
-"use server";
+/**
+ * Gammes proposées par l'API `/api/v1`, en attente de validation dans la
+ * Grille — actions exécutées par le serveur Rust : `POST /api/actions/{nom}`.
+ */
-import { z } from "zod";
-import { verifierSession } from "@/lib/authz";
-import { listerGammesAValider, supprimerGammesAValider, type GammeAValider } from "@/lib/gammes-a-valider";
+import { callAction } from "@/lib/rpc";
+import type { GammeAValider } from "@/types/ff";
+
+export type { GammeAValider };
/** Gammes proposées par l'API pour un fournisseur, en attente de validation. */
export async function getGammesAValider(
codeFournisseur: string,
): Promise<{ success: boolean; propositions: GammeAValider[]; error?: string }> {
- const acces = await verifierSession();
- if (!acces.ok) return { success: false, propositions: [], error: acces.message };
- try {
- return { success: true, propositions: await listerGammesAValider(String(codeFournisseur)) };
- } catch (err) {
- return { success: false, propositions: [], error: err instanceof Error ? err.message : "Unknown error" };
- }
+ return callAction("getGammesAValider", [codeFournisseur]);
}
-const RejetSchema = z.object({
- codeFournisseur: z.string().min(1),
- codeins: z.array(z.string()),
-});
-
/** Rejette des propositions de l'API (« Annuler les modifications » dans la Grille). */
export async function rejeterGammesAValider(raw: unknown): Promise<{ success: boolean; error?: string }> {
- const acces = await verifierSession();
- if (!acces.ok) return { success: false, error: acces.message };
- const parsed = RejetSchema.safeParse(raw);
- if (!parsed.success) return { success: false, error: "Validation failed: " + parsed.error.message };
- try {
- await supprimerGammesAValider(parsed.data.codeFournisseur, parsed.data.codeins);
- return { success: true };
- } catch (err) {
- return { success: false, error: err instanceof Error ? err.message : "Unknown error" };
- }
+ return callAction("rejeterGammesAValider", [raw]);
}
diff --git a/src/features/grid/api/get-product-rows.ts b/src/features/grid/api/get-product-rows.ts
deleted file mode 100644
index c9f4a6f..0000000
--- a/src/features/grid/api/get-product-rows.ts
+++ /dev/null
@@ -1,779 +0,0 @@
-import "server-only";
-
-import type { ProductRow, GammeCode, GridFilters } from "@/types/grid";
-import { buildLast12MonthsRange, getMensuelByArticles } from "@/lib/api-ff-client";
-import {
- pgGetArticlesByFournisseur,
- pgGetMensuelByFournisseur,
- pgGetGammesByFournisseur,
- pgGetNomenclatureByFournisseur,
- pgGetStockByFournisseur,
- pgGetCommandesByFournisseur,
- pgGetPrixVenteByFournisseur,
- type PgStockRow,
-} from "@/lib/pg-ff-client";
-import { db } from "@/db";
-import { sessionSnapshots } from "@/db/schema";
-import { eq, desc } from "drizzle-orm";
-import { getNetworkMetricsByCodeCentrale, type NetworkMetricCached } from "@/lib/qlik-network-cache";
-import { NB_MAGASINS_RESEAU } from "@/features/grid/lib/network-trend";
-// Persiste l'instantané lu par /api/v1 : sans lui, l'API n'aurait aucune donnée.
-import { readGridSnapshot, upsertGridRows } from "@/lib/grid-store";
-import {
- applyStorePatchInPlace,
- buildStorePatchEntries,
- storePatchCandidates,
- type StorePatch,
- type StorePatchEntry,
-} from "@/features/grid/lib/store-patch";
-
-interface GetProductRowsInput {
- codeFournisseur: string;
- magasin?: string;
- filters?: Partial;
- forceRefresh?: boolean;
-}
-
-const GRID_ROWS_CACHE_TTL_MS = 10 * 60 * 1000;
-/**
- * Bornes du cache mémoire. La synchro nocturne et le préchauffage passent par
- * `getProductRows()` pour CHAQUE fournisseur : sans plafond, le processus finissait
- * par garder toutes les grilles en mémoire (plusieurs centaines de Mo), ce qui
- * ralentissait toutes les requêtes (ramasse-miettes). Ordre d'insertion de la Map
- * = ordre d'usage : on évince les entrées les moins récemment servies.
- */
-const GRID_ROWS_CACHE_MAX_ENTRIES = Number(process.env.GRID_ROWS_CACHE_MAX_ENTRIES ?? 30);
-const GRID_ROWS_CACHE_MAX_ROWS = Number(process.env.GRID_ROWS_CACHE_MAX_ROWS ?? 150_000);
-const gridRowsCache = new Map();
-const gridRowsPending = new Map>();
-/** Nombre d'enregistrements de gammes par fournisseur (cf. patchGridRowsCache). */
-const gammeSaveVersion = new Map();
-
-function cacheGridRows(key: string, rows: ProductRow[]): void {
- gridRowsCache.delete(key);
- gridRowsCache.set(key, { rows, createdAt: Date.now() });
- let totalRows = 0;
- for (const entry of gridRowsCache.values()) totalRows += entry.rows.length;
- for (const [oldKey, entry] of gridRowsCache) {
- if (gridRowsCache.size <= 1) break;
- if (gridRowsCache.size <= GRID_ROWS_CACHE_MAX_ENTRIES && totalRows <= GRID_ROWS_CACHE_MAX_ROWS) break;
- gridRowsCache.delete(oldKey);
- totalRows -= entry.rows.length;
- }
-}
-
-function gridRowsCacheKey(input: GetProductRowsInput): string {
- return `${input.codeFournisseur}:${input.magasin ?? "TOTAL"}`;
-}
-
-export function invalidateGridRowsCache(codeFournisseur?: string) {
- if (codeFournisseur) {
- for (const key of gridRowsCache.keys()) {
- if (key.startsWith(`${codeFournisseur}:`)) gridRowsCache.delete(key);
- }
- for (const key of gridRowsPending.keys()) {
- if (key.startsWith(`${codeFournisseur}:`)) gridRowsPending.delete(key);
- }
- return;
- }
- gridRowsCache.clear();
- gridRowsPending.clear();
-}
-
-/**
- * Reporte des gammes enregistrées sur les lignes déjà en cache, au lieu de jeter
- * le cache : l'invalidation forçait un recalcul complet (jusqu'à ~40 s sur un gros
- * fournisseur) à la réouverture suivante. Le résultat est celui qu'aurait donné
- * ce recalcul : la colonne Gamme reprend la valeur du dernier snapshot (Phase 9),
- * la colonne INIT reste l'état serveur.
- */
-export function patchGridRowsCache(
- codeFournisseur: string,
- changes: ReadonlyArray<{ codein: string; codeGamme: string }>,
-): void {
- if (changes.length === 0) return;
- // Un calcul en cours pour ce fournisseur a lu les gammes avant cet
- // enregistrement : le compteur lui signale de les relire avant d'être caché.
- gammeSaveVersion.set(codeFournisseur, (gammeSaveVersion.get(codeFournisseur) ?? 0) + 1);
- const byCodein = new Map(changes.map((c) => [c.codein, c.codeGamme as GammeCode]));
- for (const [key, entry] of gridRowsCache) {
- if (!key.startsWith(`${codeFournisseur}:`)) continue;
- for (const row of entry.rows) {
- const gamme = byCodein.get(row.codein);
- if (gamme !== undefined) row.codeGamme = gamme;
- }
- }
-}
-
-/**
- * Rafraîchit UNIQUEMENT la colonne INIT (codeGammeInit = gamme serveur courante)
- * sur des lignes servies depuis le cache. La colonne Gamme (codeGamme) n'est pas
- * touchée : elle conserve la valeur issue du snapshot. Ainsi l'état serveur (INIT)
- * est toujours à jour à chaque chargement, même sur un hit du cache 10 min — et le
- * marqueur "modifié" (Gamme ≠ INIT) se résorbe dès que le serveur rattrape la modif.
- */
-async function refreshGammeInit(rows: ProductRow[], codeFournisseur: string): Promise {
- try {
- const gammeMap = await pgGetGammesByFournisseur(codeFournisseur);
- if (gammeMap.size === 0) return;
- for (const row of rows) {
- const live = gammeMap.get(row.codein);
- if (live !== undefined) row.codeGammeInit = live as GammeCode;
- }
- } catch (e) {
- console.error("[getProductRows] refreshGammeInit error:", (e as Error).message?.slice(0, 200));
- }
-}
-
-/**
- * Écrit l'instantané de grille lu par /api/v1 (table `grid_rows`).
- *
- * Seul `magasin = TOTAL` est persisté : `ProductRow` embarque déjà les ventilations
- * par magasin (sales12mByStore, caByStore…), inutile de stocker trois variantes.
- * Toute erreur est avalée : la persistance ne doit jamais casser l'affichage.
- */
-async function persistGridSnapshot(input: GetProductRowsInput, rows: ProductRow[]): Promise {
- if ((input.magasin ?? "TOTAL") !== "TOTAL") return;
- try {
- const n = await upsertGridRows(input.codeFournisseur, rows);
- console.log(`[getProductRows] instantané persisté: ${n} lignes pour ${input.codeFournisseur}`);
- } catch (e) {
- console.error("[getProductRows] persistance grid_rows KO:", (e as Error).message?.slice(0, 200));
- }
-}
-
-export async function getProductRows(input: GetProductRowsInput): Promise {
- const cacheKey = gridRowsCacheKey(input);
- const cached = gridRowsCache.get(cacheKey);
- if (!input.forceRefresh && cached && Date.now() - cached.createdAt < GRID_ROWS_CACHE_TTL_MS) {
- // Remonte l'entrée en tête de l'ordre d'usage (éviction LRU).
- gridRowsCache.delete(cacheKey);
- gridRowsCache.set(cacheKey, cached);
- // La colonne INIT doit refléter l'état serveur à CHAQUE chargement,
- // y compris sur un hit de cache (les données lourdes restent, elles, cachées).
- await refreshGammeInit(cached.rows, input.codeFournisseur);
- return cached.rows;
- }
-
- // Un calcul déjà en cours est réutilisé même en rechargement forcé : il part
- // de données fraîches, et en lancer un second en parallèle doublait la charge
- // (double clic, onglet rouvert…) sans rien apporter.
- const pending = gridRowsPending.get(cacheKey);
- if (pending) {
- return pending;
- }
-
- // Instantané persisté (calcul de la nuit ou de la dernière ouverture) : servi
- // en une lecture au lieu d'un recalcul de 10 à 40 s. Jamais en rechargement
- // forcé — c'est précisément ce que l'utilisateur demande d'éviter.
- if (!input.forceRefresh) {
- const servi = await serveFromSnapshot(input, cacheKey);
- if (servi) return servi;
- }
-
- const versionAuDepart = gammeSaveVersion.get(input.codeFournisseur) ?? 0;
- const promise = buildProductRows(input).then(async (rows) => {
- if ((gammeSaveVersion.get(input.codeFournisseur) ?? 0) !== versionAuDepart) {
- // Gammes enregistrées pendant le calcul : on reprend le dernier snapshot.
- applySnapshotChanges(rows, await loadLatestSnapshotChanges(input.codeFournisseur));
- }
- cacheGridRows(cacheKey, rows);
- gridRowsPending.delete(cacheKey);
- // Persiste l'instantané pour /api/v1 : le calcul vient d'avoir lieu, on
- // arrête simplement de jeter le résultat. Volontairement NON bloquant —
- // l'affichage de la Grille ne doit pas attendre l'écriture.
- void persistGridSnapshot(input, rows);
- return rows;
- }).catch((error) => {
- gridRowsPending.delete(cacheKey);
- throw error;
- });
-
- gridRowsPending.set(cacheKey, promise);
- return promise;
-}
-
-/** Au-delà, l'instantané est servi mais un recalcul est relancé en arrière-plan. */
-const SNAPSHOT_REFRESH_AFTER_MS = 20 * 60 * 60 * 1000;
-
-/**
- * Sert la Grille depuis `grid_rows` quand c'est possible : mêmes lignes que le
- * calcul en direct (elles en sont issues), avec la gamme FF du moment (INIT) et
- * les dernières gammes enregistrées reportées dessus. Hors « tous magasins »,
- * le rattrapage du magasin choisi est appliqué comme après un calcul.
- *
- * `null` = pas d'instantané utilisable (absent, ancien format, autre mois) :
- * l'appelant recalcule.
- */
-async function serveFromSnapshot(input: GetProductRowsInput, cacheKey: string): Promise {
- const { codeFournisseur, magasin = "TOTAL" } = input;
- let snapshot: Awaited>;
- try {
- snapshot = await readGridSnapshot(codeFournisseur);
- } catch (e) {
- console.error("[getProductRows] lecture grid_rows KO:", (e as Error).message?.slice(0, 200));
- return null;
- }
- if (!snapshot || snapshot.rows.length === 0) return null;
-
- const { rows } = snapshot;
- // Les colonnes réseau de l'instantané datent de son calcul : on les relit dans
- // le cache Qlik, comme le calcul en direct. Sans cela, une synchro Qlik faite
- // depuis (au changement de mois notamment) restait invisible jusqu'au
- // prochain recalcul, et la tendance réseau disparaissait.
- const [changes, network] = await Promise.all([
- loadLatestSnapshotChanges(codeFournisseur),
- fetchNetworkMetrics(rows.map((r) => r.codeCentrale ?? "")),
- refreshGammeInit(rows, codeFournisseur),
- ]);
- applySnapshotChanges(rows, changes);
- enrichWithNetworkMetrics(rows, network);
-
- if (magasin !== "TOTAL") {
- const { dateDebut, dateFin } = buildLast12MonthsRange();
- await reconcileSelectedStoreFromMensuelApi(rows, magasin, dateDebut, dateFin, last12Periods());
- }
-
- cacheGridRows(cacheKey, rows);
-
- // Instantané qui n'a pas été recalculé par la nuit : on le rafraîchit sans
- // faire attendre l'utilisateur (la prochaine ouverture en profitera).
- // Toujours le calcul « tous magasins » : c'est lui qui réécrit l'instantané.
- if (Date.now() - snapshot.computedAt.getTime() > SNAPSHOT_REFRESH_AFTER_MS && !gridRowsPending.has(`${codeFournisseur}:TOTAL`)) {
- void getProductRows({ codeFournisseur, magasin: "TOTAL", forceRefresh: true }).catch((e) =>
- console.error("[getProductRows] rafraîchissement en arrière-plan KO:", (e as Error).message?.slice(0, 200)),
- );
- }
- return rows;
-}
-
-/** Les 12 derniers mois complets, clés « YYYYMM » triées (même fenêtre que le calcul). */
-function last12Periods(): string[] {
- const now = new Date();
- const periods: string[] = [];
- for (let i = 12; i >= 1; i--) {
- const d = new Date(now.getFullYear(), now.getMonth() - i, 1);
- periods.push(`${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, "0")}`);
- }
- return periods;
-}
-
-async function buildProductRows(input: GetProductRowsInput): Promise {
- const { codeFournisseur, magasin = "TOTAL" } = input;
- console.log(`\n>>> [getProductRows] supplier: ${codeFournisseur}, magasin: ${magasin}`);
-
- try {
- const { dateDebut, dateFin } = buildLast12MonthsRange();
-
- // ─── Phase 1 : 7 requêtes SQL en parallèle ────────────────────────────
- // Remplace des centaines/milliers d'appels HTTP per-article.
- const articlesPromise = pgGetArticlesByFournisseur(codeFournisseur).catch(e => { console.error("[getProductRows] pgGetArticlesByFournisseur ERROR:", e); return []; });
- // Phases 8 et 9 lancées dès maintenant : elles n'attendent que la liste des
- // articles (codes centraux) ou le seul code fournisseur. Exécutées après la
- // Phase 1, elles ajoutaient deux allers-retours en série à chaque calcul.
- const networkPromise = articlesPromise.then((arts) =>
- fetchNetworkMetrics(arts.map((a) => (a.codeCentrale ? String(a.codeCentrale).trim() : ""))),
- );
- const snapshotPromise = loadLatestSnapshotChanges(codeFournisseur);
-
- const [
- articles,
- mensuelRows,
- gammeMap,
- nomMap,
- stockMap,
- commandesMap,
- prixVenteMap,
- ] = await Promise.all([
- articlesPromise,
- pgGetMensuelByFournisseur(codeFournisseur, dateDebut, dateFin).catch(e => { console.error("[getProductRows] pgGetMensuelByFournisseur ERROR:", e); return []; }),
- pgGetGammesByFournisseur(codeFournisseur).catch(e => { console.error("[getProductRows] pgGetGammesByFournisseur ERROR:", e); return new Map(); }),
- pgGetNomenclatureByFournisseur(codeFournisseur).catch(e => { console.error("[getProductRows] pgGetNomenclatureByFournisseur ERROR:", e); return new Map(); }),
- pgGetStockByFournisseur(codeFournisseur).catch(e => { console.error("[getProductRows] pgGetStockByFournisseur ERROR:", e); return new Map(); }),
- pgGetCommandesByFournisseur(codeFournisseur).catch(e => { console.error("[getProductRows] pgGetCommandesByFournisseur ERROR:", e); return new Map(); }),
- pgGetPrixVenteByFournisseur(codeFournisseur).catch(e => { console.error("[getProductRows] pgGetPrixVenteByFournisseur ERROR:", e); return new Map>(); }),
- ]);
-
- console.log(`[getProductRows] ${articles.length} articles, ${mensuelRows.length} mensuel rows, ${gammeMap.size} gammes`);
-
- // ─── Phase 2 : Fenêtre temporelle 12 mois complets ───────────────────
- const sortedPeriods = last12Periods();
- const allowedPeriods = new Set(sortedPeriods);
-
- // ─── Phase 3 : Seed productMap depuis articles ────────────────────────
- const productMap = new Map();
- for (const art of articles) {
- if (!art.codein || productMap.has(art.codein)) continue;
- productMap.set(art.codein, {
- codein: art.codein,
- codeFournisseur: art.codefou ?? codeFournisseur,
- nomFournisseur: art.nomfou ?? "",
- fournisseurPrincipalCode: art.codefou_principal ?? undefined,
- fournisseurPrincipalNom: art.nomfou_principal ?? undefined,
- libelle1: art.libelle1 ?? "",
- gtin: art.gtin ?? "",
- reference: art.reference ?? "",
- codeCentrale: art.codeCentrale ? String(art.codeCentrale).trim() : undefined,
- code1: "", libelleNiveau1: "",
- code2: "", libelleNiveau2: "",
- code3: "", libelle3: "",
- codeGamme: null,
- codeGammeInit: null,
- codeGammeDraft: null,
- sales12m: {},
- stock12m: {},
- receptions12m: {},
- totalQuantite: 0,
- totalCa: 0,
- totalMarge: 0,
- tauxMarge: 0,
- workingStores: [],
- noid: art.no_id ? Number(art.no_id) : undefined,
- pcb: art.pcb ? Number(art.pcb) : undefined,
- prixVente: art.pv_central ? Number(art.pv_central) : undefined,
- });
- }
-
- // ─── Phase 4 : Agréger mensuelRows → byPeriod par codein ─────────────
- // SQL a déjà fait l'agrégation par (codein, site, mois).
- // On somme les 2 sites (TOTAL) ET on accumule par site pour le switch client-side.
- type PeriodData = { qty: number; ca: number; marge: number; stock: number; receptions: number };
- const mensuelByCodein = new Map>();
- const mensuelBySite = new Map>>(); // codein → site → periode → data
- const storeMonthsByCodein = new Map>>();
-
- for (const row of mensuelRows) {
- const periode = row.mois.replace("-", ""); // "2026-02" → "202602"
- if (!allowedPeriods.has(periode)) continue;
-
- // Accumulation TOTAL (toujours tous sites)
- if (!mensuelByCodein.has(row.codein)) mensuelByCodein.set(row.codein, new Map());
- const byPeriod = mensuelByCodein.get(row.codein)!;
- if (!byPeriod.has(periode)) byPeriod.set(periode, { qty: 0, ca: 0, marge: 0, stock: 0, receptions: 0 });
- const p = byPeriod.get(periode)!;
- p.stock += Number(row.stock_fin_mois) || 0;
- p.qty += Number(row.qte_vendue) || 0;
- p.ca += Number(row.ca_ht) || 0;
- p.marge += Number(row.marge) || 0;
- p.receptions += Number(row.qte_recue) || 0;
-
- // Accumulation par site (pour switch client-side)
- if (!mensuelBySite.has(row.codein)) mensuelBySite.set(row.codein, new Map());
- const bySite = mensuelBySite.get(row.codein)!;
- if (!bySite.has(row.site)) bySite.set(row.site, new Map());
- const siteByPeriod = bySite.get(row.site)!;
- if (!siteByPeriod.has(periode)) siteByPeriod.set(periode, { qty: 0, ca: 0, marge: 0, stock: 0, receptions: 0 });
- const sp = siteByPeriod.get(periode)!;
- sp.qty += Number(row.qte_vendue) || 0;
- sp.ca += Number(row.ca_ht) || 0;
- sp.marge += Number(row.marge) || 0;
- sp.stock = Number(row.stock_fin_mois) || 0; // SQL donne déjà le dernier mouvement
- sp.receptions += Number(row.qte_recue) || 0;
-
- // Suivi magasins actifs (pour workingStores) : 1 vente suffit
- if (Number(row.qte_vendue) > 0) {
- if (!storeMonthsByCodein.has(row.codein)) storeMonthsByCodein.set(row.codein, new Map());
- storeMonthsByCodein.get(row.codein)!.set(row.site, new Set());
- }
- }
-
- // ─── Phase 5 : Remplir ProductRow depuis mensuelByCodein ─────────────
- for (const [codein, byPeriod] of mensuelByCodein.entries()) {
- const product = productMap.get(codein);
- if (!product) continue;
-
- let lastStock = 0;
- for (const periode of sortedPeriods) {
- const p = byPeriod.get(periode);
- if (p) {
- product.sales12m[periode] = p.qty;
- product.stock12m[periode] = p.stock;
- product.receptions12m[periode] = p.receptions;
- product.totalQuantite += p.qty;
- product.totalCa += p.ca;
- product.totalMarge += p.marge;
- lastStock = p.stock;
- } else {
- product.sales12m[periode] = 0;
- product.stock12m[periode] = lastStock; // carry-forward
- product.receptions12m[periode] = 0;
- }
- }
-
- product.tauxMarge = product.totalCa > 0 ? (product.totalMarge / product.totalCa) * 100 : 0;
-
- // Breakdowns par site pour le switch client-side
- const siteMap = mensuelBySite.get(codein);
- if (siteMap) {
- product.sales12mByStore = {};
- product.stock12mByStore = {};
- product.receptions12mByStore = {};
- product.caByStore = {};
- product.quantiteByStore = {};
- product.margeByStore = {};
- for (const [site, siteByPeriod] of siteMap.entries()) {
- product.sales12mByStore[site] = {};
- product.stock12mByStore[site] = {};
- product.receptions12mByStore![site] = {};
- let sQty = 0, sCa = 0, sMarge = 0;
- let lastSiteStock = 0;
- for (const periode of sortedPeriods) {
- const sp = siteByPeriod.get(periode);
- product.sales12mByStore[site][periode] = sp?.qty ?? 0;
- product.receptions12mByStore![site][periode] = sp?.receptions ?? 0;
- if (sp) {
- product.stock12mByStore[site][periode] = sp.stock;
- lastSiteStock = sp.stock;
- } else {
- product.stock12mByStore[site][periode] = lastSiteStock; // carry-forward
- }
- sQty += sp?.qty ?? 0;
- sCa += sp?.ca ?? 0;
- sMarge += sp?.marge ?? 0;
- }
- product.quantiteByStore[site] = sQty;
- product.caByStore[site] = sCa;
- product.margeByStore[site] = sMarge;
- }
-
- // Le stock TOTAL se recalcule ici, à partir des séries par site.
- //
- // Il était sommé plus haut depuis les lignes mensuelles brutes, ce
- // qui perdait tout magasin SANS MOUVEMENT dans le mois : le stock
- // est un niveau, pas un flux — un magasin qui n'a rien vendu ni reçu
- // détient toujours sa marchandise. Sur un produit à faible rotation,
- // « tous magasins » n'affichait donc que le site actif, en pratique
- // Frouard. Les séries par site, elles, sont reportées d'un mois sur
- // l'autre : leur somme est la bonne.
- const sites = Object.keys(product.stock12mByStore);
- if (sites.length > 0) {
- for (const periode of sortedPeriods) {
- product.stock12m[periode] = sites.reduce(
- (total, site) => total + (product.stock12mByStore![site][periode] ?? 0),
- 0,
- );
- }
- }
- }
-
- // workingStores : sites avec au moins 1 vente sur les 12 derniers mois
- const storeMonths = storeMonthsByCodein.get(codein);
- if (storeMonths) {
- product.workingStores = [...storeMonths.keys()].sort();
- }
-
- // Commandes en cours
- const cmdQty = commandesMap.get(codein);
- if (cmdQty) product.commandesEnCours = cmdQty;
- }
-
- // ─── Phase 6 : Gammes (saison active) ────────────────────────────────
- for (const [codein, gammeCode] of gammeMap.entries()) {
- const product = productMap.get(codein);
- if (!product) continue;
- product.codeGammeInit = gammeCode as GammeCode;
- product.codeGamme = gammeCode as GammeCode;
- }
-
- // ─── Phase 6b : Nomenclature (famille / sous-famille) ────────────────
- for (const [codein, nom] of nomMap.entries()) {
- const product = productMap.get(codein);
- if (!product) continue;
- product.code3 = nom.code3 ?? "";
- product.libelle3 = nom.libelle3 ?? "";
- product.code2 = nom.code2 ?? "";
- product.libelleNiveau2 = nom.libelle2 ?? "";
- product.code1 = nom.code1 ?? "";
- product.libelleNiveau1 = nom.libelle1nom ?? "";
- }
-
- // ─── Phase 7 : Stock temps réel (cube_stock) ─────────────────────────
- for (const [codein, stocks] of stockMap.entries()) {
- const product = productMap.get(codein);
- if (!product) continue;
-
- const sitesStock = stocks;
-
- product.stockActuel = sitesStock.reduce((s, r) => s + (Number(r.stockdispo) || 0), 0);
- product.stockTotal = sitesStock.reduce((s, r) => s + (Number(r.qte) || 0), 0);
- product.stockValeur = sitesStock.reduce((s, r) => s + (Number(r.valstock) || 0), 0);
-
- const withPrmp = sitesStock.find(r => Number(r.prmp) > 0);
- if (withPrmp) {
- product.pa = Number(withPrmp.prmp);
- product.prixAchat = product.pa;
- }
-
- const dernVente = sitesStock.reduce((best, r) =>
- r.dernierevente && r.dernierevente > best ? r.dernierevente : best, "");
- if (dernVente) product.derniereVente = dernVente;
-
- const dernLiv = sitesStock.reduce((best, r) =>
- r.dernierereception && r.dernierereception > best ? r.dernierereception : best, "");
- if (dernLiv) product.derniereLivraison = dernLiv;
-
- // Map store-specific delivery dates
- product.derniereLivraisonByStore = {};
- for (const r of sitesStock) {
- if (r.site && r.dernierereception) {
- product.derniereLivraisonByStore[r.site] = r.dernierereception;
- }
- }
- }
-
- // ─── Phase 7b : Prix de vente (cube_pv, sinon le PV du cube de stock) ─
- //
- // `article_infosup.prix_vente_mini`, renseigné en Phase 3, n'est qu'une
- // borne de paramétrage : elle est vide en base et laissait la colonne PV
- // entièrement creuse. Le vrai prix vit dans `cube_pv`, par article ET par
- // site. On garde le détail par magasin — deux magasins peuvent ne pas
- // pratiquer le même prix, et l'afficher vaut mieux que le moyenner.
- for (const product of productMap.values()) {
- const parSite = prixVenteMap.get(product.codein);
- if (parSite && Object.keys(parSite).length > 0) {
- product.prixVenteByStore = parSite;
- } else {
- // Filet de secours : le cube de stock porte le même PV, mais
- // seulement pour les articles qui ont une ligne de stock.
- const depuisStock: Record = {};
- for (const s of stockMap.get(product.codein) ?? []) {
- const pv = Number(s.pv);
- const site = String(s.site ?? "").trim();
- if (site && Number.isFinite(pv) && pv > 0) depuisStock[site] = pv;
- }
- if (Object.keys(depuisStock).length > 0) product.prixVenteByStore = depuisStock;
- }
-
- const prix = Object.values(product.prixVenteByStore ?? {});
- // Le plus élevé quand les magasins divergent : une moyenne inventerait
- // un prix qu'aucune caisse ne pratique. L'écart est signalé à l'écran.
- if (prix.length > 0) product.prixVente = Math.max(...prix);
- }
-
- // ─── Phase 8 : Données réseau Qlik (CA / Qté / nb magasins par code centrale) ──
- enrichWithNetworkMetrics(productMap.values(), await networkPromise);
-
- // ─── Phase 9 : Restaurer gammes depuis dernier snapshot ──────────────
- // La colonne Gamme (codeGamme) conserve la valeur du snapshot telle quelle.
- // La colonne INIT (codeGammeInit) reste, elle, l'état LIVE du serveur
- // rechargé en Phase 6 — jamais écrasée ici.
- applySnapshotChanges(productMap.values(), await snapshotPromise);
-
- // ─── Phase 10 : Filtrer gamme Y sans ventes ──────────────────────────
- const allRows = Array.from(productMap.values());
- const rows = allRows.filter(p => p.codeGamme !== "Y" || p.totalQuantite > 0);
- await reconcileSelectedStoreFromMensuelApi(rows, magasin, dateDebut, dateFin, sortedPeriods);
- const excludedY = allRows.length - rows.length;
- console.log(`[getProductRows] ${rows.length} produits (${excludedY} gamme Y sans ventes exclus), ${mensuelByCodein.size} avec ventes`);
-
- return rows;
-
- } catch (error) {
- console.error(`[getProductRows] Error for ${codeFournisseur}:`, error);
- // Ne PAS renvoyer [] : une liste vide est indiscernable d'un fournisseur
- // sans article. La Grille affichait une page blanche sans explication, et
- // la synchro nocturne prenait la panne pour un fournisseur vide — qu'elle
- // désactivait alors automatiquement. La remonter laisse chaque appelant la
- // traiter comme une erreur (bandeau rouge, statut « echec »).
- throw error instanceof Error
- ? error
- : new Error(`Calcul de la grille impossible pour ${codeFournisseur} : ${String(error)}`);
- }
-}
-
-/** Articles complétés par l'API FF, au plus, lors d'un changement de magasin. */
-function plafondComplement(): number {
- return Number(process.env.GRID_STORE_RECONCILE_MAX ?? 300);
-}
-
-/** Interroge l'API FF pour les articles du magasin à compléter (cf. store-patch). */
-async function fetchStorePatchEntries(
- rows: ProductRow[],
- magasin: string,
- dateDebut: string,
- dateFin: string,
- periods: string[],
-): Promise {
- const candidates = storePatchCandidates(rows, magasin);
- if (candidates.length === 0) return [];
-
- // Ce rattrapage fait UNE requête HTTP par article : sur un gros fournisseur,
- // les candidats se comptent par milliers et le changement de magasin se fige
- // plusieurs minutes. On le borne, et on dit ce qui a été laissé de côté
- // plutôt que de tronquer en silence.
- const PLAFOND = plafondComplement();
- const retenus = candidates.slice(0, PLAFOND);
- if (candidates.length > retenus.length) {
- console.warn(
- `[getProductRows] rattrapage magasin ${magasin} borné à ${retenus.length} articles`
- + ` sur ${candidates.length} : les autres gardent la valeur SQL.`,
- );
- }
-
- const mensuelMap = await getMensuelByArticles(
- retenus.map((row) => ({
- codein: row.codein,
- libelle1: row.libelle1,
- codefou: row.codeFournisseur,
- noid: row.noid,
- })),
- dateDebut,
- dateFin,
- 25
- );
- return buildStorePatchEntries(retenus, magasin, periods, mensuelMap);
-}
-
-async function reconcileSelectedStoreFromMensuelApi(
- rows: ProductRow[],
- magasin: string,
- dateDebut: string,
- dateFin: string,
- sortedPeriods: string[]
-) {
- if (magasin === "TOTAL") return;
- try {
- const entries = await fetchStorePatchEntries(rows, magasin, dateDebut, dateFin, sortedPeriods);
- const fixedRows = applyStorePatchInPlace(rows, magasin, sortedPeriods, entries);
- if (fixedRows > 0) {
- console.log(`[getProductRows] ${fixedRows} produits corrigés via API mensuelle pour magasin ${magasin}`);
- }
- } catch (error) {
- console.error("[getProductRows] Mensuel API reconciliation error:", error);
- }
-}
-
-/**
- * Compléments par magasin, rattachés au tableau de lignes « tous magasins » en
- * cache : ils vivent et meurent avec lui (expiration, « Actualiser », nouvel
- * enregistrement), sans autre invalidation à gérer.
- */
-const storePatches = new WeakMap>>();
-
-/**
- * Complément de l'API FF pour un magasin, calculé sur les lignes « tous
- * magasins » (jamais modifiées ici). La Grille l'applique à son arrivée, sans
- * recharger les lignes. Les demandes simultanées partagent le même calcul, et
- * un échec n'est jamais gardé.
- */
-export async function getStorePatch(codeFournisseur: string, magasin: string): Promise {
- const enCache = gridRowsCache.get(`${codeFournisseur}:TOTAL`);
- const rows = enCache && Date.now() - enCache.createdAt < GRID_ROWS_CACHE_TTL_MS
- ? enCache.rows
- : await getProductRows({ codeFournisseur, magasin: "TOTAL" });
-
- let parMagasin = storePatches.get(rows);
- if (!parMagasin) {
- parMagasin = new Map();
- storePatches.set(rows, parMagasin);
- }
- let patch = parMagasin.get(magasin);
- if (!patch) {
- const periods = last12Periods();
- const { dateDebut, dateFin } = buildLast12MonthsRange();
- const enCours = fetchStorePatchEntries(rows, magasin, dateDebut, dateFin, periods)
- .then((entries): StorePatch => ({ magasin, periods, entries }));
- const table = parMagasin;
- enCours.catch(() => {
- if (table.get(magasin) === enCours) table.delete(magasin);
- });
- parMagasin.set(magasin, enCours);
- patch = enCours;
- }
- return patch;
-}
-
-/**
- * Extrait la série « nombre de magasins vendeurs » du détail mensuel complet.
- *
- * `metricsByMonth` porte les cinq mesures Qlik du mois ; seule `nbMag` sert à la
- * deuxième courbe de la carte tendance. Renvoie `null` plutôt qu'un objet vide
- * pour que l'UI distingue « pas de donnée » de « zéro magasin ».
- */
-function nbMagParMois(
- metricsByMonth: Record | null | undefined,
-): Record | null {
- if (!metricsByMonth) return null;
- const parMois: Record = {};
- for (const [mois] of Object.entries(metricsByMonth)) {
- // Un mois PRÉSENT dans le détail est un mois extrait : s'il n'a pas de
- // `nbMag`, c'est qu'aucun magasin n'a vendu, donc zéro. Le traiter comme
- // « manquant » amputait la série et faisait disparaître toute la courbe
- // (les anciens caches n'écrivaient `nbMag` que sur les mois avec vente).
- const nb = Number(metricsByMonth[mois]?.nbMag);
- parMois[mois] = Number.isFinite(nb) ? nb : 0;
- }
- return Object.keys(parMois).length > 0 ? parMois : null;
-}
-
-type SnapshotChanges = Record;
-
-/**
- * Phase 9 : la colonne Gamme (codeGamme) reprend la valeur du snapshot ;
- * codeGammeInit reste figé (état serveur).
- */
-function applySnapshotChanges(rows: Iterable, changes: SnapshotChanges | null): void {
- if (!changes) return;
- for (const row of rows) {
- const change = changes[row.codein];
- if (change?.after) row.codeGamme = change.after as GammeCode;
- }
-}
-
-/** Dernières gammes enregistrées pour ce fournisseur (Phase 9), ou `null`. */
-async function loadLatestSnapshotChanges(codeFournisseur: string): Promise {
- try {
- const snaps = await db
- .select({ changes: sessionSnapshots.changes })
- .from(sessionSnapshots)
- .where(eq(sessionSnapshots.codeFournisseur, codeFournisseur))
- .orderBy(desc(sessionSnapshots.createdAt))
- .limit(1);
- return snaps.length > 0 ? (snaps[0].changes as SnapshotChanges) : null;
- } catch (snapErr) {
- console.error("[getProductRows] Snapshot restore error:", snapErr);
- return null;
- }
-}
-
-/**
- * Lit les metriques reseau Qlik (cache qlik_network_metrics) des codes centraux
- * donnes. `null` en cas d'erreur : la grille s'affiche alors sans donnees reseau.
- */
-async function fetchNetworkMetrics(
- codesCentrale: string[],
-): Promise