From 7882b0493af551b30a3334cd762a1b4a72698e52 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:52:50 +0300 Subject: [PATCH 01/31] refactor: remove unused quiz and recommendation service functions --- apps/api/src/services/quizzes.ts | 3 --- apps/api/src/services/recommendations.ts | 3 --- 2 files changed, 6 deletions(-) delete mode 100644 apps/api/src/services/quizzes.ts delete mode 100644 apps/api/src/services/recommendations.ts diff --git a/apps/api/src/services/quizzes.ts b/apps/api/src/services/quizzes.ts deleted file mode 100644 index 2288cc0..0000000 --- a/apps/api/src/services/quizzes.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const generateNewQuiz = () => { - console.log("Generating a new quiz..."); -}; diff --git a/apps/api/src/services/recommendations.ts b/apps/api/src/services/recommendations.ts deleted file mode 100644 index 63a8bd7..0000000 --- a/apps/api/src/services/recommendations.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const getRecommendations = () => { - console.log("Getting recommendations..."); -}; From 0fb3a0b0179beb1b0552bbb78e273418d9b17ecd Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:52:58 +0300 Subject: [PATCH 02/31] fix(pnpm-lock): update dependency versions and add axios --- pnpm-lock.yaml | 71 +++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d1a243..86d32e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,7 +25,7 @@ importers: dependencies: '@adminjs/express': specifier: ^6.1.1 - version: 6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1) + version: 6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1) '@prisma/client': specifier: 6.11.1 version: 6.11.1(prisma@6.12.0(typescript@5.8.2))(typescript@5.8.2) @@ -34,7 +34,10 @@ importers: version: 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) adminjs: specifier: ^7.8.17 - version: 7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8) + version: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) + axios: + specifier: ^1.11.0 + version: 1.11.0 better-auth: specifier: ^1.2.12 version: 1.3.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -173,7 +176,7 @@ importers: version: 9.32.0 '@tailwindcss/vite': specifier: ^4.1.5 - version: 4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.6.3 @@ -194,7 +197,7 @@ importers: version: 19.1.6(@types/react@19.1.8) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.6) @@ -233,16 +236,16 @@ importers: version: 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.7.3) vite: specifier: ^6.3.1 - version: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + version: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) vite-plugin-svgr: specifier: ^4.3.0 - version: 4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) vitest: specifier: ^3.1.2 - version: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3) + version: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) packages: @@ -5688,9 +5691,9 @@ snapshots: - react-is - supports-color - '@adminjs/express@6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1)': + '@adminjs/express@6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1)': dependencies: - adminjs: 7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8) + adminjs: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) express: 4.21.2 express-formidable: 1.2.0 express-session: 1.18.2 @@ -6963,7 +6966,7 @@ snapshots: '@floating-ui/utils@0.2.10': {} - '@hello-pangea/dnd@16.6.0(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@hello-pangea/dnd@16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.28.2 css-box-model: 1.2.1 @@ -6971,7 +6974,7 @@ snapshots: raf-schd: 4.0.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-redux: 8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) + react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) redux: 4.2.1 use-memo-one: 1.1.3(react@18.3.1) transitivePeerDependencies: @@ -7736,12 +7739,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.11 '@tailwindcss/oxide-win32-x64-msvc': 4.1.11 - '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': + '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': dependencies: '@tailwindcss/node': 4.1.11 '@tailwindcss/oxide': 4.1.11 tailwindcss: 4.1.11 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) '@tanstack/query-core@5.83.0': {} @@ -8282,7 +8285,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': + '@vitejs/plugin-react@4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0) @@ -8290,7 +8293,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - supports-color @@ -8302,13 +8305,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -8349,7 +8352,7 @@ snapshots: acorn@8.15.0: {} - adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8): + adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8): dependencies: '@adminjs/design-system': 4.1.1(@babel/core@7.28.0)(@types/react@19.1.8)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) '@babel/core': 7.28.0 @@ -8360,7 +8363,7 @@ snapshots: '@babel/preset-react': 7.27.1(@babel/core@7.28.0) '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) '@babel/register': 7.27.1(@babel/core@7.28.0) - '@hello-pangea/dnd': 16.6.0(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@hello-pangea/dnd': 16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@redux-devtools/extension': 3.3.0(redux@4.2.1) '@rollup/plugin-babel': 6.0.4(@babel/core@7.28.0)(@types/babel__core@7.20.5)(rollup@4.40.2) '@rollup/plugin-commonjs': 25.0.8(rollup@4.40.2) @@ -8383,7 +8386,7 @@ snapshots: react-feather: 2.0.10(react@18.3.1) react-i18next: 12.3.1(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-is: 18.3.1 - react-redux: 8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) + react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) react-router: 6.30.1(react@18.3.1) react-router-dom: 6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) redux: 4.2.1 @@ -10601,7 +10604,7 @@ snapshots: react-fast-compare: 3.2.2 warning: 4.0.3 - react-redux@8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1): + react-redux@8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1): dependencies: '@babel/runtime': 7.28.2 '@types/hoist-non-react-statics': 3.3.7(@types/react@19.1.8) @@ -10612,6 +10615,7 @@ snapshots: use-sync-external-store: 1.5.0(react@18.3.1) optionalDependencies: '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) react-dom: 18.3.1(react@18.3.1) redux: 4.2.1 @@ -11424,13 +11428,13 @@ snapshots: vary@1.1.2: {} - vite-node@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3): + vite-node@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): dependencies: cac: 6.7.14 debug: 4.4.1(supports-color@5.5.0) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - '@types/node' - jiti @@ -11445,29 +11449,29 @@ snapshots: - tsx - yaml - vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)): + vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)): dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.40.2) '@svgr/core': 8.1.0(typescript@5.7.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.7.3)) - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)): + vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.7.3) optionalDependencies: - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - supports-color - typescript - vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3): + vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): dependencies: esbuild: 0.25.4 fdir: 6.4.6(picomatch@4.0.3) @@ -11481,12 +11485,13 @@ snapshots: jiti: 2.5.1 lightningcss: 1.30.1 tsx: 4.20.3 + yaml: 1.10.2 - vitest@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3): + vitest@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -11504,8 +11509,8 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) - vite-node: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite-node: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.16.5 From 684fdc7342dfb1908b967d673e214c2cad8cf96c Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:53:02 +0300 Subject: [PATCH 03/31] fix(package.json): ensure axios dependency is included --- apps/api/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/api/package.json b/apps/api/package.json index 8aeb33f..9319bb7 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -19,6 +19,7 @@ "@prisma/client": "6.11.1", "@tiptap/extension-horizontal-rule": "2.1.13", "adminjs": "^7.8.17", + "axios": "^1.11.0", "better-auth": "^1.2.12", "cors": "^2.8.5", "dotenv": "^17.2.1", From 6ba0573ef174138aa71fc6e43ea1f98c888eb8c9 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:53:24 +0300 Subject: [PATCH 04/31] feat(prisma): add difficulty and attempt tracking to Topic model; set default values for DailyQuiz --- apps/api/prisma/schema.prisma | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index 9f7ec5e..b83210a 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -66,6 +66,10 @@ model Topic { userCompletions UserCompletion[] questions Question[] userPerformances UserTopicPerformance[] + + difficulty QuestionDifficulty @default(easy) + attempted Int @default(0) + solved Int @default(0) } model UserCompletion { @@ -134,6 +138,9 @@ model DailyQuiz { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt submittedAt DateTime? + totalQuestions Int @default(10) + + @@unique([userId, createdAt]) } model User { @@ -226,3 +233,4 @@ model Jwks { @@map("jwks") } + From 6b4575f0c141ce34d455adc7e42266269813eeed Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:53:33 +0300 Subject: [PATCH 05/31] feat(migration): add totalQuestions to DailyQuiz and attempted, difficulty, solved to Topic; create unique index on DailyQuiz --- .../migration.sql | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 apps/api/prisma/migrations/20250813194643_adding_unique_id_quiz/migration.sql diff --git a/apps/api/prisma/migrations/20250813194643_adding_unique_id_quiz/migration.sql b/apps/api/prisma/migrations/20250813194643_adding_unique_id_quiz/migration.sql new file mode 100644 index 0000000..4c2d110 --- /dev/null +++ b/apps/api/prisma/migrations/20250813194643_adding_unique_id_quiz/migration.sql @@ -0,0 +1,16 @@ +/* + Warnings: + + - A unique constraint covering the columns `[userId,createdAt]` on the table `DailyQuiz` will be added. If there are existing duplicate values, this will fail. + +*/ +-- AlterTable +ALTER TABLE "DailyQuiz" ADD COLUMN "totalQuestions" INTEGER NOT NULL DEFAULT 10; + +-- AlterTable +ALTER TABLE "Topic" ADD COLUMN "attempted" INTEGER NOT NULL DEFAULT 0, +ADD COLUMN "difficulty" "QuestionDifficulty" NOT NULL DEFAULT 'easy', +ADD COLUMN "solved" INTEGER NOT NULL DEFAULT 0; + +-- CreateIndex +CREATE UNIQUE INDEX "DailyQuiz_userId_createdAt_key" ON "DailyQuiz"("userId", "createdAt"); From 2c972bbc92031cb2523b3826417e4c169ada899c Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:53:38 +0300 Subject: [PATCH 06/31] chore: update app.ts for improved error handling and middleware configuration --- apps/api/src/app.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index be0dc45..6344954 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -3,13 +3,44 @@ import express from "express"; import { auth } from "./lib/auth.js"; import { toNodeHandler } from "better-auth/node"; import { admin, adminRouter } from "./lib/admin.js"; +import { quizzesRouter } from "./routes/quizzes.js"; const app = express(); +// Basic middleware +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); + app.disable("x-powered-by"); app.all("/api/auth/*", toNodeHandler(auth)); app.use(admin.options.rootPath, adminRouter); console.log(`AdminJS is running under ${admin.options.rootPath}`); +// API routes +app.use("/api/quizzes", quizzesRouter); + +// Simple health route +app.get("/api/health", (_req: express.Request, res: express.Response): void => { + res.json({ status: "ok" }); +}); + +// Error handler +// eslint-disable-next-line @typescript-eslint/no-unused-vars +app.use((( + err: any, + _req: express.Request, + res: express.Response, + _next: express.NextFunction +) => { + console.error("[Error]", err); + if (err?.message === "Unauthorized") { + res.status(401).json({ status: "fail", message: "Unauthorized" }); + return; + } + res + .status(500) + .json({ status: "error", message: err?.message || "Server error" }); +}) as express.ErrorRequestHandler); + export default app; From 34d20013f7ebe8695ec333f7944e0f27cc664622 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:53:45 +0300 Subject: [PATCH 07/31] feat(calendar): implement getQuizSubmissionCalendar to track user quiz submissions by date --- .../api/src/controller/calender.controller.ts | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 apps/api/src/controller/calender.controller.ts diff --git a/apps/api/src/controller/calender.controller.ts b/apps/api/src/controller/calender.controller.ts new file mode 100644 index 0000000..d7b2d15 --- /dev/null +++ b/apps/api/src/controller/calender.controller.ts @@ -0,0 +1,84 @@ +import { Request, Response } from "express"; +import type { Session, User } from "better-auth"; +import { prisma } from "../lib/prisma.js"; + +declare global { + // Ensure session typing just like other controllers + namespace Express { + interface Request { + session?: Session; + user?: User; + } + } +} + +interface ApiResponse { + status: string; + message?: string; + data?: T; +} +const send = (res: Response, code: number, body: ApiResponse) => + res.status(code).json(body); + +// Utility to get month boundaries in local time (00:00:00.000 inclusive to next month start exclusive) +const monthRange = (year: number, month0: number) => { + const start = new Date(year, month0, 1, 0, 0, 0, 0); + const end = new Date(year, month0 + 1, 1, 0, 0, 0, 0); + return { start, end }; +}; + +/** + * Returns an array of booleans (index 0 = day 1) for the requested month indicating + * which days the user submitted a quiz (DailyQuiz.submittedAt not null). + * Query params: year=YYYY, month=1-12 (defaults to current year/month if omitted) + */ +export const getQuizSubmissionCalendar = async ( + req: Request, + res: Response +): Promise => { + if (!req.session) { + send(res, 401, { status: "fail", message: "Unauthorized" }); + return; + } + const userId = req.session.userId; + + // Parse month/year with fallbacks + const now = new Date(); + const year = Number(req.query.year) || now.getFullYear(); + const monthParam = Number(req.query.month); // 1-12 + const month0 = + monthParam && monthParam >= 1 && monthParam <= 12 ? + monthParam - 1 + : now.getMonth(); + + try { + const { start, end } = monthRange(year, month0); + const daysInMonth = new Date(year, month0 + 1, 0).getDate(); + const days: boolean[] = Array(daysInMonth).fill(false); + + const submissions = await prisma.dailyQuiz.findMany({ + where: { + userId, + submittedAt: { not: null, gte: start, lt: end }, + }, + select: { submittedAt: true }, + }); + + for (const s of submissions) { + if (!s.submittedAt) continue; + const day = s.submittedAt.getDate(); // 1-based + if (day >= 1 && day <= daysInMonth) days[day - 1] = true; + } + + send(res, 200, { + status: "success", + data: { year, month: month0 + 1, days }, + }); + } catch (err) { + console.error("[getQuizSubmissionCalendar] error", err); + send(res, 500, { + status: "error", + message: "Failed to fetch calendar", + }); + } +}; From 37f6029be1717bd91208ccacae02d55b617a6c3d Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:53:52 +0300 Subject: [PATCH 08/31] feat(quiz): implement getQuiz and submitQuiz endpoints for quiz management --- apps/api/src/controller/quiz.controller.ts | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 apps/api/src/controller/quiz.controller.ts diff --git a/apps/api/src/controller/quiz.controller.ts b/apps/api/src/controller/quiz.controller.ts new file mode 100644 index 0000000..df66ce1 --- /dev/null +++ b/apps/api/src/controller/quiz.controller.ts @@ -0,0 +1,130 @@ +import { Request, Response } from "express"; +import type { Session, User } from "better-auth"; +import { fetchAiRecommendation } from "../services/ai.service.js"; +import { buildUserQuizData } from "../services/quiz-data.service.js"; +import { fetchQuestionsByRecommendation } from "../services/question.service.js"; +import { + saveOrUpdateDailyQuiz, + findTodayDailyQuiz, +} from "../services/daily-quiz.service.js"; +import { + gradeAnswers, + SubmittedAnswerInput, +} from "../services/quiz-submission.service.js"; +import { updateDailyQuizScoreByUserToday } from "../services/daily-quiz.service.js"; + +declare global { + namespace Express { + interface Request { + session?: Session; + user?: User; + } + } +} + +// Utility helpers ------------------------------------------------------------- +const startOfDay = (d: Date) => + new Date(d.getFullYear(), d.getMonth(), d.getDate()); + +interface ApiResponse { + status: string; + message?: string; + data?: T; +} +const send = (res: Response, code: number, body: ApiResponse) => + res.status(code).json(body); + +export const getQuiz = async (req: Request, res: Response): Promise => { + if (!req.session) { + send(res, 401, { status: "fail", message: "Unauthorized" }); + return; + } + const userId = req.session.userId; + const today = new Date(); + + try { + // Fetch existing quiz (by date range) if any + const existingQuiz = await findTodayDailyQuiz(userId, today); + const totalQuestions = existingQuiz?.totalQuestions || 10; + + // Build data for AI + const quizData = await buildUserQuizData(userId, totalQuestions); + if (!quizData) { + send(res, 404, { + status: "fail", + message: "User hasn't completed any topics yet", + }); + return; + } + + const aiRecommendation = await fetchAiRecommendation(quizData); + const questions = await fetchQuestionsByRecommendation( + aiRecommendation, + totalQuestions + ); + + // Persist / update quiz record (schema only stores counts currently) + const savedQuiz = await saveOrUpdateDailyQuiz( + userId, + startOfDay(today), + totalQuestions + ); + + send(res, 200, { + status: "success", + data: { quiz: savedQuiz, questions, aiRecommendation }, + }); + } catch (err) { + console.error("[getQuiz] error", err); + send(res, 500, { + status: "error", + message: "Failed to generate quiz", + }); + } +}; + +export const submitQuiz = async ( + req: Request, + res: Response +): Promise => { + if (!req.session) { + send(res, 401, { status: "fail", message: "Unauthorized" }); + return; + } + const userId = req.session.userId; + const today = new Date(); + + try { + const { answers } = req.body as { answers: SubmittedAnswerInput[] }; + if (!Array.isArray(answers) || answers.length === 0) { + send(res, 400, { + status: "fail", + message: "answers array required", + }); + return; + } + + const grading = await gradeAnswers(answers); + await updateDailyQuizScoreByUserToday( + userId, + today, + grading.scorePercentage + ); + + send(res, 200, { + status: "success", + data: { + score: grading.scorePercentage, + correctCount: grading.correctCount, + total: grading.total, + answers: grading.graded, + }, + }); + } catch (err) { + console.error("[submitQuiz] error", err); + send(res, 500, { + status: "error", + message: "Failed to submit quiz", + }); + } +}; From 6dd9535ab9da09f19bddb870edf6a09e897aec17 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:53:59 +0300 Subject: [PATCH 09/31] feat(quizzes): implement calendar endpoint for quiz submission tracking --- apps/api/src/routes/quizzes.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/api/src/routes/quizzes.ts b/apps/api/src/routes/quizzes.ts index 06dbcac..44c0f5c 100644 --- a/apps/api/src/routes/quizzes.ts +++ b/apps/api/src/routes/quizzes.ts @@ -1,23 +1,29 @@ import { Router } from "express"; import { validate } from "../middlewares/validate.js"; +import { requireAuth } from "../middlewares/auth.js"; import { submitDailyQuizBodySchema } from "../schemas/quizzes.js"; +import { getQuiz, submitQuiz } from "../controller/quiz.controller.js"; +import { getQuizSubmissionCalendar } from "../controller/calender.controller.js"; const router = Router(); -router.get("/monthly-stats", (req, res) => { - res.send(req.url); -}); +// Calendar of submissions (month view) +router.get( + "/calendar", + requireAuth, + // optional validation for query could be added later + getQuizSubmissionCalendar +); -router.get("/daily", (req, res) => { - res.send(req.url); -}); +// Fetch / (re)generate today's quiz for the user +router.get("/daily", requireAuth, getQuiz); +// Submit answers for today's quiz router.post( "/daily", + requireAuth, validate({ body: submitDailyQuizBodySchema }), - (req, res) => { - res.send(req.url); - }, + submitQuiz ); export { router as quizzesRouter }; From 6a576b97e8c8f45a7113a74d0d396f18181839f8 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:54:05 +0300 Subject: [PATCH 10/31] feat(quizzes): update submitDailyQuizBodySchema to require choiceIndex and remove optional answer field --- apps/api/src/schemas/quizzes.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/api/src/schemas/quizzes.ts b/apps/api/src/schemas/quizzes.ts index 1e6e4e9..226288a 100644 --- a/apps/api/src/schemas/quizzes.ts +++ b/apps/api/src/schemas/quizzes.ts @@ -1,10 +1,12 @@ import z from "zod"; export const submitDailyQuizBodySchema = z.object({ - answers: z.array( - z.object({ - questionId: z.string().uuid(), - answer: z.string().optional(), - }), - ), + answers: z + .array( + z.object({ + questionId: z.string().uuid(), + choiceIndex: z.number().int().min(0), + }) + ) + .min(1), }); From 1eeb191bf470a64764ff8653a63bfcb79de66359 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:54:09 +0300 Subject: [PATCH 11/31] feat(ai): add fetchAiRecommendation function for AI-based quiz recommendations --- apps/api/src/services/ai.service.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 apps/api/src/services/ai.service.ts diff --git a/apps/api/src/services/ai.service.ts b/apps/api/src/services/ai.service.ts new file mode 100644 index 0000000..12848a9 --- /dev/null +++ b/apps/api/src/services/ai.service.ts @@ -0,0 +1,14 @@ +import axios from "axios"; + +export const fetchAiRecommendation = async (quizData: any) => { + try { + const response = await axios.post( + "http://localhost:5000/api/data", + quizData + ); + return response.data; + } catch (err) { + console.error("AI Recommendation error:", err); + throw new Error("Failed to get AI recommendation"); + } +}; From 04377644af417fa13eb17e99255ee9f1ee507a4a Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:54:14 +0300 Subject: [PATCH 12/31] feat(daily-quiz): implement daily quiz service with CRUD operations --- apps/api/src/services/daily-quiz.service.ts | 67 +++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 apps/api/src/services/daily-quiz.service.ts diff --git a/apps/api/src/services/daily-quiz.service.ts b/apps/api/src/services/daily-quiz.service.ts new file mode 100644 index 0000000..c24acf7 --- /dev/null +++ b/apps/api/src/services/daily-quiz.service.ts @@ -0,0 +1,67 @@ +// Local prisma client +import { prisma } from "../lib/prisma.js"; + +const startOfDay = (d: Date) => + new Date(d.getFullYear(), d.getMonth(), d.getDate()); +const nextDay = (d: Date) => + new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1); + +export const findTodayDailyQuiz = async ( + userId: string, + refDate = new Date() +) => { + return prisma.dailyQuiz.findFirst({ + where: { + userId, + createdAt: { gte: startOfDay(refDate), lt: nextDay(refDate) }, + }, + orderBy: { createdAt: "desc" }, + }); +}; + +export const createDailyQuiz = async ( + userId: string, + totalQuestions: number +) => { + return prisma.dailyQuiz.create({ + data: { userId, totalQuestions, score: 0 }, + }); +}; + +export const saveOrUpdateDailyQuiz = async ( + userId: string, + refDate: Date, + totalQuestions: number +) => { + const existing = await findTodayDailyQuiz(userId, refDate); + if (existing) { + if (existing.totalQuestions !== totalQuestions) { + return prisma.dailyQuiz.update({ + where: { id: existing.id }, + data: { totalQuestions }, + }); + } + return existing; + } + return createDailyQuiz(userId, totalQuestions); +}; + +export const submitDailyQuiz = async (quizId: string, score: number) => { + return prisma.dailyQuiz.update({ + where: { id: quizId }, + data: { score, submittedAt: new Date() }, + }); +}; + +export const updateDailyQuizScoreByUserToday = async ( + userId: string, + refDate: Date, + score: number +) => { + const quiz = await findTodayDailyQuiz(userId, refDate); + if (!quiz) return null; + return prisma.dailyQuiz.update({ + where: { id: quiz.id }, + data: { score, submittedAt: new Date() }, + }); +}; From 1f6b5e2066061130cbc9d4a1644c5fb4bfbd8f44 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:54:18 +0300 Subject: [PATCH 13/31] feat(questions): add fetchQuestionsByRecommendation function to retrieve questions based on AI recommendations --- apps/api/src/services/question.service.ts | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 apps/api/src/services/question.service.ts diff --git a/apps/api/src/services/question.service.ts b/apps/api/src/services/question.service.ts new file mode 100644 index 0000000..db3f88b --- /dev/null +++ b/apps/api/src/services/question.service.ts @@ -0,0 +1,25 @@ +import { prisma } from "../lib/prisma.js"; + +export const fetchQuestionsByRecommendation = async ( + aiRecommendation: any, + totalQuestions: number +) => { + const levelsToFetch = aiRecommendation.topics.flatMap((topic: any) => + topic.recommendations.map((rec: any) => rec.level) + ); + + return prisma.question.findMany({ + where: { + topics: { + some: { + course: { + level: { + title: { in: levelsToFetch.map((lvl: number) => `Level ${lvl}`) }, + }, + }, + }, + }, + }, + take: totalQuestions, + }); +}; From 81440cda306ac1960ae3d25d4a186bdd01b79141 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:54:21 +0300 Subject: [PATCH 14/31] feat(quiz-data): implement buildUserQuizData function to aggregate user quiz topics and progress --- apps/api/src/services/quiz-data.service.ts | 97 ++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 apps/api/src/services/quiz-data.service.ts diff --git a/apps/api/src/services/quiz-data.service.ts b/apps/api/src/services/quiz-data.service.ts new file mode 100644 index 0000000..a29e4a1 --- /dev/null +++ b/apps/api/src/services/quiz-data.service.ts @@ -0,0 +1,97 @@ +import { prisma } from "../lib/prisma.js"; + +export const buildUserQuizData = async ( + userId: string, + totalQuestions: number +) => { + const user = await prisma.user.findUnique({ + where: { id: userId }, + include: { + userCompletions: { + include: { + topic: { + include: { + course: { include: { level: true } }, + questions: true, + }, + }, + }, + }, + }, + }); + + const userCompletions = user?.userCompletions; + if (!userCompletions || userCompletions.length === 0) { + return null; + } + + const topicMap = new Map< + string, + { topic: string; available: { level: number; count: number }[] } + >(); + const progressMap = new Map< + string, + { + topic: string; + progressByLevel: { level: number; solved: number; attempted: number }[]; + } + >(); + + for (const completion of userCompletions) { + const topic = completion.topic; + const course = topic.course; + const levelNumber = parseInt(course.level.title.match(/\d+/)?.[0] || "0"); + + // Build userTopics + if (!topicMap.has(topic.title)) { + topicMap.set(topic.title, { + topic: topic.title, + available: [{ level: levelNumber, count: topic.questions.length }], + }); + } else { + const available = topicMap.get(topic.title)!.available; + const levelEntry = available.find((a) => a.level === levelNumber); + if (levelEntry) { + levelEntry.count += topic.questions.length; + } else { + available.push({ level: levelNumber, count: topic.questions.length }); + } + } + + // Build userProgress + if (!progressMap.has(topic.title)) { + progressMap.set(topic.title, { + topic: topic.title, + progressByLevel: [ + { + level: levelNumber, + solved: topic.solved, + attempted: topic.attempted, + }, + ], + }); + } else { + const progressByLevel = progressMap.get(topic.title)!.progressByLevel; + const progressEntry = progressByLevel.find( + (p) => p.level === levelNumber + ); + if (progressEntry) { + progressEntry.solved += topic.solved; + progressEntry.attempted += topic.attempted; + } else { + progressByLevel.push({ + level: levelNumber, + solved: topic.solved, + attempted: topic.attempted, + }); + } + } + } + + return { + userId, + totalQuestions, + userTopics: Array.from(topicMap.values()), + userProgress: Array.from(progressMap.values()), + }; +}; From 88371c7d221d5cf7aaea786a7c18550d6931fca9 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Wed, 13 Aug 2025 22:54:25 +0300 Subject: [PATCH 15/31] feat(quiz-submission): add gradeAnswers function to evaluate quiz submissions and calculate scores --- .../src/services/quiz-submission.service.ts | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 apps/api/src/services/quiz-submission.service.ts diff --git a/apps/api/src/services/quiz-submission.service.ts b/apps/api/src/services/quiz-submission.service.ts new file mode 100644 index 0000000..fab58a5 --- /dev/null +++ b/apps/api/src/services/quiz-submission.service.ts @@ -0,0 +1,75 @@ +import { prisma } from "../lib/prisma.js"; + +export interface SubmittedAnswerInput { + questionId: string; + choiceIndex: number; +} + +export interface GradedAnswerResult { + questionId: string; + userChoiceIndex: number | null; + correctOptionIndex: number; + isCorrect: boolean; +} + +export interface GradeQuizResult { + graded: GradedAnswerResult[]; + correctCount: number; + total: number; + scorePercentage: number; // 0-100 +} + +/** + * Grades a batch of answers. Missing or invalid questions are ignored but still counted toward total if they existed in input. + */ +export const gradeAnswers = async ( + answers: SubmittedAnswerInput[] +): Promise => { + // Dedupe by questionId (keep last answer provided by user) + const map = new Map(); + for (const a of answers) { + if (a && a.questionId) map.set(a.questionId, a); + } + const uniqueAnswers = Array.from(map.values()); + if (uniqueAnswers.length === 0) { + return { graded: [], correctCount: 0, total: 0, scorePercentage: 0 }; + } + + const questionIds = uniqueAnswers.map((a) => a.questionId); + const questions = await prisma.question.findMany({ + where: { id: { in: questionIds } }, + select: { id: true, correctOptionIndex: true }, + }); + const questionMap = new Map< + string, + { id: string; correctOptionIndex: number } + >( + questions.map((q: { id: string; correctOptionIndex: number }) => [q.id, q]) + ); + + const graded: GradedAnswerResult[] = uniqueAnswers.map((a) => { + const q = questionMap.get(a.questionId); + if (!q) { + return { + questionId: a.questionId, + userChoiceIndex: a.choiceIndex ?? null, + correctOptionIndex: -1, + isCorrect: false, + }; + } + const isCorrect = a.choiceIndex === q.correctOptionIndex; + return { + questionId: q.id, + userChoiceIndex: a.choiceIndex ?? null, + correctOptionIndex: q.correctOptionIndex, + isCorrect, + }; + }); + + const correctCount = graded.filter((g) => g.isCorrect).length; + const total = graded.length; + const scorePercentage = + total === 0 ? 0 : +((correctCount / total) * 100).toFixed(2); + + return { graded, correctCount, total, scorePercentage }; +}; From 08b00d99276b46eda127c192d33ffa742ad8d69b Mon Sep 17 00:00:00 2001 From: ahmed elgaml Date: Sat, 16 Aug 2025 05:25:13 +0300 Subject: [PATCH 16/31] implement the user-topic completion feature and add the essential functions for courses and topics and tracks with server-side validation and aplly authntication middleware --- apps/api/src/app.ts | 3 +- apps/api/src/routes/courses.ts | 67 ++++++++++++++++++++++++++++++++ apps/api/src/routes/index.ts | 17 ++++++++ apps/api/src/routes/topics.ts | 40 +++++++++++++++++++ apps/api/src/routes/tracks.ts | 60 ++++++++++++++++++++++++++++ apps/api/src/schemas/courses.ts | 9 +++++ apps/api/src/schemas/topics.ts | 5 +++ apps/api/src/schemas/tracks.ts | 8 ++++ apps/api/src/services/courses.ts | 61 +++++++++++++++++++++++++++++ apps/api/src/services/topics.ts | 54 +++++++++++++++++++++++++ apps/api/src/services/tracks.ts | 25 ++++++++++++ 11 files changed, 348 insertions(+), 1 deletion(-) create mode 100644 apps/api/src/routes/courses.ts create mode 100644 apps/api/src/routes/index.ts create mode 100644 apps/api/src/routes/topics.ts create mode 100644 apps/api/src/routes/tracks.ts create mode 100644 apps/api/src/schemas/courses.ts create mode 100644 apps/api/src/schemas/topics.ts create mode 100644 apps/api/src/schemas/tracks.ts create mode 100644 apps/api/src/services/courses.ts create mode 100644 apps/api/src/services/topics.ts create mode 100644 apps/api/src/services/tracks.ts diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index be0dc45..c79443c 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -3,7 +3,7 @@ import express from "express"; import { auth } from "./lib/auth.js"; import { toNodeHandler } from "better-auth/node"; import { admin, adminRouter } from "./lib/admin.js"; - +import api from "./routes/index.js"; const app = express(); app.disable("x-powered-by"); @@ -11,5 +11,6 @@ app.disable("x-powered-by"); app.all("/api/auth/*", toNodeHandler(auth)); app.use(admin.options.rootPath, adminRouter); console.log(`AdminJS is running under ${admin.options.rootPath}`); +app.use("/api", api); export default app; diff --git a/apps/api/src/routes/courses.ts b/apps/api/src/routes/courses.ts new file mode 100644 index 0000000..2bc4bd6 --- /dev/null +++ b/apps/api/src/routes/courses.ts @@ -0,0 +1,67 @@ +import exprees from "express"; +const router = exprees.Router(); +import { requireAuth } from "../middlewares/auth.js"; +import { validate } from "../middlewares/validate.js"; +import { + getCourseParamsSchema, + getCourseQuerySchema, +} from "../schemas/courses.js"; +import * as Service from "../services/courses.js"; +import * as topicService from "../services/topics.js"; + +router.get( + "/:courseId", + requireAuth, + validate({ params: getCourseParamsSchema }), + async (req, res) => { + const course = await Service.getCourse(req.params.courseId); + + const totalTopics = await Service.getToltalTopics(req.params.courseId); + + const completedTopics = await Service.getCompletedTopics( + req.user!.id, + req.params.courseId, + ); + const persentage = (completedTopics.length / totalTopics.length) * 100; + + res.status(200).json({ + course, + totalTopics, + persentage, + }); + }, +); +router.get( + "/:courseId/topics", + requireAuth, + validate({ params: getCourseParamsSchema, query: getCourseQuerySchema }), + async (req, res) => { + const { completed } = req.query; + + const totalTopics = await topicService.getToltalTopics(req.params.courseId); + + const completedTopics = await topicService.getCompletedTopics( + req.user!.id, + req.params.courseId, + ); + + let filterdTopics; + if (completed === "true") { + filterdTopics = completedTopics; + } else if (completed === "false") { + const completedTopicsIds = completedTopics.map((ele) => ele.topic.id); + const unCompletedTopics = totalTopics.filter( + (ele) => !completedTopicsIds.includes(ele.id), + ); + filterdTopics = unCompletedTopics; + } else { + filterdTopics = totalTopics; + } + + res.status(200).json({ + filterdTopics, + }); + }, +); + +export { router as coursesRouter }; diff --git a/apps/api/src/routes/index.ts b/apps/api/src/routes/index.ts new file mode 100644 index 0000000..a66cad7 --- /dev/null +++ b/apps/api/src/routes/index.ts @@ -0,0 +1,17 @@ +import express from "express"; +const router = express.Router(); +import { tracksRouter } from "./tracks.js"; +import { coursesRouter } from "./courses.js"; +import { topicsRouter } from "./topics.js"; + +router.get("/", (req, res) => { + res.status(200).json({ + message: "hello from api.", + }); +}); + +router.use("/tracks", tracksRouter); +router.use("/courses", coursesRouter); +router.use("/topics", topicsRouter); + +export default router; diff --git a/apps/api/src/routes/topics.ts b/apps/api/src/routes/topics.ts new file mode 100644 index 0000000..d56f2e3 --- /dev/null +++ b/apps/api/src/routes/topics.ts @@ -0,0 +1,40 @@ +import exprees from "express"; +const router = exprees.Router(); +import { validate } from "../middlewares/validate.js"; +import { getTopicParamsSchema } from "../schemas/topics.js"; +import * as Service from "../services/topics.js"; +import { requireAuth } from "../middlewares/auth.js"; + +router.get( + "/:topicId", + validate({ params: getTopicParamsSchema }), + async (req, res) => { + const topic = await Service.getTopic(req.params.topicId); + + res.status(200).json({ + topic, + }); + }, +); +router.post( + "/:topicId/completion", + requireAuth, + validate({ params: getTopicParamsSchema }), + async (req, res) => { + const topic = await Service.completeTopic(req.user!.id, req.params.topicId); + res.status(201).json({ + topic, + }); + }, +); +router.delete( + "/:topicId/completion", + requireAuth, + validate({ params: getTopicParamsSchema }), + async (req, res) => { + await Service.inCompleteTopic(req.user!.id, req.params.topicId); + res.status(204).json({}); + }, +); + +export { router as topicsRouter }; diff --git a/apps/api/src/routes/tracks.ts b/apps/api/src/routes/tracks.ts new file mode 100644 index 0000000..9776dc9 --- /dev/null +++ b/apps/api/src/routes/tracks.ts @@ -0,0 +1,60 @@ +import exprees from "express"; +const router = exprees.Router(); +import { Prisma } from "../generated/prisma/client.js"; +import { validate } from "../middlewares/validate.js"; +import { + getTrackQuerySchema, + getTrackParamsSchema, +} from "../schemas/tracks.js"; +import * as Service from "../services/tracks.js"; +import { requireAuth } from "../middlewares/auth.js"; +import * as courseSrvice from "../services/courses.js"; + +router.get("/", async (req, res) => { + const tracks = await Service.getAllTracks(); + + res.status(200).json({ + length: tracks.length, + data: tracks, + }); +}); +router.get( + "/:trackId", + requireAuth, + validate({ params: getTrackParamsSchema, query: getTrackQuerySchema }), + async (req, res) => { + const { levelId } = req.query as { levelId: string }; + const track = await Service.getTrack(req.params.trackId); + + const courses = await courseSrvice.getCourses( + levelId, + req.params.trackId, + req.user!.id, + ); + const progress = courses.map( + ( + course: Prisma.CourseGetPayload<{ + include: { topics: { select: { userCompletions: true } } }; + }>, + ) => { + const totalTopics = course.topics.length; + const completedTopics = course.topics.filter( + (topic) => topic.userCompletions.length > 0, + ).length; + const percentage = (completedTopics / totalTopics) * 100; + + return { + id: course.id, + title: course.title, + percentage, + }; + }, + ); + res.status(200).json({ + track, + courses: progress, + }); + }, +); + +export { router as tracksRouter }; diff --git a/apps/api/src/schemas/courses.ts b/apps/api/src/schemas/courses.ts new file mode 100644 index 0000000..3571e3c --- /dev/null +++ b/apps/api/src/schemas/courses.ts @@ -0,0 +1,9 @@ +import z from "zod"; + +export const getCourseParamsSchema = z.object({ + courseId: z.string().min(1, "courseId is required"), +}); + +export const getCourseQuerySchema = z.object({ + completed: z.string().optional(), +}); diff --git a/apps/api/src/schemas/topics.ts b/apps/api/src/schemas/topics.ts new file mode 100644 index 0000000..0a34e09 --- /dev/null +++ b/apps/api/src/schemas/topics.ts @@ -0,0 +1,5 @@ +import z from "zod"; + +export const getTopicParamsSchema = z.object({ + topicId: z.string().min(1, "topicId is required"), +}); diff --git a/apps/api/src/schemas/tracks.ts b/apps/api/src/schemas/tracks.ts new file mode 100644 index 0000000..8130adb --- /dev/null +++ b/apps/api/src/schemas/tracks.ts @@ -0,0 +1,8 @@ +import z from "zod"; + +export const getTrackParamsSchema = z.object({ + trackId: z.string().min(1, "trackId is required"), +}); +export const getTrackQuerySchema = z.object({ + levelId: z.string().optional(), +}); diff --git a/apps/api/src/services/courses.ts b/apps/api/src/services/courses.ts new file mode 100644 index 0000000..065b1b0 --- /dev/null +++ b/apps/api/src/services/courses.ts @@ -0,0 +1,61 @@ +import { prisma } from "../lib/prisma.js"; + +export const getCourse = async (courseId: string) => { + return await prisma.course.findUnique({ + where: { + id: courseId, + }, + }); +}; + +export const getToltalTopics = async (courseId: string) => { + return await prisma.topic.findMany({ + where: { + courseId, + }, + select: { + title: true, + }, + orderBy: { + order: "asc", + }, + }); +}; + +export const getCompletedTopics = async (userId: string, courseId: string) => { + return await prisma.userCompletion.findMany({ + where: { + userId, + topic: { + courseId, + }, + }, + }); +}; + +export const getCourses = async ( + levelId: string, + trackId: string, + userId: string, +) => { + return await prisma.course.findMany({ + where: { + trackId, + ...(levelId && { levelId }), + }, + orderBy: { + order: "asc", + }, + include: { + topics: { + select: { + userCompletions: { + where: { + userId, + }, + }, + }, + }, + }, + }); +}; diff --git a/apps/api/src/services/topics.ts b/apps/api/src/services/topics.ts new file mode 100644 index 0000000..c42b5c0 --- /dev/null +++ b/apps/api/src/services/topics.ts @@ -0,0 +1,54 @@ +import { prisma } from "../lib/prisma.js"; + +export const getTopic = async (topicId: string) => { + return prisma.topic.findUnique({ + where: { + id: topicId, + }, + select: { + title: true, + durationInMinutes: true, + content: true, + }, + }); +}; + +export const completeTopic = async (userId: string, topicId: string) => { + return await prisma.userCompletion.create({ + data: { + userId, + topicId, + }, + }); +}; +export const inCompleteTopic = async (userId: string, topicId: string) => { + prisma.userCompletion.delete({ + where: { + userId_topicId: { userId, topicId }, + }, + }); +}; + +export const getToltalTopics = async (courseId: string) => { + return await prisma.topic.findMany({ + where: { + courseId, + }, + orderBy: { + order: "asc", + }, + }); +}; +export const getCompletedTopics = async (userId: string, courseId: string) => { + return await prisma.userCompletion.findMany({ + where: { + userId, + topic: { + courseId, + }, + }, + include: { + topic: true, + }, + }); +}; diff --git a/apps/api/src/services/tracks.ts b/apps/api/src/services/tracks.ts new file mode 100644 index 0000000..2c9c858 --- /dev/null +++ b/apps/api/src/services/tracks.ts @@ -0,0 +1,25 @@ +import { prisma } from "../lib/prisma.js"; + +export const getAllTracks = async () => { + const tracks = await prisma.track.findMany({ + select: { + id: true, + title: true, + }, + }); + return tracks; +}; + +export const getTrack = async (trackId: string) => { + const track = await prisma.track.findUnique({ + where: { + id: trackId, + }, + select: { + id: true, + title: true, + description: true, + }, + }); + return track; +}; From 790354d45ddc32f7f7aaf5c1aa5a815c15262ec1 Mon Sep 17 00:00:00 2001 From: Elshahaby Date: Sat, 16 Aug 2025 19:31:45 +0300 Subject: [PATCH 17/31] feat(api): implement notes feature Adds full CRUD functionality for user notes, including advanced filtering, sorting, and pagination. --- .../migration.sql | 22 +++ apps/api/prisma/schema.prisma | 20 +++ apps/api/src/app.ts | 4 +- apps/api/src/errors/not-found.ts | 12 ++ apps/api/src/routes/notes.ts | 95 +++++++++++ apps/api/src/schemas/notes.ts | 97 +++++++++++ apps/api/src/services/notes.ts | 155 ++++++++++++++++++ 7 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 apps/api/prisma/migrations/20250815080928_add_notes_model/migration.sql create mode 100644 apps/api/src/errors/not-found.ts create mode 100644 apps/api/src/routes/notes.ts create mode 100644 apps/api/src/schemas/notes.ts create mode 100644 apps/api/src/services/notes.ts diff --git a/apps/api/prisma/migrations/20250815080928_add_notes_model/migration.sql b/apps/api/prisma/migrations/20250815080928_add_notes_model/migration.sql new file mode 100644 index 0000000..6d8bc9b --- /dev/null +++ b/apps/api/prisma/migrations/20250815080928_add_notes_model/migration.sql @@ -0,0 +1,22 @@ +-- CreateTable +CREATE TABLE "Note" ( + "id" TEXT NOT NULL, + "title" TEXT NOT NULL, + "content" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "userId" TEXT NOT NULL, + "topicId" TEXT NOT NULL, + "courseId" TEXT NOT NULL, + + CONSTRAINT "Note_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "Note" ADD CONSTRAINT "Note_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Note" ADD CONSTRAINT "Note_topicId_fkey" FOREIGN KEY ("topicId") REFERENCES "Topic"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Note" ADD CONSTRAINT "Note_courseId_fkey" FOREIGN KEY ("courseId") REFERENCES "Course"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index 9f7ec5e..14c4e60 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -49,6 +49,7 @@ model Course { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt topics Topic[] + notes Note[] } model Topic { @@ -66,6 +67,24 @@ model Topic { userCompletions UserCompletion[] questions Question[] userPerformances UserTopicPerformance[] + notes Note[] +} + +model Note { + id String @id @default(cuid()) + title String + content String @db.Text + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // --- Relations --- + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + topicId String + topic Topic @relation(fields: [topicId], references: [id], onDelete: Cascade) + courseId String + course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) } model UserCompletion { @@ -158,6 +177,7 @@ model User { trackId String? joinedTrack Track? @relation(fields: [trackId], references: [id], onDelete: Cascade, name: "joinedTrack") userCompletions UserCompletion[] + notes Note[] // Instructors createdTracks Track[] diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index be0dc45..84f9736 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -3,13 +3,15 @@ import express from "express"; import { auth } from "./lib/auth.js"; import { toNodeHandler } from "better-auth/node"; import { admin, adminRouter } from "./lib/admin.js"; +import { notesRouter } from "./routes/notes.js"; const app = express(); - app.disable("x-powered-by"); app.all("/api/auth/*", toNodeHandler(auth)); app.use(admin.options.rootPath, adminRouter); console.log(`AdminJS is running under ${admin.options.rootPath}`); +app.use(express.json()); +app.use(notesRouter); export default app; diff --git a/apps/api/src/errors/not-found.ts b/apps/api/src/errors/not-found.ts new file mode 100644 index 0000000..e2157bd --- /dev/null +++ b/apps/api/src/errors/not-found.ts @@ -0,0 +1,12 @@ +import BaseError from "./base.js"; + +export class NotFoundError extends BaseError { + constructor(hint?: string) { + super( + "Not Found: Ensure the requested resource exists.", + 404, + undefined, + hint, + ); + } +} diff --git a/apps/api/src/routes/notes.ts b/apps/api/src/routes/notes.ts new file mode 100644 index 0000000..1cad568 --- /dev/null +++ b/apps/api/src/routes/notes.ts @@ -0,0 +1,95 @@ +import { Router } from "express"; +import { validate } from "../middlewares/validate.js"; +import { + createNote, + deleteNote, + getAllFilteredNotes, + getNoteById, + updateNote, +} from "../services/notes.js"; +import { + CreateNoteBodySchema, + GetAllNotesQuerySchema, + noteIdSchema, + topicIdSchema, + UpdateNoteBodySchema, +} from "../schemas/notes.js"; +import { requireAuth } from "../middlewares/auth.js"; + +const router = Router(); + +router.use(requireAuth); + +router.get( + "/api/notes/:noteId", + validate({ params: noteIdSchema }), + async (req, res) => { + const { noteId } = req.params; + const response = await getNoteById(noteId, req.user!.id); + res.status(200).json({ + status: "success", + data: response, + }); + }, +); + +router.get( + "/api/notes", + validate({ query: GetAllNotesQuerySchema }), + async (req, res) => { + const response = await getAllFilteredNotes(req.user!.id, req.query); + res.status(200).json({ + status: "success", + pagination: response.pagination, + data: response.data, + }); + }, +); + +router.post( + "/api/topics/:topicId/notes", + validate({ params: topicIdSchema, body: CreateNoteBodySchema }), + async (req, res) => { + const { topicId } = req.params; + const { title, content } = req.body; + const response = await createNote( + { title, content }, + topicId, + req.user!.id, + ); + res.status(201).json({ + status: "success", + data: response, + }); + }, +); + +router.put( + "/api/notes/:noteId", + validate({ params: noteIdSchema, body: UpdateNoteBodySchema }), + async (req, res) => { + const { noteId } = req.params; + const { title, content } = req.body; + + const response = await updateNote(noteId, req.user!.id, { title, content }); + res.status(200).json({ + status: "success", + data: response, + }); + }, +); + +router.delete( + "/api/notes/:noteId", + validate({ params: noteIdSchema }), + async (req, res) => { + const { noteId } = req.params; + await deleteNote(noteId, req.user!.id); + res.status(204).json({ + status: "success", + message: "Note deleted successfully.", + }); + }, +); + +export { router as notesRouter }; diff --git a/apps/api/src/schemas/notes.ts b/apps/api/src/schemas/notes.ts new file mode 100644 index 0000000..3bbbcf3 --- /dev/null +++ b/apps/api/src/schemas/notes.ts @@ -0,0 +1,97 @@ +import z from "zod"; + +export const CreateNoteBodySchema = z.object({ + title: z + .string() + .trim() + .min(1, { message: "Title is required and must be at least 1 character." }), + content: z + .string() + .trim() + .min(1, { + message: "Content is required and must be at least 1 character.", + }), +}); + +export const NoteSchema = z.object({ + id: z.string().cuid({ message: "id must be a valid CUID." }), + title: z.string().min(1, { message: "Title must be at least 1 character." }), + content: z + .string() + .min(1, { message: "Content must be at least 1 character." }), + topicId: z.string().cuid({ message: "topicId must be a valid CUID." }), + userId: z.string().cuid({ message: "userId must be a valid CUID." }), + courseId: z.string().cuid({ message: "courseId must be a valid CUID." }), + createdAt: z.date({ message: "createdAt must be a valid date." }), + updatedAt: z.date({ message: "updatedAt must be a valid date." }), +}); + +export const UpdateNoteBodySchema = z.object({ + title: z + .string() + .trim() + .min(1, { message: "Title must be at least 1 character." }) + .optional(), + content: z + .string() + .trim() + .min(1, { message: "Content must be at least 1 character." }) + .optional(), +}); + +// valitate query string +const validSortFields = [ + "title", + "-title", + "createdAt", + "-createdAt", + "updatedAt", + "-updatedAt", +]; + +export const GetAllNotesQuerySchema = z.object({ + courseId: z + .string() + .cuid({ message: "courseId must be a valid CUID." }) + .optional(), + topicId: z + .string() + .cuid({ message: "topicId must be a valid CUID." }) + .optional(), + search: z.string().optional(), + sort: z + .string() + .refine( + (value) => { + // Ensure every comma-separated value is in whitelist + return value + .split(",") + .every((field) => validSortFields.includes(field)); + }, + { message: `Invalid sort field.` }, + ) + .optional(), + page: z.coerce + .number({ message: "page must be an number." }) + .int({ message: "page must be an integer." }) + .min(1, { message: "page must be at least 1." }) + .default(1), + limit: z.coerce + .number({ message: "limit must be an number." }) + .int({ message: "limit must be an integer." }) + .min(1, { message: "limit must be at least 1." }) + .default(10), +}); + +// valitate params +export const topicIdSchema = z.object({ + topicId: z.string().trim().cuid({ message: "id must be a valid CUID." }), +}); +export const noteIdSchema = z.object({ + noteId: z.string().trim().cuid({ message: "id must be a valid CUID." }), +}); + +export type NoteServiceType = z.infer; +export type UpdateNoteServiceType = z.infer; +export type CreateNoteBodyType = z.infer; +export type GetAllNotesQueryType = z.infer; diff --git a/apps/api/src/services/notes.ts b/apps/api/src/services/notes.ts new file mode 100644 index 0000000..2f0d3e7 --- /dev/null +++ b/apps/api/src/services/notes.ts @@ -0,0 +1,155 @@ +import { NotFoundError } from "../errors/not-found.js"; +import PermissionDenied from "../errors/permission-denied.js"; +import { Note, Prisma } from "../generated/prisma/client.js"; +import { Not } from "../generated/prisma/internal/prismaNamespace.js"; +import { prisma } from "../lib/prisma.js"; +import { + CreateNoteBodyType, + GetAllNotesQueryType, + NoteServiceType, + UpdateNoteServiceType, +} from "../schemas/notes.js"; + +interface PaginatedNotesResult { + pagination: { + totalNotes: number; + totalPages: number; + currentPage: number; + limit: number; + }; + data: NoteServiceType[]; +} + +export async function createNote( + input: CreateNoteBodyType, + topicId: string, + userId: string, +): Promise { + const topic = await prisma.topic.findUnique({ + where: { id: topicId }, + select: { courseId: true }, + }); + + if (!topic) { + throw new NotFoundError(); + } + + const createdNote = await prisma.note.create({ + data: { + title: input.title, + content: input.content, + topicId, + userId, + courseId: topic.courseId, + }, + }); + + return createdNote; +} + +export async function getNoteById( + noteId: string, + userId: string, +): Promise { + const note = await prisma.note.findFirst({ + where: { + id: noteId, + userId: userId, // Authorization check + }, + }); + + if (!note) { + throw new NotFoundError(); + } + + return note; +} + +export async function updateNote( + noteId: string, + userId: string, + data: UpdateNoteServiceType, +): Promise { + const note = await prisma.note.findFirst({ + where: { + id: noteId, + userId: userId, + }, + }); + + if (!note) { + throw new NotFoundError(); + } + + const updatedNote = await prisma.note.update({ + where: { id: noteId }, + data, + }); + + return updatedNote; +} + +export async function deleteNote( + noteId: string, + userId: string, +): Promise { + const note = await prisma.note.findFirst({ + where: { + id: noteId, + userId: userId, + }, + }); + + if (!note) { + throw new NotFoundError(); + } + + await prisma.note.delete({ where: { id: noteId } }); +} + +export async function getAllFilteredNotes( + userId: string, + query: GetAllNotesQueryType, +): Promise { + const { courseId, topicId, search, sort, page, limit } = query; + + const where: Prisma.NoteWhereInput = { userId }; + if (topicId) { + where.topicId = topicId; + } else if (courseId) { + where.courseId = courseId; + } + if (search) { + where.OR = [ + { title: { contains: search, mode: "insensitive" } }, + { content: { contains: search, mode: "insensitive" } }, + ]; + } + + // default sorting by updatedAt desc + let orderBy: Prisma.NoteOrderByWithRelationInput[] = [{ updatedAt: "desc" }]; + if (sort) { + orderBy = sort.split(",").map((field) => { + const direction = field.startsWith("-") ? "desc" : "asc"; + const fieldName = field.replace(/^-/, ""); + return { [fieldName]: direction }; + }); + } + + const skip = (page - 1) * limit; + + const [notes, totalCount] = await prisma.$transaction([ + prisma.note.findMany({ where, orderBy, skip, take: limit }), + prisma.note.count({ where }), + ]); + + return { + pagination: { + totalNotes: totalCount, + totalPages: Math.ceil(totalCount / limit), + currentPage: page, + limit, + }, + data: notes, + }; +} From f6ded3d92d343b193e34c457319dcd14bceec6cd Mon Sep 17 00:00:00 2001 From: Elshahaby Date: Sat, 16 Aug 2025 20:40:43 +0300 Subject: [PATCH 18/31] fix(api): correct linting and formatting in note schemas --- apps/api/src/schemas/notes.ts | 17 ++++++----------- apps/api/src/services/notes.ts | 4 +--- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/apps/api/src/schemas/notes.ts b/apps/api/src/schemas/notes.ts index 3bbbcf3..37944d6 100644 --- a/apps/api/src/schemas/notes.ts +++ b/apps/api/src/schemas/notes.ts @@ -5,12 +5,9 @@ export const CreateNoteBodySchema = z.object({ .string() .trim() .min(1, { message: "Title is required and must be at least 1 character." }), - content: z - .string() - .trim() - .min(1, { - message: "Content is required and must be at least 1 character.", - }), + content: z.string().trim().min(1, { + message: "Content is required and must be at least 1 character.", + }), }); export const NoteSchema = z.object({ @@ -40,14 +37,14 @@ export const UpdateNoteBodySchema = z.object({ }); // valitate query string -const validSortFields = [ +const validSortFields = new Set([ "title", "-title", "createdAt", "-createdAt", "updatedAt", "-updatedAt", -]; +]); export const GetAllNotesQuerySchema = z.object({ courseId: z @@ -64,9 +61,7 @@ export const GetAllNotesQuerySchema = z.object({ .refine( (value) => { // Ensure every comma-separated value is in whitelist - return value - .split(",") - .every((field) => validSortFields.includes(field)); + return value.split(",").every((field) => validSortFields.has(field)); }, { message: `Invalid sort field.` }, ) diff --git a/apps/api/src/services/notes.ts b/apps/api/src/services/notes.ts index 2f0d3e7..913eb93 100644 --- a/apps/api/src/services/notes.ts +++ b/apps/api/src/services/notes.ts @@ -1,7 +1,5 @@ import { NotFoundError } from "../errors/not-found.js"; -import PermissionDenied from "../errors/permission-denied.js"; -import { Note, Prisma } from "../generated/prisma/client.js"; -import { Not } from "../generated/prisma/internal/prismaNamespace.js"; +import { Prisma } from "../generated/prisma/client.js"; import { prisma } from "../lib/prisma.js"; import { CreateNoteBodyType, From d6850961dc7c6f46b712088877b0f1de5468fa0d Mon Sep 17 00:00:00 2001 From: ahmed elgaml Date: Sun, 17 Aug 2025 00:19:16 +0300 Subject: [PATCH 19/31] replace the completed course array with set --- apps/api/src/routes/courses.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/api/src/routes/courses.ts b/apps/api/src/routes/courses.ts index 2bc4bd6..6414a44 100644 --- a/apps/api/src/routes/courses.ts +++ b/apps/api/src/routes/courses.ts @@ -45,13 +45,15 @@ router.get( req.params.courseId, ); + // const completedTopicsSet = new Set(completedTopics) let filterdTopics; if (completed === "true") { filterdTopics = completedTopics; } else if (completed === "false") { - const completedTopicsIds = completedTopics.map((ele) => ele.topic.id); + const completedTopicsIdsSet = new Set(); + completedTopics.forEach((ele) => completedTopicsIdsSet.add(ele)); const unCompletedTopics = totalTopics.filter( - (ele) => !completedTopicsIds.includes(ele.id), + (ele) => !completedTopicsIdsSet.has(ele.id), ); filterdTopics = unCompletedTopics; } else { From 73359422286583dc1b7c10861817dd91681c60fd Mon Sep 17 00:00:00 2001 From: ahmed elgaml Date: Sun, 17 Aug 2025 00:37:49 +0300 Subject: [PATCH 20/31] replace the forEach with for of --- apps/api/src/routes/courses.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/api/src/routes/courses.ts b/apps/api/src/routes/courses.ts index 6414a44..b831ef3 100644 --- a/apps/api/src/routes/courses.ts +++ b/apps/api/src/routes/courses.ts @@ -45,15 +45,16 @@ router.get( req.params.courseId, ); - // const completedTopicsSet = new Set(completedTopics) let filterdTopics; if (completed === "true") { filterdTopics = completedTopics; } else if (completed === "false") { - const completedTopicsIdsSet = new Set(); - completedTopics.forEach((ele) => completedTopicsIdsSet.add(ele)); + const completedTopicsIds = new Set(); + for (const topic of completedTopics) { + completedTopicsIds.add(topic.id); + } const unCompletedTopics = totalTopics.filter( - (ele) => !completedTopicsIdsSet.has(ele.id), + (ele) => !completedTopicsIds.has(ele.id), ); filterdTopics = unCompletedTopics; } else { From a60b30f428a5f35f0ea3bcc4be8838df5c1c8b4b Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Tue, 19 Aug 2025 22:46:08 +0300 Subject: [PATCH 21/31] feat(daily-quiz): add quizDate field and update unique constraint for DailyQuiz model --- apps/api/prisma/schema.prisma | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index b83210a..2454dea 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -139,8 +139,9 @@ model DailyQuiz { updatedAt DateTime @updatedAt submittedAt DateTime? totalQuestions Int @default(10) + quizDate DateTime // Should be set to the date (midnight) of the quiz, without time component - @@unique([userId, createdAt]) + @@unique([userId, quizDate]) } model User { From 498b256403f8ea2d0d0f0c168c7d05854b14677f Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Tue, 19 Aug 2025 22:46:13 +0300 Subject: [PATCH 22/31] feat(calendar): implement getQuizSubmissionCalendar function to retrieve quiz submission days for a given month --- .../api/src/controller/calendar.controller.ts | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 apps/api/src/controller/calendar.controller.ts diff --git a/apps/api/src/controller/calendar.controller.ts b/apps/api/src/controller/calendar.controller.ts new file mode 100644 index 0000000..d7b2d15 --- /dev/null +++ b/apps/api/src/controller/calendar.controller.ts @@ -0,0 +1,84 @@ +import { Request, Response } from "express"; +import type { Session, User } from "better-auth"; +import { prisma } from "../lib/prisma.js"; + +declare global { + // Ensure session typing just like other controllers + namespace Express { + interface Request { + session?: Session; + user?: User; + } + } +} + +interface ApiResponse { + status: string; + message?: string; + data?: T; +} +const send = (res: Response, code: number, body: ApiResponse) => + res.status(code).json(body); + +// Utility to get month boundaries in local time (00:00:00.000 inclusive to next month start exclusive) +const monthRange = (year: number, month0: number) => { + const start = new Date(year, month0, 1, 0, 0, 0, 0); + const end = new Date(year, month0 + 1, 1, 0, 0, 0, 0); + return { start, end }; +}; + +/** + * Returns an array of booleans (index 0 = day 1) for the requested month indicating + * which days the user submitted a quiz (DailyQuiz.submittedAt not null). + * Query params: year=YYYY, month=1-12 (defaults to current year/month if omitted) + */ +export const getQuizSubmissionCalendar = async ( + req: Request, + res: Response +): Promise => { + if (!req.session) { + send(res, 401, { status: "fail", message: "Unauthorized" }); + return; + } + const userId = req.session.userId; + + // Parse month/year with fallbacks + const now = new Date(); + const year = Number(req.query.year) || now.getFullYear(); + const monthParam = Number(req.query.month); // 1-12 + const month0 = + monthParam && monthParam >= 1 && monthParam <= 12 ? + monthParam - 1 + : now.getMonth(); + + try { + const { start, end } = monthRange(year, month0); + const daysInMonth = new Date(year, month0 + 1, 0).getDate(); + const days: boolean[] = Array(daysInMonth).fill(false); + + const submissions = await prisma.dailyQuiz.findMany({ + where: { + userId, + submittedAt: { not: null, gte: start, lt: end }, + }, + select: { submittedAt: true }, + }); + + for (const s of submissions) { + if (!s.submittedAt) continue; + const day = s.submittedAt.getDate(); // 1-based + if (day >= 1 && day <= daysInMonth) days[day - 1] = true; + } + + send(res, 200, { + status: "success", + data: { year, month: month0 + 1, days }, + }); + } catch (err) { + console.error("[getQuizSubmissionCalendar] error", err); + send(res, 500, { + status: "error", + message: "Failed to fetch calendar", + }); + } +}; From 4960098e21f68f4895cf44f17d2be73e6ae5672e Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Tue, 19 Aug 2025 22:46:18 +0300 Subject: [PATCH 23/31] feat(calendar): remove getQuizSubmissionCalendar function and associated code --- .../api/src/controller/calender.controller.ts | 84 ------------------- 1 file changed, 84 deletions(-) delete mode 100644 apps/api/src/controller/calender.controller.ts diff --git a/apps/api/src/controller/calender.controller.ts b/apps/api/src/controller/calender.controller.ts deleted file mode 100644 index d7b2d15..0000000 --- a/apps/api/src/controller/calender.controller.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Request, Response } from "express"; -import type { Session, User } from "better-auth"; -import { prisma } from "../lib/prisma.js"; - -declare global { - // Ensure session typing just like other controllers - namespace Express { - interface Request { - session?: Session; - user?: User; - } - } -} - -interface ApiResponse { - status: string; - message?: string; - data?: T; -} -const send = (res: Response, code: number, body: ApiResponse) => - res.status(code).json(body); - -// Utility to get month boundaries in local time (00:00:00.000 inclusive to next month start exclusive) -const monthRange = (year: number, month0: number) => { - const start = new Date(year, month0, 1, 0, 0, 0, 0); - const end = new Date(year, month0 + 1, 1, 0, 0, 0, 0); - return { start, end }; -}; - -/** - * Returns an array of booleans (index 0 = day 1) for the requested month indicating - * which days the user submitted a quiz (DailyQuiz.submittedAt not null). - * Query params: year=YYYY, month=1-12 (defaults to current year/month if omitted) - */ -export const getQuizSubmissionCalendar = async ( - req: Request, - res: Response -): Promise => { - if (!req.session) { - send(res, 401, { status: "fail", message: "Unauthorized" }); - return; - } - const userId = req.session.userId; - - // Parse month/year with fallbacks - const now = new Date(); - const year = Number(req.query.year) || now.getFullYear(); - const monthParam = Number(req.query.month); // 1-12 - const month0 = - monthParam && monthParam >= 1 && monthParam <= 12 ? - monthParam - 1 - : now.getMonth(); - - try { - const { start, end } = monthRange(year, month0); - const daysInMonth = new Date(year, month0 + 1, 0).getDate(); - const days: boolean[] = Array(daysInMonth).fill(false); - - const submissions = await prisma.dailyQuiz.findMany({ - where: { - userId, - submittedAt: { not: null, gte: start, lt: end }, - }, - select: { submittedAt: true }, - }); - - for (const s of submissions) { - if (!s.submittedAt) continue; - const day = s.submittedAt.getDate(); // 1-based - if (day >= 1 && day <= daysInMonth) days[day - 1] = true; - } - - send(res, 200, { - status: "success", - data: { year, month: month0 + 1, days }, - }); - } catch (err) { - console.error("[getQuizSubmissionCalendar] error", err); - send(res, 500, { - status: "error", - message: "Failed to fetch calendar", - }); - } -}; From 3f812642e76b8f234ac1bdc502687a7c6d921ea9 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Tue, 19 Aug 2025 22:46:24 +0300 Subject: [PATCH 24/31] fix(quizzes): correct import path for getQuizSubmissionCalendar function --- apps/api/src/routes/quizzes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/src/routes/quizzes.ts b/apps/api/src/routes/quizzes.ts index 44c0f5c..986ae87 100644 --- a/apps/api/src/routes/quizzes.ts +++ b/apps/api/src/routes/quizzes.ts @@ -3,7 +3,7 @@ import { validate } from "../middlewares/validate.js"; import { requireAuth } from "../middlewares/auth.js"; import { submitDailyQuizBodySchema } from "../schemas/quizzes.js"; import { getQuiz, submitQuiz } from "../controller/quiz.controller.js"; -import { getQuizSubmissionCalendar } from "../controller/calender.controller.js"; +import { getQuizSubmissionCalendar } from "../controller/calendar.controller.js"; const router = Router(); From 309a7e2395108e9a4c1a78fd593ee1e0be3453e9 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Tue, 19 Aug 2025 22:46:31 +0300 Subject: [PATCH 25/31] chore(ai.service): no code changes made --- apps/api/src/services/ai.service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/api/src/services/ai.service.ts b/apps/api/src/services/ai.service.ts index 12848a9..f37d205 100644 --- a/apps/api/src/services/ai.service.ts +++ b/apps/api/src/services/ai.service.ts @@ -2,8 +2,9 @@ import axios from "axios"; export const fetchAiRecommendation = async (quizData: any) => { try { + const aiApiUrl = process.env.AI_API_URL || "http://localhost:5000/api/data"; const response = await axios.post( - "http://localhost:5000/api/data", + aiApiUrl, quizData ); return response.data; From ffd1bbe9eef09d31d3f775322e8ba662d42bd9d1 Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Tue, 19 Aug 2025 22:46:45 +0300 Subject: [PATCH 26/31] fix(quiz-submission): replace hardcoded value with constant for invalid question index --- apps/api/src/services/quiz-submission.service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/api/src/services/quiz-submission.service.ts b/apps/api/src/services/quiz-submission.service.ts index fab58a5..f957198 100644 --- a/apps/api/src/services/quiz-submission.service.ts +++ b/apps/api/src/services/quiz-submission.service.ts @@ -19,6 +19,8 @@ export interface GradeQuizResult { scorePercentage: number; // 0-100 } +const INVALID_QUESTION_INDEX = -1; + /** * Grades a batch of answers. Missing or invalid questions are ignored but still counted toward total if they existed in input. */ @@ -53,7 +55,7 @@ export const gradeAnswers = async ( return { questionId: a.questionId, userChoiceIndex: a.choiceIndex ?? null, - correctOptionIndex: -1, + correctOptionIndex: INVALID_QUESTION_INDEX, isCorrect: false, }; } From fc0686b2e1724226ae73e16c14498cbadeea909c Mon Sep 17 00:00:00 2001 From: NaderMohamed325 Date: Tue, 19 Aug 2025 22:47:41 +0300 Subject: [PATCH 27/31] feat(migration): add quizDate column and unique constraint to DailyQuiz table --- .../20250819194732_adding_quiz_date/migration.sql | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 apps/api/prisma/migrations/20250819194732_adding_quiz_date/migration.sql diff --git a/apps/api/prisma/migrations/20250819194732_adding_quiz_date/migration.sql b/apps/api/prisma/migrations/20250819194732_adding_quiz_date/migration.sql new file mode 100644 index 0000000..0171224 --- /dev/null +++ b/apps/api/prisma/migrations/20250819194732_adding_quiz_date/migration.sql @@ -0,0 +1,15 @@ +/* + Warnings: + + - A unique constraint covering the columns `[userId,quizDate]` on the table `DailyQuiz` will be added. If there are existing duplicate values, this will fail. + - Added the required column `quizDate` to the `DailyQuiz` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropIndex +DROP INDEX "DailyQuiz_userId_createdAt_key"; + +-- AlterTable +ALTER TABLE "DailyQuiz" ADD COLUMN "quizDate" TIMESTAMP(3) NOT NULL; + +-- CreateIndex +CREATE UNIQUE INDEX "DailyQuiz_userId_quizDate_key" ON "DailyQuiz"("userId", "quizDate"); From 2992d226fbb6cd86c537048a8065b50b1f0580e7 Mon Sep 17 00:00:00 2001 From: Seif El-Din Sweilam Date: Sat, 30 Aug 2025 19:34:11 +0300 Subject: [PATCH 28/31] Refactor API structure and add Postman collection - Restructured routes and controllers - Added comprehensive Postman collection with all API endpoints - Removed deprecated controller files - Added new service files for better organization - Updated schemas and middleware --- OpenLearnPlatform-API.postman_collection.json | 1071 +++++++++++++++++ apps/api/eslint.config.mjs | 1 + apps/api/package.json | 2 +- .../migration.sql | 12 + apps/api/prisma/schema.prisma | 5 - apps/api/src/app.ts | 12 +- .../api/src/controller/calendar.controller.ts | 84 -- apps/api/src/controller/quiz.controller.ts | 130 -- apps/api/src/errors/already-submitted-quiz.ts | 12 + apps/api/src/errors/not-enough-topics.ts | 12 + apps/api/src/helpers/dates.ts | 11 + apps/api/src/middlewares/auth.ts | 7 +- apps/api/src/middlewares/enhanced-send.ts | 28 + apps/api/src/router.ts | 14 + apps/api/src/routes/courses.ts | 40 +- apps/api/src/routes/index.ts | 17 - apps/api/src/routes/notes.ts | 62 +- apps/api/src/routes/quizzes.ts | 75 +- apps/api/src/routes/topics.ts | 30 +- apps/api/src/routes/tracks.ts | 52 +- apps/api/src/schemas/courses.ts | 2 +- apps/api/src/schemas/notes.ts | 17 - apps/api/src/schemas/pagination.ts | 6 + apps/api/src/schemas/quizzes.ts | 22 +- apps/api/src/services/ai.service.ts | 15 - apps/api/src/services/courses.ts | 19 +- apps/api/src/services/daily-quiz.service.ts | 67 -- apps/api/src/services/notes.ts | 28 +- .../{question.service.ts => questions.ts} | 8 +- apps/api/src/services/quiz-data.service.ts | 97 -- .../src/services/quiz-submission.service.ts | 77 -- apps/api/src/services/quizzes.ts | 182 +++ apps/api/src/services/recommendations.ts | 13 + apps/api/src/services/topics.ts | 30 +- pnpm-lock.yaml | 80 +- 35 files changed, 1614 insertions(+), 726 deletions(-) create mode 100644 OpenLearnPlatform-API.postman_collection.json create mode 100644 apps/api/prisma/migrations/20250821101109_remove_performance_records_from_topic/migration.sql delete mode 100644 apps/api/src/controller/calendar.controller.ts delete mode 100644 apps/api/src/controller/quiz.controller.ts create mode 100644 apps/api/src/errors/already-submitted-quiz.ts create mode 100644 apps/api/src/errors/not-enough-topics.ts create mode 100644 apps/api/src/helpers/dates.ts create mode 100644 apps/api/src/middlewares/enhanced-send.ts create mode 100644 apps/api/src/router.ts delete mode 100644 apps/api/src/routes/index.ts create mode 100644 apps/api/src/schemas/pagination.ts delete mode 100644 apps/api/src/services/ai.service.ts delete mode 100644 apps/api/src/services/daily-quiz.service.ts rename apps/api/src/services/{question.service.ts => questions.ts} (64%) delete mode 100644 apps/api/src/services/quiz-data.service.ts delete mode 100644 apps/api/src/services/quiz-submission.service.ts create mode 100644 apps/api/src/services/quizzes.ts create mode 100644 apps/api/src/services/recommendations.ts diff --git a/OpenLearnPlatform-API.postman_collection.json b/OpenLearnPlatform-API.postman_collection.json new file mode 100644 index 0000000..aa1d9f2 --- /dev/null +++ b/OpenLearnPlatform-API.postman_collection.json @@ -0,0 +1,1071 @@ +{ + "info": { + "name": "OpenLearnPlatform API", + "description": "Complete API collection for OpenLearnPlatform with authentication, tracks, courses, topics, notes, and quizzes endpoints", + "version": "1.0.0", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "variable": [ + { + "key": "base_url", + "value": "http://localhost:3000", + "type": "string" + }, + { + "key": "api_prefix", + "value": "/api", + "type": "string" + }, + { + "key": "auth_token", + "value": "", + "type": "string" + } + ], + "item": [ + { + "name": "Tracks", + "item": [ + { + "name": "Get All Tracks", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/tracks", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "tracks"] + }, + "description": "Retrieve all available learning tracks" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/tracks", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "tracks"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": [\n {\n \"id\": \"track_1\",\n \"name\": \"Frontend Development\",\n \"description\": \"Learn modern frontend technologies\",\n \"icon\": \"frontend-icon.svg\",\n \"createdAt\": \"2024-01-01T00:00:00.000Z\",\n \"updatedAt\": \"2024-01-01T00:00:00.000Z\"\n }\n ]\n}" + } + ] + }, + { + "name": "Get Track by ID", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/tracks/:trackId?levelId=beginner", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "tracks", ":trackId"], + "query": [ + { + "key": "levelId", + "value": "beginner", + "description": "Optional filter by level" + } + ], + "variable": [ + { + "key": "trackId", + "value": "track_1", + "description": "Track identifier (required)" + } + ] + }, + "description": "Get specific track with its courses, optionally filtered by level" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/tracks/track_1?levelId=beginner", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "tracks", "track_1"], + "query": [ + { + "key": "levelId", + "value": "beginner" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"id\": \"track_1\",\n \"name\": \"Frontend Development\",\n \"description\": \"Learn modern frontend technologies\",\n \"icon\": \"frontend-icon.svg\",\n \"courses\": [\n {\n \"id\": \"course_1\",\n \"name\": \"HTML Basics\",\n \"description\": \"Introduction to HTML\",\n \"level\": \"beginner\"\n }\n ]\n }\n}" + } + ] + } + ], + "description": "Learning tracks management" + }, + { + "name": "Courses", + "item": [ + { + "name": "Get Course by ID", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/courses/:courseId", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "courses", ":courseId"], + "variable": [ + { + "key": "courseId", + "value": "course_1", + "description": "Course identifier (required)" + } + ] + }, + "description": "Get course details with topics and completion percentage" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/courses/course_1", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "courses", "course_1"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"id\": \"course_1\",\n \"name\": \"HTML Basics\",\n \"description\": \"Introduction to HTML\",\n \"level\": \"beginner\",\n \"topics\": [\n {\n \"id\": \"topic_1\",\n \"name\": \"HTML Elements\",\n \"content\": \"Learn about HTML elements\"\n }\n ],\n \"completedPercentage\": 75.5\n }\n}" + } + ] + }, + { + "name": "Get Course Topics", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/courses/:courseId/topics?completed=true", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "courses", ":courseId", "topics"], + "query": [ + { + "key": "completed", + "value": "true", + "description": "Filter by completion status (true/false)" + } + ], + "variable": [ + { + "key": "courseId", + "value": "course_1", + "description": "Course identifier (required)" + } + ] + }, + "description": "Get all topics for a course, optionally filtered by completion status" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/courses/course_1/topics?completed=true", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "courses", "course_1", "topics"], + "query": [ + { + "key": "completed", + "value": "true" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": [\n {\n \"id\": \"topic_1\",\n \"name\": \"HTML Elements\",\n \"content\": \"Learn about HTML elements\",\n \"completed\": true,\n \"completedAt\": \"2024-08-25T10:00:00.000Z\"\n }\n ]\n}" + } + ] + } + ], + "description": "Course management and topic tracking" + }, + { + "name": "Topics", + "item": [ + { + "name": "Get Topic by ID", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/topics/:topicId", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "topics", ":topicId"], + "variable": [ + { + "key": "topicId", + "value": "topic_1", + "description": "Topic identifier (required)" + } + ] + }, + "description": "Get detailed information about a specific topic" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/topics/topic_1", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "topics", "topic_1"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"id\": \"topic_1\",\n \"name\": \"HTML Elements\",\n \"content\": \"Learn about HTML elements and their structure\",\n \"courseId\": \"course_1\",\n \"order\": 1,\n \"completed\": false,\n \"createdAt\": \"2024-01-01T00:00:00.000Z\",\n \"updatedAt\": \"2024-01-01T00:00:00.000Z\"\n }\n}" + } + ] + }, + { + "name": "Mark Topic as Completed", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/topics/:topicId/completion", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "topics", ":topicId", "completion"], + "variable": [ + { + "key": "topicId", + "value": "topic_1", + "description": "Topic identifier (required)" + } + ] + }, + "description": "Mark a topic as completed for the authenticated user" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "POST", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/topics/topic_1/completion", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "topics", "topic_1", "completion"] + } + }, + "status": "Created", + "code": 201, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 201,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"id\": \"completion_1\",\n \"userId\": \"user_123\",\n \"topicId\": \"topic_1\",\n \"completedAt\": \"2024-08-30T10:00:00.000Z\"\n }\n}" + } + ] + }, + { + "name": "Unmark Topic as Completed", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/topics/:topicId/completion", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "topics", ":topicId", "completion"], + "variable": [ + { + "key": "topicId", + "value": "topic_1", + "description": "Topic identifier (required)" + } + ] + }, + "description": "Remove completion status from a topic for the authenticated user" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/topics/topic_1/completion", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "topics", "topic_1", "completion"] + } + }, + "status": "No Content", + "code": 204, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 204,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": null\n}" + } + ] + } + ], + "description": "Topic completion tracking" + }, + { + "name": "Notes", + "item": [ + { + "name": "Get All Notes", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes?courseId=course_1&topicId=topic_1&search=html&sort=createdAt,-title&page=1&limit=10", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes"], + "query": [ + { + "key": "courseId", + "value": "course_1", + "description": "Filter by course ID (CUID)" + }, + { + "key": "topicId", + "value": "topic_1", + "description": "Filter by topic ID (CUID)" + }, + { + "key": "search", + "value": "html", + "description": "Search in title and content" + }, + { + "key": "sort", + "value": "createdAt,-title", + "description": "Sort fields (title, -title, createdAt, -createdAt, updatedAt, -updatedAt)" + }, + { + "key": "page", + "value": "1", + "description": "Page number (default: 1)" + }, + { + "key": "limit", + "value": "10", + "description": "Items per page (default: 10)" + } + ] + }, + "description": "Get all notes for the authenticated user with filtering, searching, sorting, and pagination" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes?page=1&limit=10", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes"], + "query": [ + { + "key": "page", + "value": "1" + }, + { + "key": "limit", + "value": "10" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": [\n {\n \"id\": \"note_1\",\n \"title\": \"HTML Elements Notes\",\n \"content\": \"Important points about HTML elements...\",\n \"topicId\": \"topic_1\",\n \"userId\": \"user_123\",\n \"createdAt\": \"2024-08-30T10:00:00.000Z\",\n \"updatedAt\": \"2024-08-30T10:00:00.000Z\"\n }\n ],\n \"pagination\": {\n \"totalItems\": 25,\n \"totalPages\": 3,\n \"currentPage\": 1,\n \"itemsPerPage\": 10\n }\n}" + } + ] + }, + { + "name": "Get Note by ID", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes/:noteId", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes", ":noteId"], + "variable": [ + { + "key": "noteId", + "value": "note_1", + "description": "Note identifier (CUID, required)" + } + ] + }, + "description": "Get a specific note by its ID" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes/note_1", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes", "note_1"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"id\": \"note_1\",\n \"title\": \"HTML Elements Notes\",\n \"content\": \"Important points about HTML elements and their structure...\",\n \"topicId\": \"topic_1\",\n \"userId\": \"user_123\",\n \"createdAt\": \"2024-08-30T10:00:00.000Z\",\n \"updatedAt\": \"2024-08-30T10:00:00.000Z\"\n }\n}" + } + ] + }, + { + "name": "Create Note", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\": \"My HTML Notes\",\n \"content\": \"These are my notes about HTML elements and their usage.\",\n \"topicId\": \"clabcd1234567890abcdef12\"\n}" + }, + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes"] + }, + "description": "Create a new note for a specific topic" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\": \"My HTML Notes\",\n \"content\": \"These are my notes about HTML elements and their usage.\",\n \"topicId\": \"clabcd1234567890abcdef12\"\n}" + }, + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes"] + } + }, + "status": "Created", + "code": 201, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 201,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"id\": \"clnew1234567890abcdef12\",\n \"title\": \"My HTML Notes\",\n \"content\": \"These are my notes about HTML elements and their usage.\",\n \"topicId\": \"clabcd1234567890abcdef12\",\n \"userId\": \"user_123\",\n \"createdAt\": \"2024-08-30T10:00:00.000Z\",\n \"updatedAt\": \"2024-08-30T10:00:00.000Z\"\n }\n}" + } + ] + }, + { + "name": "Update Note", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\": \"Updated HTML Notes\",\n \"content\": \"Updated content about HTML elements with more details.\"\n}" + }, + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes/:noteId", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes", ":noteId"], + "variable": [ + { + "key": "noteId", + "value": "note_1", + "description": "Note identifier (CUID, required)" + } + ] + }, + "description": "Update an existing note (title and/or content are optional)" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"title\": \"Updated HTML Notes\",\n \"content\": \"Updated content about HTML elements with more details.\"\n}" + }, + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes/note_1", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes", "note_1"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"id\": \"note_1\",\n \"title\": \"Updated HTML Notes\",\n \"content\": \"Updated content about HTML elements with more details.\",\n \"topicId\": \"topic_1\",\n \"userId\": \"user_123\",\n \"createdAt\": \"2024-08-30T09:00:00.000Z\",\n \"updatedAt\": \"2024-08-30T10:00:00.000Z\"\n }\n}" + } + ] + }, + { + "name": "Delete Note", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes/:noteId", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes", ":noteId"], + "variable": [ + { + "key": "noteId", + "value": "note_1", + "description": "Note identifier (CUID, required)" + } + ] + }, + "description": "Delete a note permanently" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/notes/note_1", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "notes", "note_1"] + } + }, + "status": "No Content", + "code": 204, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 204,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": null\n}" + } + ] + } + ], + "description": "User notes management with full CRUD operations" + }, + { + "name": "Quizzes", + "item": [ + { + "name": "Get Quiz Calendar", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/calendar?month=8&year=2024", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "calendar"], + "query": [ + { + "key": "month", + "value": "8", + "description": "Month (1-12, optional - defaults to current month)" + }, + { + "key": "year", + "value": "2024", + "description": "Year (2000-2100, optional - defaults to current year)" + } + ] + }, + "description": "Get calendar view of quiz submissions for a specific month and year" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/calendar?month=8&year=2024", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "calendar"], + "query": [ + { + "key": "month", + "value": "8" + }, + { + "key": "year", + "value": "2024" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"year\": 2024,\n \"month\": 8,\n \"days\": [\n {\n \"day\": 1,\n \"hasSubmission\": true,\n \"score\": 85.5\n },\n {\n \"day\": 2,\n \"hasSubmission\": false,\n \"score\": null\n },\n {\n \"day\": 30,\n \"hasSubmission\": true,\n \"score\": 92.0\n }\n ]\n }\n}" + } + ] + }, + { + "name": "Get Daily Quiz", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/daily", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "daily"] + }, + "description": "Get or generate today's quiz for the authenticated user. If already submitted, returns AlreadySubmittedQuiz error." + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/daily", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "daily"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"quiz\": {\n \"id\": \"quiz_123\",\n \"userId\": \"user_123\",\n \"date\": \"2024-08-30T00:00:00.000Z\",\n \"totalQuestions\": 10,\n \"submittedAt\": null,\n \"score\": null\n },\n \"questions\": [\n {\n \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"question\": \"What does HTML stand for?\",\n \"choices\": [\n \"Hypertext Markup Language\",\n \"High Tech Modern Language\",\n \"Home Tool Markup Language\",\n \"Hyperlink and Text Markup Language\"\n ],\n \"difficulty\": \"beginner\",\n \"topic\": \"HTML Basics\"\n }\n ],\n \"aiRecommendation\": {\n \"recommendedTopics\": [\n {\n \"topic\": \"HTML Basics\",\n \"difficulty\": \"beginner\",\n \"count\": 5\n },\n {\n \"topic\": \"CSS Fundamentals\",\n \"difficulty\": \"beginner\",\n \"count\": 3\n }\n ],\n \"reasoning\": \"Based on your progress, focusing on HTML basics will strengthen your foundation.\"\n }\n }\n}" + }, + { + "name": "Already Submitted Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/daily", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "daily"] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": false,\n \"statusCode\": 400,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"error\": {\n \"name\": \"AlreadySubmittedQuiz\",\n \"message\": \"You have already submitted today's quiz\"\n }\n}" + }, + { + "name": "Not Enough Topics Error", + "originalRequest": { + "method": "GET", + "header": [], + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/daily", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "daily"] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": false,\n \"statusCode\": 400,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"error\": {\n \"name\": \"NotEnoughTopics\",\n \"message\": \"Not enough completed topics to generate quiz\"\n }\n}" + } + ] + }, + { + "name": "Submit Daily Quiz", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{auth_token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"answers\": [\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"choiceIndex\": 0\n },\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"choiceIndex\": 2\n },\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440002\",\n \"choiceIndex\": 1\n }\n ]\n}" + }, + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/daily", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "daily"] + }, + "description": "Submit answers for today's daily quiz" + }, + "response": [ + { + "name": "Success Response", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"answers\": [\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"choiceIndex\": 0\n },\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"choiceIndex\": 2\n },\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440002\",\n \"choiceIndex\": 1\n }\n ]\n}" + }, + "url": { + "raw": "{{base_url}}{{api_prefix}}/quizzes/daily", + "host": ["{{base_url}}"], + "path": ["{{api_prefix}}", "quizzes", "daily"] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"success\": true,\n \"statusCode\": 200,\n \"timestamp\": \"2024-08-30T10:00:00.000Z\",\n \"data\": {\n \"score\": 86.7,\n \"correctCount\": 8,\n \"total\": 10,\n \"answers\": [\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"choiceIndex\": 0,\n \"isCorrect\": true,\n \"correctChoiceIndex\": 0,\n \"explanation\": \"HTML stands for Hypertext Markup Language\"\n },\n {\n \"questionId\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"choiceIndex\": 2,\n \"isCorrect\": false,\n \"correctChoiceIndex\": 1,\n \"explanation\": \"The correct answer is CSS stands for Cascading Style Sheets\"\n }\n ]\n }\n}" + } + ] + } + ], + "description": "Daily quiz system with AI-powered question generation and progress tracking" + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "// Check if auth_token is set, if not, remind user to authenticate", + "const authToken = pm.collectionVariables.get('auth_token');", + "if (!authToken && pm.request.auth && pm.request.auth.type === 'bearer') {", + " console.log('⚠️ Authentication token not set. Please sign in first or set the auth_token variable.');", + "}" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "// Test for successful responses", + "pm.test('Status code is success', function () {", + " pm.expect(pm.response.code).to.be.oneOf([200, 201, 204]);", + "});", + "", + "// Test response structure", + "if (pm.response.code !== 204) {", + " pm.test('Response has required structure', function () {", + " const jsonData = pm.response.json();", + " pm.expect(jsonData).to.have.property('success');", + " pm.expect(jsonData).to.have.property('statusCode');", + " pm.expect(jsonData).to.have.property('timestamp');", + " pm.expect(jsonData).to.have.property('data');", + " });", + "}", + "", + "// Auth token can be set manually in collection variables", + "// Set 'auth_token' variable with your authentication token" + ], + "type": "text/javascript" + } + } + ] +} diff --git a/apps/api/eslint.config.mjs b/apps/api/eslint.config.mjs index bd60cb9..6d12476 100644 --- a/apps/api/eslint.config.mjs +++ b/apps/api/eslint.config.mjs @@ -29,6 +29,7 @@ export default [ "sonarjs/no-hardcoded-passwords": "off", "sonarjs/cors": "off", "@typescript-eslint/no-namespace": "off", + "unicorn/no-useless-undefined": "off", }, languageOptions: { globals: globals.node, diff --git a/apps/api/package.json b/apps/api/package.json index 9319bb7..96f8545 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -25,7 +25,7 @@ "dotenv": "^17.2.1", "express": "^4.21.2", "express-async-errors": "^3.1.1", - "zod": "^3.24.3" + "zod": "^4.0.17" }, "devDependencies": { "@better-auth/cli": "^1.2.12", diff --git a/apps/api/prisma/migrations/20250821101109_remove_performance_records_from_topic/migration.sql b/apps/api/prisma/migrations/20250821101109_remove_performance_records_from_topic/migration.sql new file mode 100644 index 0000000..b20c7c9 --- /dev/null +++ b/apps/api/prisma/migrations/20250821101109_remove_performance_records_from_topic/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `attempted` on the `Topic` table. All the data in the column will be lost. + - You are about to drop the column `difficulty` on the `Topic` table. All the data in the column will be lost. + - You are about to drop the column `solved` on the `Topic` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Topic" DROP COLUMN "attempted", +DROP COLUMN "difficulty", +DROP COLUMN "solved"; diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index f2bee33..e14ca02 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -68,11 +68,6 @@ model Topic { questions Question[] userPerformances UserTopicPerformance[] - - difficulty QuestionDifficulty @default(easy) - attempted Int @default(0) - solved Int @default(0) - notes Note[] } diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index 4a6274d..2e46f5d 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -3,22 +3,20 @@ import express from "express"; import { auth } from "./lib/auth.js"; import { toNodeHandler } from "better-auth/node"; import { admin, adminRouter } from "./lib/admin.js"; -import { quizzesRouter } from "./routes/quizzes.js"; -import api from "./routes/index.js"; -import { notesRouter } from "./routes/notes.js"; +import { router, ROUTES_PREFIX } from "./router.js"; +import { addEnhancedSendMethod } from "./middlewares/enhanced-send.js"; const app = express(); app.disable("x-powered-by"); app.all("/api/auth/*", toNodeHandler(auth)); + app.use(admin.options.rootPath, adminRouter); console.log(`AdminJS is running under ${admin.options.rootPath}`); app.use(express.json()); +app.use(addEnhancedSendMethod); -app.use(notesRouter); -app.use("/api", api); -app.use("/api/quizzes", quizzesRouter); - +app.use(ROUTES_PREFIX, router); export default app; diff --git a/apps/api/src/controller/calendar.controller.ts b/apps/api/src/controller/calendar.controller.ts deleted file mode 100644 index d7b2d15..0000000 --- a/apps/api/src/controller/calendar.controller.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { Request, Response } from "express"; -import type { Session, User } from "better-auth"; -import { prisma } from "../lib/prisma.js"; - -declare global { - // Ensure session typing just like other controllers - namespace Express { - interface Request { - session?: Session; - user?: User; - } - } -} - -interface ApiResponse { - status: string; - message?: string; - data?: T; -} -const send = (res: Response, code: number, body: ApiResponse) => - res.status(code).json(body); - -// Utility to get month boundaries in local time (00:00:00.000 inclusive to next month start exclusive) -const monthRange = (year: number, month0: number) => { - const start = new Date(year, month0, 1, 0, 0, 0, 0); - const end = new Date(year, month0 + 1, 1, 0, 0, 0, 0); - return { start, end }; -}; - -/** - * Returns an array of booleans (index 0 = day 1) for the requested month indicating - * which days the user submitted a quiz (DailyQuiz.submittedAt not null). - * Query params: year=YYYY, month=1-12 (defaults to current year/month if omitted) - */ -export const getQuizSubmissionCalendar = async ( - req: Request, - res: Response -): Promise => { - if (!req.session) { - send(res, 401, { status: "fail", message: "Unauthorized" }); - return; - } - const userId = req.session.userId; - - // Parse month/year with fallbacks - const now = new Date(); - const year = Number(req.query.year) || now.getFullYear(); - const monthParam = Number(req.query.month); // 1-12 - const month0 = - monthParam && monthParam >= 1 && monthParam <= 12 ? - monthParam - 1 - : now.getMonth(); - - try { - const { start, end } = monthRange(year, month0); - const daysInMonth = new Date(year, month0 + 1, 0).getDate(); - const days: boolean[] = Array(daysInMonth).fill(false); - - const submissions = await prisma.dailyQuiz.findMany({ - where: { - userId, - submittedAt: { not: null, gte: start, lt: end }, - }, - select: { submittedAt: true }, - }); - - for (const s of submissions) { - if (!s.submittedAt) continue; - const day = s.submittedAt.getDate(); // 1-based - if (day >= 1 && day <= daysInMonth) days[day - 1] = true; - } - - send(res, 200, { - status: "success", - data: { year, month: month0 + 1, days }, - }); - } catch (err) { - console.error("[getQuizSubmissionCalendar] error", err); - send(res, 500, { - status: "error", - message: "Failed to fetch calendar", - }); - } -}; diff --git a/apps/api/src/controller/quiz.controller.ts b/apps/api/src/controller/quiz.controller.ts deleted file mode 100644 index df66ce1..0000000 --- a/apps/api/src/controller/quiz.controller.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { Request, Response } from "express"; -import type { Session, User } from "better-auth"; -import { fetchAiRecommendation } from "../services/ai.service.js"; -import { buildUserQuizData } from "../services/quiz-data.service.js"; -import { fetchQuestionsByRecommendation } from "../services/question.service.js"; -import { - saveOrUpdateDailyQuiz, - findTodayDailyQuiz, -} from "../services/daily-quiz.service.js"; -import { - gradeAnswers, - SubmittedAnswerInput, -} from "../services/quiz-submission.service.js"; -import { updateDailyQuizScoreByUserToday } from "../services/daily-quiz.service.js"; - -declare global { - namespace Express { - interface Request { - session?: Session; - user?: User; - } - } -} - -// Utility helpers ------------------------------------------------------------- -const startOfDay = (d: Date) => - new Date(d.getFullYear(), d.getMonth(), d.getDate()); - -interface ApiResponse { - status: string; - message?: string; - data?: T; -} -const send = (res: Response, code: number, body: ApiResponse) => - res.status(code).json(body); - -export const getQuiz = async (req: Request, res: Response): Promise => { - if (!req.session) { - send(res, 401, { status: "fail", message: "Unauthorized" }); - return; - } - const userId = req.session.userId; - const today = new Date(); - - try { - // Fetch existing quiz (by date range) if any - const existingQuiz = await findTodayDailyQuiz(userId, today); - const totalQuestions = existingQuiz?.totalQuestions || 10; - - // Build data for AI - const quizData = await buildUserQuizData(userId, totalQuestions); - if (!quizData) { - send(res, 404, { - status: "fail", - message: "User hasn't completed any topics yet", - }); - return; - } - - const aiRecommendation = await fetchAiRecommendation(quizData); - const questions = await fetchQuestionsByRecommendation( - aiRecommendation, - totalQuestions - ); - - // Persist / update quiz record (schema only stores counts currently) - const savedQuiz = await saveOrUpdateDailyQuiz( - userId, - startOfDay(today), - totalQuestions - ); - - send(res, 200, { - status: "success", - data: { quiz: savedQuiz, questions, aiRecommendation }, - }); - } catch (err) { - console.error("[getQuiz] error", err); - send(res, 500, { - status: "error", - message: "Failed to generate quiz", - }); - } -}; - -export const submitQuiz = async ( - req: Request, - res: Response -): Promise => { - if (!req.session) { - send(res, 401, { status: "fail", message: "Unauthorized" }); - return; - } - const userId = req.session.userId; - const today = new Date(); - - try { - const { answers } = req.body as { answers: SubmittedAnswerInput[] }; - if (!Array.isArray(answers) || answers.length === 0) { - send(res, 400, { - status: "fail", - message: "answers array required", - }); - return; - } - - const grading = await gradeAnswers(answers); - await updateDailyQuizScoreByUserToday( - userId, - today, - grading.scorePercentage - ); - - send(res, 200, { - status: "success", - data: { - score: grading.scorePercentage, - correctCount: grading.correctCount, - total: grading.total, - answers: grading.graded, - }, - }); - } catch (err) { - console.error("[submitQuiz] error", err); - send(res, 500, { - status: "error", - message: "Failed to submit quiz", - }); - } -}; diff --git a/apps/api/src/errors/already-submitted-quiz.ts b/apps/api/src/errors/already-submitted-quiz.ts new file mode 100644 index 0000000..893ebab --- /dev/null +++ b/apps/api/src/errors/already-submitted-quiz.ts @@ -0,0 +1,12 @@ +import BaseError from "./base.js"; + +export default class AlreadySubmittedQuiz extends BaseError { + constructor() { + super( + "Quiz has already been submitted", + 409, + undefined, + "You will be able to submit a new task by tomorrow", + ); + } +} diff --git a/apps/api/src/errors/not-enough-topics.ts b/apps/api/src/errors/not-enough-topics.ts new file mode 100644 index 0000000..a1f97f2 --- /dev/null +++ b/apps/api/src/errors/not-enough-topics.ts @@ -0,0 +1,12 @@ +import BaseError from "./base.js"; + +export default class NotEnoughTopics extends BaseError { + constructor() { + super( + "Not enough topics completed", + 422, + undefined, + "Start to complete more topics to be able to perform this action", + ); + } +} diff --git a/apps/api/src/helpers/dates.ts b/apps/api/src/helpers/dates.ts new file mode 100644 index 0000000..f0800fd --- /dev/null +++ b/apps/api/src/helpers/dates.ts @@ -0,0 +1,11 @@ +export const getMonthInterval = (month: number, year: number) => { + const start = new Date(year, month, 1); + const end = new Date(year, month + 1, 1); + return { start, end }; +}; + +export const getStartOfDay = (d: Date) => + new Date(d.getFullYear(), d.getMonth(), d.getDate()); + +export const getNextDay = (d: Date) => + new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1); diff --git a/apps/api/src/middlewares/auth.ts b/apps/api/src/middlewares/auth.ts index c9310f3..9a2fd7d 100644 --- a/apps/api/src/middlewares/auth.ts +++ b/apps/api/src/middlewares/auth.ts @@ -12,7 +12,12 @@ declare global { } } -export const requireAuth: RequestHandler = async (req, res, next) => { +export const requireAuth: RequestHandler< + unknown, + unknown, + unknown, + unknown +> = async (req, res, next) => { const data = await auth.api.getSession({ headers: fromNodeHeaders(req.headers), }); diff --git a/apps/api/src/middlewares/enhanced-send.ts b/apps/api/src/middlewares/enhanced-send.ts new file mode 100644 index 0000000..42ced5d --- /dev/null +++ b/apps/api/src/middlewares/enhanced-send.ts @@ -0,0 +1,28 @@ +import { RequestHandler } from "express"; +import { Pagination } from "../schemas/pagination.js"; + +declare global { + namespace Express { + export interface Response { + enhancedSend: ( + statusCode: number, + data: unknown, + pagination?: Pagination, + ) => Response; + } + } +} + +export const addEnhancedSendMethod: RequestHandler = (req, res, next) => { + res.enhancedSend = (statusCode, data, pagination) => { + const success = statusCode < 400; + return res.status(statusCode).json({ + success, + statusCode, + timestamp: new Date(), + data, + pagination, + }); + }; + next(); +}; diff --git a/apps/api/src/router.ts b/apps/api/src/router.ts new file mode 100644 index 0000000..79fabff --- /dev/null +++ b/apps/api/src/router.ts @@ -0,0 +1,14 @@ +import { Router } from "express"; +import { notesRouter } from "./routes/notes.js"; +import { tracksRouter } from "./routes/tracks.js"; +import { coursesRouter } from "./routes/courses.js"; +import { topicsRouter } from "./routes/topics.js"; + +export const ROUTES_PREFIX = "/api"; + +export const router = Router(); + +router.use("/notes", notesRouter); +router.use("/tracks", tracksRouter); +router.use("/courses", coursesRouter); +router.use("/topics", topicsRouter); diff --git a/apps/api/src/routes/courses.ts b/apps/api/src/routes/courses.ts index b831ef3..902011e 100644 --- a/apps/api/src/routes/courses.ts +++ b/apps/api/src/routes/courses.ts @@ -22,15 +22,17 @@ router.get( req.user!.id, req.params.courseId, ); - const persentage = (completedTopics.length / totalTopics.length) * 100; + const completedPercentage = + (completedTopics.length / totalTopics.length) * 100; - res.status(200).json({ - course, - totalTopics, - persentage, + res.enhancedSend(200, { + ...course, + topics: totalTopics, + completedPercentage, }); }, ); + router.get( "/:courseId/topics", requireAuth, @@ -38,32 +40,14 @@ router.get( async (req, res) => { const { completed } = req.query; - const totalTopics = await topicService.getToltalTopics(req.params.courseId); - - const completedTopics = await topicService.getCompletedTopics( - req.user!.id, + const topics = await topicService.getToltalTopics( req.params.courseId, + completed + ? { isCompleted: completed === "true", userId: req.user!.id } + : undefined, ); - let filterdTopics; - if (completed === "true") { - filterdTopics = completedTopics; - } else if (completed === "false") { - const completedTopicsIds = new Set(); - for (const topic of completedTopics) { - completedTopicsIds.add(topic.id); - } - const unCompletedTopics = totalTopics.filter( - (ele) => !completedTopicsIds.has(ele.id), - ); - filterdTopics = unCompletedTopics; - } else { - filterdTopics = totalTopics; - } - - res.status(200).json({ - filterdTopics, - }); + res.enhancedSend(200, topics); }, ); diff --git a/apps/api/src/routes/index.ts b/apps/api/src/routes/index.ts deleted file mode 100644 index a66cad7..0000000 --- a/apps/api/src/routes/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import express from "express"; -const router = express.Router(); -import { tracksRouter } from "./tracks.js"; -import { coursesRouter } from "./courses.js"; -import { topicsRouter } from "./topics.js"; - -router.get("/", (req, res) => { - res.status(200).json({ - message: "hello from api.", - }); -}); - -router.use("/tracks", tracksRouter); -router.use("/courses", coursesRouter); -router.use("/topics", topicsRouter); - -export default router; diff --git a/apps/api/src/routes/notes.ts b/apps/api/src/routes/notes.ts index 1cad568..aee23a4 100644 --- a/apps/api/src/routes/notes.ts +++ b/apps/api/src/routes/notes.ts @@ -11,7 +11,6 @@ import { CreateNoteBodySchema, GetAllNotesQuerySchema, noteIdSchema, - topicIdSchema, UpdateNoteBodySchema, } from "../schemas/notes.js"; import { requireAuth } from "../middlewares/auth.js"; @@ -20,75 +19,46 @@ const router = Router(); router.use(requireAuth); -router.get( - "/api/notes/:noteId", - validate({ params: noteIdSchema }), - async (req, res) => { - const { noteId } = req.params; - const response = await getNoteById(noteId, req.user!.id); - res.status(200).json({ - status: "success", - data: response, - }); - }, -); +router.get("/:noteId", validate({ params: noteIdSchema }), async (req, res) => { + const { noteId } = req.params; + const response = await getNoteById(noteId, req.user!.id); + res.enhancedSend(200, response); +}); router.get( - "/api/notes", + "/", validate({ query: GetAllNotesQuerySchema }), async (req, res) => { const response = await getAllFilteredNotes(req.user!.id, req.query); - res.status(200).json({ - status: "success", - pagination: response.pagination, - data: response.data, - }); + res.enhancedSend(200, response.data, response.pagination); }, ); -router.post( - "/api/topics/:topicId/notes", - validate({ params: topicIdSchema, body: CreateNoteBodySchema }), - async (req, res) => { - const { topicId } = req.params; - const { title, content } = req.body; - const response = await createNote( - { title, content }, - topicId, - req.user!.id, - ); - res.status(201).json({ - status: "success", - data: response, - }); - }, -); +router.post("/", validate({ body: CreateNoteBodySchema }), async (req, res) => { + const { title, content, topicId } = req.body; + const response = await createNote({ title, content, topicId }, req.user!.id); + res.enhancedSend(201, response); +}); router.put( - "/api/notes/:noteId", + "/:noteId", validate({ params: noteIdSchema, body: UpdateNoteBodySchema }), async (req, res) => { const { noteId } = req.params; const { title, content } = req.body; const response = await updateNote(noteId, req.user!.id, { title, content }); - res.status(200).json({ - status: "success", - data: response, - }); + res.enhancedSend(200, response); }, ); router.delete( - "/api/notes/:noteId", + "/:noteId", validate({ params: noteIdSchema }), async (req, res) => { const { noteId } = req.params; await deleteNote(noteId, req.user!.id); - res.status(204).json({ - status: "success", - message: "Note deleted successfully.", - }); + res.enhancedSend(204, undefined); }, ); diff --git a/apps/api/src/routes/quizzes.ts b/apps/api/src/routes/quizzes.ts index 986ae87..cd56ff7 100644 --- a/apps/api/src/routes/quizzes.ts +++ b/apps/api/src/routes/quizzes.ts @@ -1,9 +1,22 @@ import { Router } from "express"; import { validate } from "../middlewares/validate.js"; import { requireAuth } from "../middlewares/auth.js"; -import { submitDailyQuizBodySchema } from "../schemas/quizzes.js"; -import { getQuiz, submitQuiz } from "../controller/quiz.controller.js"; -import { getQuizSubmissionCalendar } from "../controller/calendar.controller.js"; +import { + getMonthSubmissionsQuerySchema, + submitDailyQuizBodySchema, +} from "../schemas/quizzes.js"; +import { + buildUserQuizData, + createDailyQuiz, + getMonthSubmissions, + getQuizByDate, + gradeAnswers, + submitDailyQuiz, +} from "../services/quizzes.js"; +import NotEnoughTopics from "../errors/not-enough-topics.js"; +import { fetchAiRecommendation } from "../services/recommendations.js"; +import { fetchQuestionsByRecommendation } from "../services/questions.js"; +import AlreadySubmittedQuiz from "../errors/already-submitted-quiz.js"; const router = Router(); @@ -11,19 +24,67 @@ const router = Router(); router.get( "/calendar", requireAuth, - // optional validation for query could be added later - getQuizSubmissionCalendar + validate({ query: getMonthSubmissionsQuerySchema }), + async (req, res) => { + const userId = req.session!.userId; + + const now = new Date(); + const year = req.query.year || now.getFullYear(); + const month = req.query.month ? req.query.month - 1 : now.getMonth(); + + const days = await getMonthSubmissions(month, year, userId); + + res.enhancedSend(200, { year, month: month + 1, days }); + }, ); // Fetch / (re)generate today's quiz for the user -router.get("/daily", requireAuth, getQuiz); +router.get("/daily", requireAuth, async (req, res): Promise => { + const userId = req.session!.userId; + const today = new Date(); + + const existingQuiz = await getQuizByDate(userId, today); + const totalQuestions = existingQuiz?.totalQuestions || 10; + + if (existingQuiz?.submittedAt) { + throw new AlreadySubmittedQuiz(); + } + + // Build data for AI + const quizData = await buildUserQuizData(userId, totalQuestions); + if (!quizData) { + throw new NotEnoughTopics(); + } + + const aiRecommendation = await fetchAiRecommendation(quizData); + const questions = await fetchQuestionsByRecommendation( + aiRecommendation, + totalQuestions, + ); + + const quiz = existingQuiz ?? (await createDailyQuiz(userId, totalQuestions)); + + res.enhancedSend(200, { quiz, questions, aiRecommendation }); +}); // Submit answers for today's quiz router.post( "/daily", requireAuth, validate({ body: submitDailyQuizBodySchema }), - submitQuiz + async (req, res) => { + const { answers } = req.body; + + const grading = await gradeAnswers(answers); + await submitDailyQuiz(req.user!.id, grading.scorePercentage); + + res.enhancedSend(200, { + score: grading.scorePercentage, + correctCount: grading.correctCount, + total: grading.total, + answers: grading.graded, + }); + }, ); export { router as quizzesRouter }; diff --git a/apps/api/src/routes/topics.ts b/apps/api/src/routes/topics.ts index d56f2e3..c88ce4d 100644 --- a/apps/api/src/routes/topics.ts +++ b/apps/api/src/routes/topics.ts @@ -1,39 +1,43 @@ -import exprees from "express"; -const router = exprees.Router(); +import { Router } from "express"; import { validate } from "../middlewares/validate.js"; import { getTopicParamsSchema } from "../schemas/topics.js"; -import * as Service from "../services/topics.js"; import { requireAuth } from "../middlewares/auth.js"; +import { + markTopicAsCompleted, + getTopic, + unmarkTopicAsCompleted, +} from "../services/topics.js"; + +const router = Router(); router.get( "/:topicId", + requireAuth, validate({ params: getTopicParamsSchema }), async (req, res) => { - const topic = await Service.getTopic(req.params.topicId); + const topic = await getTopic(req.params.topicId); - res.status(200).json({ - topic, - }); + res.enhancedSend(200, topic); }, ); + router.post( "/:topicId/completion", requireAuth, validate({ params: getTopicParamsSchema }), async (req, res) => { - const topic = await Service.completeTopic(req.user!.id, req.params.topicId); - res.status(201).json({ - topic, - }); + const topic = await markTopicAsCompleted(req.user!.id, req.params.topicId); + res.enhancedSend(201, topic); }, ); + router.delete( "/:topicId/completion", requireAuth, validate({ params: getTopicParamsSchema }), async (req, res) => { - await Service.inCompleteTopic(req.user!.id, req.params.topicId); - res.status(204).json({}); + await unmarkTopicAsCompleted(req.user!.id, req.params.topicId); + res.enhancedSend(204, undefined); }, ); diff --git a/apps/api/src/routes/tracks.ts b/apps/api/src/routes/tracks.ts index 9776dc9..d169324 100644 --- a/apps/api/src/routes/tracks.ts +++ b/apps/api/src/routes/tracks.ts @@ -1,59 +1,31 @@ -import exprees from "express"; -const router = exprees.Router(); -import { Prisma } from "../generated/prisma/client.js"; +import { Router } from "express"; import { validate } from "../middlewares/validate.js"; import { getTrackQuerySchema, getTrackParamsSchema, } from "../schemas/tracks.js"; -import * as Service from "../services/tracks.js"; import { requireAuth } from "../middlewares/auth.js"; -import * as courseSrvice from "../services/courses.js"; +import { getAllTracks, getTrack } from "../services/tracks.js"; +import { getCourses } from "../services/courses.js"; -router.get("/", async (req, res) => { - const tracks = await Service.getAllTracks(); +const router = Router(); - res.status(200).json({ - length: tracks.length, - data: tracks, - }); +router.get("/", async (req, res) => { + const tracks = await getAllTracks(); + res.enhancedSend(200, tracks); }); + router.get( "/:trackId", requireAuth, validate({ params: getTrackParamsSchema, query: getTrackQuerySchema }), async (req, res) => { - const { levelId } = req.query as { levelId: string }; - const track = await Service.getTrack(req.params.trackId); + const { levelId } = req.query; + const track = await getTrack(req.params.trackId); - const courses = await courseSrvice.getCourses( - levelId, - req.params.trackId, - req.user!.id, - ); - const progress = courses.map( - ( - course: Prisma.CourseGetPayload<{ - include: { topics: { select: { userCompletions: true } } }; - }>, - ) => { - const totalTopics = course.topics.length; - const completedTopics = course.topics.filter( - (topic) => topic.userCompletions.length > 0, - ).length; - const percentage = (completedTopics / totalTopics) * 100; + const courses = await getCourses(levelId, req.params.trackId, req.user!.id); - return { - id: course.id, - title: course.title, - percentage, - }; - }, - ); - res.status(200).json({ - track, - courses: progress, - }); + res.enhancedSend(200, { ...track, courses }); }, ); diff --git a/apps/api/src/schemas/courses.ts b/apps/api/src/schemas/courses.ts index 3571e3c..aa7ad3f 100644 --- a/apps/api/src/schemas/courses.ts +++ b/apps/api/src/schemas/courses.ts @@ -5,5 +5,5 @@ export const getCourseParamsSchema = z.object({ }); export const getCourseQuerySchema = z.object({ - completed: z.string().optional(), + completed: z.enum(["true", "false"]).optional(), }); diff --git a/apps/api/src/schemas/notes.ts b/apps/api/src/schemas/notes.ts index 37944d6..89a341a 100644 --- a/apps/api/src/schemas/notes.ts +++ b/apps/api/src/schemas/notes.ts @@ -8,19 +8,7 @@ export const CreateNoteBodySchema = z.object({ content: z.string().trim().min(1, { message: "Content is required and must be at least 1 character.", }), -}); - -export const NoteSchema = z.object({ - id: z.string().cuid({ message: "id must be a valid CUID." }), - title: z.string().min(1, { message: "Title must be at least 1 character." }), - content: z - .string() - .min(1, { message: "Content must be at least 1 character." }), topicId: z.string().cuid({ message: "topicId must be a valid CUID." }), - userId: z.string().cuid({ message: "userId must be a valid CUID." }), - courseId: z.string().cuid({ message: "courseId must be a valid CUID." }), - createdAt: z.date({ message: "createdAt must be a valid date." }), - updatedAt: z.date({ message: "updatedAt must be a valid date." }), }); export const UpdateNoteBodySchema = z.object({ @@ -78,15 +66,10 @@ export const GetAllNotesQuerySchema = z.object({ .default(10), }); -// valitate params -export const topicIdSchema = z.object({ - topicId: z.string().trim().cuid({ message: "id must be a valid CUID." }), -}); export const noteIdSchema = z.object({ noteId: z.string().trim().cuid({ message: "id must be a valid CUID." }), }); -export type NoteServiceType = z.infer; export type UpdateNoteServiceType = z.infer; export type CreateNoteBodyType = z.infer; export type GetAllNotesQueryType = z.infer; diff --git a/apps/api/src/schemas/pagination.ts b/apps/api/src/schemas/pagination.ts new file mode 100644 index 0000000..619e645 --- /dev/null +++ b/apps/api/src/schemas/pagination.ts @@ -0,0 +1,6 @@ +export type Pagination = { + totalItems: number; + totalPages: number; + currentPage: number; + itemsPerPage: number; +}; diff --git a/apps/api/src/schemas/quizzes.ts b/apps/api/src/schemas/quizzes.ts index 226288a..7cad5ea 100644 --- a/apps/api/src/schemas/quizzes.ts +++ b/apps/api/src/schemas/quizzes.ts @@ -1,12 +1,32 @@ import z from "zod"; +export type AvailableTopic = { + topic: string; + available: { difficulty: string; count: number }[]; +}; + +export type TopicPerformance = { + topic: string; + progressByLevel: { difficulty: string; solved: number; attempted: number }[]; +}; + +export type UserQuizData = { + userTopics: AvailableTopic[]; + userProgress: TopicPerformance[]; +}; + +export const getMonthSubmissionsQuerySchema = z.object({ + month: z.coerce.number().min(1).max(12).optional(), + year: z.coerce.number().min(2000).max(2100).optional(), +}); + export const submitDailyQuizBodySchema = z.object({ answers: z .array( z.object({ questionId: z.string().uuid(), choiceIndex: z.number().int().min(0), - }) + }), ) .min(1), }); diff --git a/apps/api/src/services/ai.service.ts b/apps/api/src/services/ai.service.ts deleted file mode 100644 index f37d205..0000000 --- a/apps/api/src/services/ai.service.ts +++ /dev/null @@ -1,15 +0,0 @@ -import axios from "axios"; - -export const fetchAiRecommendation = async (quizData: any) => { - try { - const aiApiUrl = process.env.AI_API_URL || "http://localhost:5000/api/data"; - const response = await axios.post( - aiApiUrl, - quizData - ); - return response.data; - } catch (err) { - console.error("AI Recommendation error:", err); - throw new Error("Failed to get AI recommendation"); - } -}; diff --git a/apps/api/src/services/courses.ts b/apps/api/src/services/courses.ts index 065b1b0..723a463 100644 --- a/apps/api/src/services/courses.ts +++ b/apps/api/src/services/courses.ts @@ -34,14 +34,14 @@ export const getCompletedTopics = async (userId: string, courseId: string) => { }; export const getCourses = async ( - levelId: string, + levelId: string | undefined, trackId: string, userId: string, ) => { - return await prisma.course.findMany({ + const courses = await prisma.course.findMany({ where: { trackId, - ...(levelId && { levelId }), + levelId, }, orderBy: { order: "asc", @@ -58,4 +58,17 @@ export const getCourses = async ( }, }, }); + + return courses.map((course) => { + const totalTopics = course.topics.length; + const completedTopics = course.topics.filter( + (topic) => topic.userCompletions.length > 0, + ).length; + const completedPercentage = (completedTopics / totalTopics) * 100; + + return { + ...course, + completedPercentage, + }; + }); }; diff --git a/apps/api/src/services/daily-quiz.service.ts b/apps/api/src/services/daily-quiz.service.ts deleted file mode 100644 index c24acf7..0000000 --- a/apps/api/src/services/daily-quiz.service.ts +++ /dev/null @@ -1,67 +0,0 @@ -// Local prisma client -import { prisma } from "../lib/prisma.js"; - -const startOfDay = (d: Date) => - new Date(d.getFullYear(), d.getMonth(), d.getDate()); -const nextDay = (d: Date) => - new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1); - -export const findTodayDailyQuiz = async ( - userId: string, - refDate = new Date() -) => { - return prisma.dailyQuiz.findFirst({ - where: { - userId, - createdAt: { gte: startOfDay(refDate), lt: nextDay(refDate) }, - }, - orderBy: { createdAt: "desc" }, - }); -}; - -export const createDailyQuiz = async ( - userId: string, - totalQuestions: number -) => { - return prisma.dailyQuiz.create({ - data: { userId, totalQuestions, score: 0 }, - }); -}; - -export const saveOrUpdateDailyQuiz = async ( - userId: string, - refDate: Date, - totalQuestions: number -) => { - const existing = await findTodayDailyQuiz(userId, refDate); - if (existing) { - if (existing.totalQuestions !== totalQuestions) { - return prisma.dailyQuiz.update({ - where: { id: existing.id }, - data: { totalQuestions }, - }); - } - return existing; - } - return createDailyQuiz(userId, totalQuestions); -}; - -export const submitDailyQuiz = async (quizId: string, score: number) => { - return prisma.dailyQuiz.update({ - where: { id: quizId }, - data: { score, submittedAt: new Date() }, - }); -}; - -export const updateDailyQuizScoreByUserToday = async ( - userId: string, - refDate: Date, - score: number -) => { - const quiz = await findTodayDailyQuiz(userId, refDate); - if (!quiz) return null; - return prisma.dailyQuiz.update({ - where: { id: quiz.id }, - data: { score, submittedAt: new Date() }, - }); -}; diff --git a/apps/api/src/services/notes.ts b/apps/api/src/services/notes.ts index 913eb93..3b6cd80 100644 --- a/apps/api/src/services/notes.ts +++ b/apps/api/src/services/notes.ts @@ -1,30 +1,24 @@ import { NotFoundError } from "../errors/not-found.js"; -import { Prisma } from "../generated/prisma/client.js"; +import { Note, Prisma } from "../generated/prisma/client.js"; import { prisma } from "../lib/prisma.js"; import { CreateNoteBodyType, GetAllNotesQueryType, - NoteServiceType, UpdateNoteServiceType, } from "../schemas/notes.js"; +import { Pagination } from "../schemas/pagination.js"; interface PaginatedNotesResult { - pagination: { - totalNotes: number; - totalPages: number; - currentPage: number; - limit: number; - }; - data: NoteServiceType[]; + pagination: Pagination; + data: Note[]; } export async function createNote( input: CreateNoteBodyType, - topicId: string, userId: string, -): Promise { +): Promise { const topic = await prisma.topic.findUnique({ - where: { id: topicId }, + where: { id: input.topicId }, select: { courseId: true }, }); @@ -36,7 +30,7 @@ export async function createNote( data: { title: input.title, content: input.content, - topicId, + topicId: input.topicId, userId, courseId: topic.courseId, }, @@ -48,7 +42,7 @@ export async function createNote( export async function getNoteById( noteId: string, userId: string, -): Promise { +): Promise { const note = await prisma.note.findFirst({ where: { id: noteId, @@ -67,7 +61,7 @@ export async function updateNote( noteId: string, userId: string, data: UpdateNoteServiceType, -): Promise { +): Promise { const note = await prisma.note.findFirst({ where: { id: noteId, @@ -143,10 +137,10 @@ export async function getAllFilteredNotes( return { pagination: { - totalNotes: totalCount, + totalItems: totalCount, totalPages: Math.ceil(totalCount / limit), currentPage: page, - limit, + itemsPerPage: limit, }, data: notes, }; diff --git a/apps/api/src/services/question.service.ts b/apps/api/src/services/questions.ts similarity index 64% rename from apps/api/src/services/question.service.ts rename to apps/api/src/services/questions.ts index db3f88b..0cd0cc5 100644 --- a/apps/api/src/services/question.service.ts +++ b/apps/api/src/services/questions.ts @@ -1,11 +1,11 @@ import { prisma } from "../lib/prisma.js"; export const fetchQuestionsByRecommendation = async ( - aiRecommendation: any, - totalQuestions: number + aiRecommendation: { topics: { recommendations: { level: number }[] }[] }, + totalQuestions: number, ) => { - const levelsToFetch = aiRecommendation.topics.flatMap((topic: any) => - topic.recommendations.map((rec: any) => rec.level) + const levelsToFetch = aiRecommendation.topics.flatMap((topic) => + topic.recommendations.map((rec) => rec.level), ); return prisma.question.findMany({ diff --git a/apps/api/src/services/quiz-data.service.ts b/apps/api/src/services/quiz-data.service.ts deleted file mode 100644 index a29e4a1..0000000 --- a/apps/api/src/services/quiz-data.service.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { prisma } from "../lib/prisma.js"; - -export const buildUserQuizData = async ( - userId: string, - totalQuestions: number -) => { - const user = await prisma.user.findUnique({ - where: { id: userId }, - include: { - userCompletions: { - include: { - topic: { - include: { - course: { include: { level: true } }, - questions: true, - }, - }, - }, - }, - }, - }); - - const userCompletions = user?.userCompletions; - if (!userCompletions || userCompletions.length === 0) { - return null; - } - - const topicMap = new Map< - string, - { topic: string; available: { level: number; count: number }[] } - >(); - const progressMap = new Map< - string, - { - topic: string; - progressByLevel: { level: number; solved: number; attempted: number }[]; - } - >(); - - for (const completion of userCompletions) { - const topic = completion.topic; - const course = topic.course; - const levelNumber = parseInt(course.level.title.match(/\d+/)?.[0] || "0"); - - // Build userTopics - if (!topicMap.has(topic.title)) { - topicMap.set(topic.title, { - topic: topic.title, - available: [{ level: levelNumber, count: topic.questions.length }], - }); - } else { - const available = topicMap.get(topic.title)!.available; - const levelEntry = available.find((a) => a.level === levelNumber); - if (levelEntry) { - levelEntry.count += topic.questions.length; - } else { - available.push({ level: levelNumber, count: topic.questions.length }); - } - } - - // Build userProgress - if (!progressMap.has(topic.title)) { - progressMap.set(topic.title, { - topic: topic.title, - progressByLevel: [ - { - level: levelNumber, - solved: topic.solved, - attempted: topic.attempted, - }, - ], - }); - } else { - const progressByLevel = progressMap.get(topic.title)!.progressByLevel; - const progressEntry = progressByLevel.find( - (p) => p.level === levelNumber - ); - if (progressEntry) { - progressEntry.solved += topic.solved; - progressEntry.attempted += topic.attempted; - } else { - progressByLevel.push({ - level: levelNumber, - solved: topic.solved, - attempted: topic.attempted, - }); - } - } - } - - return { - userId, - totalQuestions, - userTopics: Array.from(topicMap.values()), - userProgress: Array.from(progressMap.values()), - }; -}; diff --git a/apps/api/src/services/quiz-submission.service.ts b/apps/api/src/services/quiz-submission.service.ts deleted file mode 100644 index f957198..0000000 --- a/apps/api/src/services/quiz-submission.service.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { prisma } from "../lib/prisma.js"; - -export interface SubmittedAnswerInput { - questionId: string; - choiceIndex: number; -} - -export interface GradedAnswerResult { - questionId: string; - userChoiceIndex: number | null; - correctOptionIndex: number; - isCorrect: boolean; -} - -export interface GradeQuizResult { - graded: GradedAnswerResult[]; - correctCount: number; - total: number; - scorePercentage: number; // 0-100 -} - -const INVALID_QUESTION_INDEX = -1; - -/** - * Grades a batch of answers. Missing or invalid questions are ignored but still counted toward total if they existed in input. - */ -export const gradeAnswers = async ( - answers: SubmittedAnswerInput[] -): Promise => { - // Dedupe by questionId (keep last answer provided by user) - const map = new Map(); - for (const a of answers) { - if (a && a.questionId) map.set(a.questionId, a); - } - const uniqueAnswers = Array.from(map.values()); - if (uniqueAnswers.length === 0) { - return { graded: [], correctCount: 0, total: 0, scorePercentage: 0 }; - } - - const questionIds = uniqueAnswers.map((a) => a.questionId); - const questions = await prisma.question.findMany({ - where: { id: { in: questionIds } }, - select: { id: true, correctOptionIndex: true }, - }); - const questionMap = new Map< - string, - { id: string; correctOptionIndex: number } - >( - questions.map((q: { id: string; correctOptionIndex: number }) => [q.id, q]) - ); - - const graded: GradedAnswerResult[] = uniqueAnswers.map((a) => { - const q = questionMap.get(a.questionId); - if (!q) { - return { - questionId: a.questionId, - userChoiceIndex: a.choiceIndex ?? null, - correctOptionIndex: INVALID_QUESTION_INDEX, - isCorrect: false, - }; - } - const isCorrect = a.choiceIndex === q.correctOptionIndex; - return { - questionId: q.id, - userChoiceIndex: a.choiceIndex ?? null, - correctOptionIndex: q.correctOptionIndex, - isCorrect, - }; - }); - - const correctCount = graded.filter((g) => g.isCorrect).length; - const total = graded.length; - const scorePercentage = - total === 0 ? 0 : +((correctCount / total) * 100).toFixed(2); - - return { graded, correctCount, total, scorePercentage }; -}; diff --git a/apps/api/src/services/quizzes.ts b/apps/api/src/services/quizzes.ts new file mode 100644 index 0000000..c52c5a8 --- /dev/null +++ b/apps/api/src/services/quizzes.ts @@ -0,0 +1,182 @@ +import { getMonthInterval, getStartOfDay } from "../helpers/dates.js"; +import { prisma } from "../lib/prisma.js"; +import { AvailableTopic, TopicPerformance } from "../schemas/quizzes.js"; + +export interface SubmittedAnswerInput { + questionId: string; + choiceIndex: number; +} + +export interface GradedAnswerResult { + questionId: string; + userChoiceIndex: number | null; + correctOptionIndex: number; + isCorrect: boolean; +} + +export interface GradeQuizResult { + graded: GradedAnswerResult[]; + correctCount: number; + total: number; + scorePercentage: number; // 0-100 +} + +const INVALID_QUESTION_INDEX = -1; + +export const getMonthSubmissions = async ( + month: number, + year: number, + userId: string, +) => { + const { start, end } = getMonthInterval(month, year); + const submissions = await prisma.dailyQuiz.findMany({ + where: { + userId, + submittedAt: { not: null, gte: start, lt: end }, + }, + select: { submittedAt: true }, + }); + const days = Array.from({ length: 31 }).fill(false); // 31 days max + for (const submission of submissions) { + if (!submission.submittedAt) continue; + const day = submission.submittedAt.getDate(); // 1-based + if (day >= 1 && day <= 31) days[day - 1] = true; + } + return days; +}; + +export const getQuizByDate = async (userId: string, refDate = new Date()) => { + return prisma.dailyQuiz.findFirst({ + where: { + userId, + quizDate: getStartOfDay(refDate), + }, + }); +}; + +export const buildUserQuizData = async ( + userId: string, + totalQuestions: number, +) => { + const topics = await prisma.topic.findMany({ + where: { + userCompletions: { some: { userId } }, + }, + select: { + id: true, + userPerformances: { where: { userId } }, + }, + }); + + if (!topics || topics.length === 0) { + return null; + } + + const userTopics: AvailableTopic[] = []; + const userProgress: TopicPerformance[] = []; + + for (const topic of topics) { + const questionsCount = await prisma.question.groupBy({ + where: { topics: { some: { id: topic.id } } }, + _count: { id: true }, + by: ["difficulty"], + }); + + userTopics.push({ + topic: topic.id, + available: questionsCount.map((value) => ({ + difficulty: value.difficulty, + count: value._count.id, + })), + }); + + userProgress.push({ + topic: topic.id, + progressByLevel: topic.userPerformances, + }); + } + + return { + userId, + totalQuestions, + userTopics, + userProgress, + }; +}; + +export const createDailyQuiz = async ( + userId: string, + totalQuestions: number, +) => { + return prisma.dailyQuiz.create({ + data: { + userId, + totalQuestions, + score: 0, + quizDate: getStartOfDay(new Date()), + }, + }); +}; + +export const submitDailyQuiz = async (userId: string, score: number) => { + const day = getStartOfDay(new Date()); + return prisma.dailyQuiz.updateMany({ + where: { userId, quizDate: day }, + data: { score, submittedAt: new Date() }, + }); +}; + +/** + * Grades a batch of answers. Missing or invalid questions are ignored but still counted toward total if they existed in input. + */ +export const gradeAnswers = async ( + answers: SubmittedAnswerInput[], +): Promise => { + // Dedupe by questionId (keep last answer provided by user) + const map = new Map(); + for (const a of answers) { + if (a && a.questionId) map.set(a.questionId, a); + } + const uniqueAnswers = [...map.values()]; + if (uniqueAnswers.length === 0) { + return { graded: [], correctCount: 0, total: 0, scorePercentage: 0 }; + } + + const questionIds = uniqueAnswers.map((a) => a.questionId); + const questions = await prisma.question.findMany({ + where: { id: { in: questionIds } }, + select: { id: true, correctOptionIndex: true }, + }); + const questionMap = new Map< + string, + { id: string; correctOptionIndex: number } + >( + questions.map((q: { id: string; correctOptionIndex: number }) => [q.id, q]), + ); + + const graded: GradedAnswerResult[] = uniqueAnswers.map((a) => { + const q = questionMap.get(a.questionId); + if (!q) { + return { + questionId: a.questionId, + userChoiceIndex: a.choiceIndex ?? null, + correctOptionIndex: INVALID_QUESTION_INDEX, + isCorrect: false, + }; + } + const isCorrect = a.choiceIndex === q.correctOptionIndex; + return { + questionId: q.id, + userChoiceIndex: a.choiceIndex ?? null, + correctOptionIndex: q.correctOptionIndex, + isCorrect, + }; + }); + + const correctCount = graded.filter((g) => g.isCorrect).length; + const total = graded.length; + const scorePercentage = + total === 0 ? 0 : +((correctCount / total) * 100).toFixed(2); + + return { graded, correctCount, total, scorePercentage }; +}; diff --git a/apps/api/src/services/recommendations.ts b/apps/api/src/services/recommendations.ts new file mode 100644 index 0000000..bc2463b --- /dev/null +++ b/apps/api/src/services/recommendations.ts @@ -0,0 +1,13 @@ +import axios from "axios"; +import { UserQuizData } from "../schemas/quizzes.js"; + +export const fetchAiRecommendation = async (quizData: UserQuizData) => { + try { + const aiApiUrl = process.env.AI_API_URL || "http://localhost:5000/api/data"; + const response = await axios.post(aiApiUrl, quizData); + return response.data; + } catch (error) { + console.error("AI Recommendation error:", error); + throw new Error("Failed to get AI recommendation"); + } +}; diff --git a/apps/api/src/services/topics.ts b/apps/api/src/services/topics.ts index c42b5c0..cafe473 100644 --- a/apps/api/src/services/topics.ts +++ b/apps/api/src/services/topics.ts @@ -1,3 +1,4 @@ +import { Prisma } from "../generated/prisma/client.js"; import { prisma } from "../lib/prisma.js"; export const getTopic = async (topicId: string) => { @@ -13,7 +14,7 @@ export const getTopic = async (topicId: string) => { }); }; -export const completeTopic = async (userId: string, topicId: string) => { +export const markTopicAsCompleted = async (userId: string, topicId: string) => { return await prisma.userCompletion.create({ data: { userId, @@ -21,24 +22,39 @@ export const completeTopic = async (userId: string, topicId: string) => { }, }); }; -export const inCompleteTopic = async (userId: string, topicId: string) => { - prisma.userCompletion.delete({ +export const unmarkTopicAsCompleted = async ( + userId: string, + topicId: string, +) => { + return await prisma.userCompletion.delete({ where: { userId_topicId: { userId, topicId }, }, }); }; -export const getToltalTopics = async (courseId: string) => { +export const getToltalTopics = async ( + courseId: string, + completion?: { isCompleted: boolean; userId: string }, +) => { + const whereClause: Prisma.TopicWhereInput = { courseId }; + if (completion?.isCompleted === true) { + whereClause.userCompletions = { + some: { userId: completion.userId }, + }; + } else if (completion?.isCompleted === false) { + whereClause.userCompletions = { + none: { userId: completion?.userId }, + }; + } return await prisma.topic.findMany({ - where: { - courseId, - }, + where: whereClause, orderBy: { order: "asc", }, }); }; + export const getCompletedTopics = async (userId: string, courseId: string) => { return await prisma.userCompletion.findMany({ where: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86d32e0..47e1e85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,7 +25,7 @@ importers: dependencies: '@adminjs/express': specifier: ^6.1.1 - version: 6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1) + version: 6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1) '@prisma/client': specifier: 6.11.1 version: 6.11.1(prisma@6.12.0(typescript@5.8.2))(typescript@5.8.2) @@ -34,7 +34,7 @@ importers: version: 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) adminjs: specifier: ^7.8.17 - version: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) + version: 7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8) axios: specifier: ^1.11.0 version: 1.11.0 @@ -54,8 +54,8 @@ importers: specifier: ^3.1.1 version: 3.1.1(express@4.21.2) zod: - specifier: ^3.24.3 - version: 3.25.76 + specifier: ^4.0.17 + version: 4.0.17 devDependencies: '@better-auth/cli': specifier: ^1.2.12 @@ -176,7 +176,7 @@ importers: version: 9.32.0 '@tailwindcss/vite': specifier: ^4.1.5 - version: 4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) + version: 4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.6.3 @@ -197,7 +197,7 @@ importers: version: 19.1.6(@types/react@19.1.8) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) + version: 4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.6) @@ -236,16 +236,16 @@ importers: version: 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.7.3) vite: specifier: ^6.3.1 - version: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + version: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) vite-plugin-svgr: specifier: ^4.3.0 - version: 4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) + version: 4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) + version: 5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) vitest: specifier: ^3.1.2 - version: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + version: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3) packages: @@ -5639,8 +5639,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.0.10: - resolution: {integrity: sha512-3vB+UU3/VmLL2lvwcY/4RV2i9z/YU0DTV/tDuYjrwmx5WeJ7hwy+rGEEx8glHp6Yxw7ibRbKSaIFBgReRPe5KA==} + zod@4.0.17: + resolution: {integrity: sha512-1PHjlYRevNxxdy2JZ8JcNAw7rX8V9P1AKkP+x/xZfxB0K5FYfuV+Ug6P/6NVSR2jHQ+FzDDoDHS04nYUsOIyLQ==} snapshots: @@ -5691,9 +5691,9 @@ snapshots: - react-is - supports-color - '@adminjs/express@6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1)': + '@adminjs/express@6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1)': dependencies: - adminjs: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) + adminjs: 7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8) express: 4.21.2 express-formidable: 1.2.0 express-session: 1.18.2 @@ -6966,7 +6966,7 @@ snapshots: '@floating-ui/utils@0.2.10': {} - '@hello-pangea/dnd@16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@hello-pangea/dnd@16.6.0(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.28.2 css-box-model: 1.2.1 @@ -6974,7 +6974,7 @@ snapshots: raf-schd: 4.0.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) + react-redux: 8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) redux: 4.2.1 use-memo-one: 1.1.3(react@18.3.1) transitivePeerDependencies: @@ -7739,12 +7739,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.11 '@tailwindcss/oxide-win32-x64-msvc': 4.1.11 - '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': + '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': dependencies: '@tailwindcss/node': 4.1.11 '@tailwindcss/oxide': 4.1.11 tailwindcss: 4.1.11 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) '@tanstack/query-core@5.83.0': {} @@ -8285,7 +8285,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': + '@vitejs/plugin-react@4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0) @@ -8293,7 +8293,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) transitivePeerDependencies: - supports-color @@ -8305,13 +8305,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) '@vitest/pretty-format@3.2.4': dependencies: @@ -8352,7 +8352,7 @@ snapshots: acorn@8.15.0: {} - adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8): + adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8): dependencies: '@adminjs/design-system': 4.1.1(@babel/core@7.28.0)(@types/react@19.1.8)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) '@babel/core': 7.28.0 @@ -8363,7 +8363,7 @@ snapshots: '@babel/preset-react': 7.27.1(@babel/core@7.28.0) '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) '@babel/register': 7.27.1(@babel/core@7.28.0) - '@hello-pangea/dnd': 16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@hello-pangea/dnd': 16.6.0(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@redux-devtools/extension': 3.3.0(redux@4.2.1) '@rollup/plugin-babel': 6.0.4(@babel/core@7.28.0)(@types/babel__core@7.20.5)(rollup@4.40.2) '@rollup/plugin-commonjs': 25.0.8(rollup@4.40.2) @@ -8386,7 +8386,7 @@ snapshots: react-feather: 2.0.10(react@18.3.1) react-i18next: 12.3.1(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-is: 18.3.1 - react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) + react-redux: 8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) react-router: 6.30.1(react@18.3.1) react-router-dom: 6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) redux: 4.2.1 @@ -8565,7 +8565,7 @@ snapshots: jose: 5.10.0 kysely: 0.28.2 nanostores: 0.11.4 - zod: 4.0.10 + zod: 4.0.17 optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -10604,7 +10604,7 @@ snapshots: react-fast-compare: 3.2.2 warning: 4.0.3 - react-redux@8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1): + react-redux@8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1): dependencies: '@babel/runtime': 7.28.2 '@types/hoist-non-react-statics': 3.3.7(@types/react@19.1.8) @@ -10615,7 +10615,6 @@ snapshots: use-sync-external-store: 1.5.0(react@18.3.1) optionalDependencies: '@types/react': 19.1.8 - '@types/react-dom': 19.1.6(@types/react@19.1.8) react-dom: 18.3.1(react@18.3.1) redux: 4.2.1 @@ -11428,13 +11427,13 @@ snapshots: vary@1.1.2: {} - vite-node@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): + vite-node@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3): dependencies: cac: 6.7.14 debug: 4.4.1(supports-color@5.5.0) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) transitivePeerDependencies: - '@types/node' - jiti @@ -11449,29 +11448,29 @@ snapshots: - tsx - yaml - vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)): + vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)): dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.40.2) '@svgr/core': 8.1.0(typescript@5.7.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.7.3)) - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)): + vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.7.3) optionalDependencies: - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) transitivePeerDependencies: - supports-color - typescript - vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): + vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3): dependencies: esbuild: 0.25.4 fdir: 6.4.6(picomatch@4.0.3) @@ -11485,13 +11484,12 @@ snapshots: jiti: 2.5.1 lightningcss: 1.30.1 tsx: 4.20.3 - yaml: 1.10.2 - vitest@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): + vitest@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -11509,8 +11507,8 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) - vite-node: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite-node: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.16.5 @@ -11648,4 +11646,4 @@ snapshots: zod@3.25.76: {} - zod@4.0.10: {} + zod@4.0.17: {} From 28e91c07895aa5c7c014145f4e05de0287d14bb0 Mon Sep 17 00:00:00 2001 From: fouadhassan74 Date: Mon, 1 Sep 2025 06:51:21 +0300 Subject: [PATCH 29/31] apply sercvices --- apps/api/eslint.config.mjs | 21 ++-- apps/api/pnpm | 0 apps/web/package.json | 5 +- apps/web/src/components/login/LoginForm.tsx | 3 +- apps/web/src/config/axiosInstance.ts | 76 +++++++++++++ apps/web/src/hooks/courseHooks.ts | 20 ++++ apps/web/src/hooks/notesHooks.ts | 59 ++++++++++ apps/web/src/hooks/quizHooks.ts | 41 +++++++ apps/web/src/hooks/topicHooks.ts | 38 +++++++ apps/web/src/hooks/trackHooks.ts | 19 ++++ apps/web/src/lib/Authenticator.tsx | 31 ++++++ apps/web/src/lib/auth-client.ts | 10 ++ apps/web/src/routes/AppRouter.tsx | 8 +- apps/web/src/services/authService.tsx | 23 ++++ apps/web/src/services/coursesService.tsx | 42 ++++++++ apps/web/src/services/notesService.tsx | 97 +++++++++++++++++ apps/web/src/services/quizesService.tsx | 113 ++++++++++++++++++++ apps/web/src/services/topicsService.tsx | 49 +++++++++ apps/web/src/services/tracksService.tsx | 42 ++++++++ pnpm-lock.yaml | 106 ++++++++++++------ 20 files changed, 756 insertions(+), 47 deletions(-) create mode 100644 apps/api/pnpm create mode 100644 apps/web/src/config/axiosInstance.ts create mode 100644 apps/web/src/hooks/courseHooks.ts create mode 100644 apps/web/src/hooks/notesHooks.ts create mode 100644 apps/web/src/hooks/quizHooks.ts create mode 100644 apps/web/src/hooks/topicHooks.ts create mode 100644 apps/web/src/hooks/trackHooks.ts create mode 100644 apps/web/src/lib/Authenticator.tsx create mode 100644 apps/web/src/lib/auth-client.ts create mode 100644 apps/web/src/services/authService.tsx create mode 100644 apps/web/src/services/coursesService.tsx create mode 100644 apps/web/src/services/notesService.tsx create mode 100644 apps/web/src/services/quizesService.tsx create mode 100644 apps/web/src/services/topicsService.tsx create mode 100644 apps/web/src/services/tracksService.tsx diff --git a/apps/api/eslint.config.mjs b/apps/api/eslint.config.mjs index 6d12476..876a3fe 100644 --- a/apps/api/eslint.config.mjs +++ b/apps/api/eslint.config.mjs @@ -1,21 +1,20 @@ import globals from "globals"; import jsPlugin from "@eslint/js"; import tsPlugin from "typescript-eslint"; -import unicornPlugin from 'eslint-plugin-unicorn'; -import prettierConfig from 'eslint-config-prettier'; -import prettierPluginRecommended from 'eslint-plugin-prettier/recommended'; -import sonarjs from 'eslint-plugin-sonarjs'; - +import unicornPlugin from "eslint-plugin-unicorn"; +// import prettierConfig from "eslint-config-prettier"; +// import prettierPluginRecommended from "eslint-plugin-prettier/recommended"; +import sonarjs from "eslint-plugin-sonarjs"; /** @type {import('eslint').Linter.Config[]} */ export default [ { - ignores: ["**/seed/**", "**/generated/**"] + ignores: ["**/seed/**", "**/generated/**"], }, jsPlugin.configs.recommended, - unicornPlugin.configs['recommended'], - prettierPluginRecommended, - prettierConfig, + unicornPlugin.configs["recommended"], + // prettierPluginRecommended, + // prettierConfig, sonarjs.configs.recommended, ...tsPlugin.configs.recommended, { @@ -33,6 +32,6 @@ export default [ }, languageOptions: { globals: globals.node, - } - } + }, + }, ]; diff --git a/apps/api/pnpm b/apps/api/pnpm new file mode 100644 index 0000000..e69de29 diff --git a/apps/web/package.json b/apps/web/package.json index e935ccd..2f4ec2a 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -21,9 +21,11 @@ "@radix-ui/react-tabs": "^1.1.12", "@tanstack/react-query": "^5.74.11", "@tanstack/react-query-devtools": "^5.74.11", + "better-auth": "^1.2.12", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", + "js-cookie": "^3.0.5", "lucide-react": "^0.503.0", "react": "^19.0.0", "react-day-picker": "8.10.1", @@ -41,6 +43,7 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", + "@types/js-cookie": "^3.0.6", "@types/node": "^22.15.3", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", @@ -62,4 +65,4 @@ "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.1.2" } -} \ No newline at end of file +} diff --git a/apps/web/src/components/login/LoginForm.tsx b/apps/web/src/components/login/LoginForm.tsx index 091be60..44fe76b 100644 --- a/apps/web/src/components/login/LoginForm.tsx +++ b/apps/web/src/components/login/LoginForm.tsx @@ -13,6 +13,7 @@ import { Label } from "@components/ui/label"; import { Checkbox } from "@components/ui/checkbox"; import { User, Lock } from "lucide-react"; import { loginSchema } from "@/src/validation/loginSchema"; +import { login } from "../../services/authService"; type FormValues = { username: string; @@ -42,7 +43,7 @@ function LoginForm() { }); const onSubmit = (data: FormValues) => { - console.log("Form Data:", data); + login(data.username, data.password); form.reset(); }; diff --git a/apps/web/src/config/axiosInstance.ts b/apps/web/src/config/axiosInstance.ts new file mode 100644 index 0000000..873c137 --- /dev/null +++ b/apps/web/src/config/axiosInstance.ts @@ -0,0 +1,76 @@ +import axios from "axios"; +import Cookies from "js-cookie"; + +// Ensure that the environment variable is set and valid +const URL = import.meta.env.VITE_API_URL; +if (!URL) { + console.error( + "API URL is not defined. Please check your environment variables.", + ); +} + +const config = { + maxBodyLength: 10 * 1024 * 1024, // Set to 10MB, adjust as needed + baseURL: URL, + headers: { + Accept: "application/json", + }, +}; + +// Create an axios instance with the defined configuration +const axiosInstance = axios.create(config); + +// Request interceptor to attach authorization token +axiosInstance.interceptors.request.use( + (request) => { + const token = Cookies.get("token"); + + // Attach the authorization token if available + if (token) { + request.headers["Authorization"] = `Bearer ${token}`; + } + + return request; + }, + (error) => { + console.error("Request error:", error); // Log request error + return Promise.reject(error); + }, +); + +// Response interceptor to handle responses and errors +axiosInstance.interceptors.response.use( + (response) => { + return response; + }, + (error) => { + if (error.response) { + // Handle specific error responses + console.error("API Error:", error.response.data); + switch (error.response.status) { + case 401: + // Handle unauthorized access, e.g., redirect to login + console.warn("Unauthorized access - redirecting to login."); + // Optionally, you could use a history.push or navigate to redirect + break; + case 403: + // Handle forbidden access + console.warn("Access forbidden - insufficient permissions."); + break; + case 500: + // Handle internal server errors + console.error("Internal server error - please try again later."); + break; + default: + console.error("An unexpected error occurred."); + } + } else { + // Handle errors without a response (network error, etc.) + console.error("Network error:", error.message); + } + + return Promise.reject(error); + }, +); + +export default axiosInstance; diff --git a/apps/web/src/hooks/courseHooks.ts b/apps/web/src/hooks/courseHooks.ts new file mode 100644 index 0000000..fbd4999 --- /dev/null +++ b/apps/web/src/hooks/courseHooks.ts @@ -0,0 +1,20 @@ +// src/hooks/courseHooks.ts +import { useQuery } from "@tanstack/react-query"; +import { courseService, Course } from "../services/coursesService"; + +// ================== useCoursesList ================== +export const useCoursesList = () => { + return useQuery({ + queryKey: ["courses"], + queryFn: courseService.getCoursesList, + }); +}; + +// ================== useCourseDetails ================== +export const useCourseDetails = (courseId: string) => { + return useQuery({ + queryKey: ["courseDetails", courseId], + queryFn: () => courseService.getCourseDetails(courseId), + enabled: !!courseId, + }); +}; diff --git a/apps/web/src/hooks/notesHooks.ts b/apps/web/src/hooks/notesHooks.ts new file mode 100644 index 0000000..7e16bce --- /dev/null +++ b/apps/web/src/hooks/notesHooks.ts @@ -0,0 +1,59 @@ +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { userService, NotesListParams } from "../services/notesService"; + +// 🟢 Get Notes List +export const useNotesList = (params: NotesListParams) => { + return useQuery({ + queryKey: ["notes", params], + queryFn: () => userService.getNotesList(params), + }); +}; + +// 🟢 Get Note Details +export const useNoteDetails = (noteId: string) => { + return useQuery({ + queryKey: ["note", noteId], + queryFn: () => userService.getNoteDetails(noteId), + enabled: !!noteId, + }); +}; + +// 🟢 Create Note +export const useCreateNote = () => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: userService.createNote, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["notes"] }); + }, + }); +}; + +// 🟢 Update Note +export const useUpdateNote = () => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: ({ + noteId, + updatedNote, + }: { + noteId: string; + updatedNote: { title?: string; content?: string }; + }) => userService.updateNote(noteId, updatedNote), + onSuccess: (data) => { + queryClient.invalidateQueries({ queryKey: ["notes"] }); + queryClient.invalidateQueries({ queryKey: ["note", data.id] }); + }, + }); +}; + +// 🟢 Delete Note +export const useDeleteNote = () => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: (noteId: string) => userService.deleteNote(noteId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["notes"] }); + }, + }); +}; diff --git a/apps/web/src/hooks/quizHooks.ts b/apps/web/src/hooks/quizHooks.ts new file mode 100644 index 0000000..de8e62f --- /dev/null +++ b/apps/web/src/hooks/quizHooks.ts @@ -0,0 +1,41 @@ +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { + quizService, + QuizCalendar, + DailyQuizResponse, + QuizSubmitRequest, + QuizSubmitResponse, +} from "../services/quizesService"; + +// ================== useQuizCalendar ================== +export const useQuizCalendar = (courseId: string) => { + return useQuery({ + queryKey: ["quizCalendar", courseId], + queryFn: () => quizService.getQuizCalendar(courseId), + enabled: !!courseId, + }); +}; + +// ================== useDailyQuiz ================== +export const useDailyQuiz = (courseId: string) => { + return useQuery({ + queryKey: ["dailyQuiz", courseId], + queryFn: () => quizService.getDailyQuiz(courseId), + enabled: !!courseId, + }); +}; + +// ================== useSubmitDailyQuiz ================== +export const useSubmitDailyQuiz = (courseId: string) => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (answers: QuizSubmitRequest) => + quizService.submitDailyQuiz(courseId, answers), + + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["quizCalendar", courseId] }); + queryClient.invalidateQueries({ queryKey: ["dailyQuiz", courseId] }); + }, + }); +}; diff --git a/apps/web/src/hooks/topicHooks.ts b/apps/web/src/hooks/topicHooks.ts new file mode 100644 index 0000000..2f9911b --- /dev/null +++ b/apps/web/src/hooks/topicHooks.ts @@ -0,0 +1,38 @@ +// src/hooks/useTopics.ts +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { topicsService } from "../services/topicsService"; + +// 🟢 Get Topic by ID +export const useTopicById = (topicId: string) => { + return useQuery({ + queryKey: ["topic", topicId], + queryFn: () => topicsService.getTopicById(topicId), + enabled: !!topicId, + }); +}; + +// 🟢 Mark Topic as Completed +export const useMarkTopicAsCompleted = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (topicId: string) => + topicsService.markTopicAsCompleted(topicId), + onSuccess: (_, topicId) => { + queryClient.invalidateQueries({ queryKey: ["topic", topicId] }); + }, + }); +}; + +// 🟢 Unmark Topic as Completed +export const useUnmarkTopicAsCompleted = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (topicId: string) => + topicsService.unMarkTopicAsCompleted(topicId), + onSuccess: (_, topicId) => { + queryClient.invalidateQueries({ queryKey: ["topic", topicId] }); + }, + }); +}; diff --git a/apps/web/src/hooks/trackHooks.ts b/apps/web/src/hooks/trackHooks.ts new file mode 100644 index 0000000..fea6177 --- /dev/null +++ b/apps/web/src/hooks/trackHooks.ts @@ -0,0 +1,19 @@ +import { useQuery } from "@tanstack/react-query"; +import { trackService, Track } from "../services/tracksService"; + +// 🔹 Hook: Get all tracks list +export const useTracksList = () => { + return useQuery({ + queryKey: ["tracks"], + queryFn: () => trackService.getTracksList(), + }); +}; + +// 🔹 Hook: Get track details by ID +export const useTrackDetails = (trackId: string) => { + return useQuery({ + queryKey: ["track", trackId], + queryFn: () => trackService.getTrackDetails(trackId), + enabled: !!trackId, // only fetch if trackId is provided + }); +}; diff --git a/apps/web/src/lib/Authenticator.tsx b/apps/web/src/lib/Authenticator.tsx new file mode 100644 index 0000000..0f0d558 --- /dev/null +++ b/apps/web/src/lib/Authenticator.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import Cookies from "js-cookie"; +import { Navigate, useLocation } from "react-router-dom"; + +interface AuthenticatorProps { + children: React.ReactNode; +} + +const Authenticator: React.FC = ({ children }) => { + const location = useLocation(); + const token = Cookies.get("token"); + + const currentPath = location.pathname; + const isOnAuthPage = currentPath.startsWith("/login"); + + if (token) { + // If user is authenticated and tries to access auth pages, redirect to home + if (isOnAuthPage) { + return ; + } + } else { + // If not authenticated and NOT on auth page, redirect to landing/login + if (!isOnAuthPage) { + return ; + } + } + + return <>{children}; +}; + +export default Authenticator; diff --git a/apps/web/src/lib/auth-client.ts b/apps/web/src/lib/auth-client.ts new file mode 100644 index 0000000..5786fc1 --- /dev/null +++ b/apps/web/src/lib/auth-client.ts @@ -0,0 +1,10 @@ +// authClient.ts +import { createAuthClient } from "better-auth/react"; +const URL = import.meta.env.VITE_API_URL; + +export const authClient = createAuthClient({ + baseURL: URL, + fetchOptions: { + credentials: "include", + }, +}); diff --git a/apps/web/src/routes/AppRouter.tsx b/apps/web/src/routes/AppRouter.tsx index 25f5cae..d7bc2f0 100644 --- a/apps/web/src/routes/AppRouter.tsx +++ b/apps/web/src/routes/AppRouter.tsx @@ -1,5 +1,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import Authenticator from "../lib/Authenticator"; + //layouts import MainLayout from "@layouts/MainLayout"; @@ -31,7 +33,11 @@ const router = createBrowserRouter([ }, { path: "/", - element: , + element: ( + + + + ), children: [ { index: true, diff --git a/apps/web/src/services/authService.tsx b/apps/web/src/services/authService.tsx new file mode 100644 index 0000000..814c12b --- /dev/null +++ b/apps/web/src/services/authService.tsx @@ -0,0 +1,23 @@ +import { authClient } from "../lib/auth-client"; + +async function login(email: string, password: string) { + try { + const res = await authClient.signIn.email({ email, password }); + console.log("Logged in user:", res); + return res; + } catch (err) { + console.error("Login failed:", err); + } +} + +async function getProfile() { + try { + const res = await authClient.getSession(); + console.log("User profile:", res); + return res; + } catch (err) { + console.error("Fetch user failed:", err); + } +} + +export { login, getProfile }; diff --git a/apps/web/src/services/coursesService.tsx b/apps/web/src/services/coursesService.tsx new file mode 100644 index 0000000..672e7f5 --- /dev/null +++ b/apps/web/src/services/coursesService.tsx @@ -0,0 +1,42 @@ +import axiosInstance from "../config/axiosInstance"; + +export interface Topic { + id: string; + name: string; + content: string; +} + +export interface Course { + id: string; + name: string; + description: string; + level: string; + topics: Topic[]; + completedPercentage: number; +} + +export const courseService = { + // 🟢 Get all courses + getCoursesList: async (): Promise => { + const { data } = await axiosInstance.get<{ + success: boolean; + statusCode: number; + timestamp: string; + data: Course[]; + }>("/courses"); + + return data.data; // ✅ unwrap the data + }, + + // 🟢 Get single course details + getCourseDetails: async (courseId: string): Promise => { + const { data } = await axiosInstance.get<{ + success: boolean; + statusCode: number; + timestamp: string; + data: Course; + }>(`/courses/${courseId}`); + + return data.data; // ✅ unwrap the data + }, +}; diff --git a/apps/web/src/services/notesService.tsx b/apps/web/src/services/notesService.tsx new file mode 100644 index 0000000..07d0e85 --- /dev/null +++ b/apps/web/src/services/notesService.tsx @@ -0,0 +1,97 @@ +import axiosInstance from "../config/axiosInstance"; + +export interface Note { + id: string; + title: string; + content: string; + topicId: string; + userId: string; // موجود في schema + createdAt: string; + updatedAt: string; +} + +export interface NotesListParams { + courseId?: string; + topicId?: string; + search?: string; + sort?: string; + page?: number; + limit?: number; +} + +export interface Pagination { + totalItems: number; + totalPages: number; + currentPage: number; + itemsPerPage: number; +} + +export interface ApiResponse { + success: boolean; + statusCode: number; + timestamp: string; + data: T; + pagination?: Pagination; +} + +export const userService = { + // 🟢 Get list + getNotesList: async ({ + courseId = "", + topicId = "", + search = "", + sort = "createdAt", + page = 1, + limit = 10, + }: NotesListParams): Promise<{ notes: Note[]; pagination: Pagination }> => { + const { data } = await axiosInstance.get>("/notes", { + params: { courseId, topicId, search, sort, page, limit }, + }); + + return { + notes: data.data, + pagination: data.pagination!, + }; + }, + + // 🟢 Get details + getNoteDetails: async (noteId: string): Promise => { + const { data } = await axiosInstance.get>( + `/notes/${noteId}`, + ); + return data.data; + }, + + // 🟢 Create + createNote: async (newNote: { + title: string; + content: string; + topicId: string; + }): Promise => { + const { data } = await axiosInstance.post>( + "/notes", + newNote, + ); + return data.data; + }, + + // 🟢 Update + updateNote: async ( + noteId: string, + updatedNote: { title?: string; content?: string }, + ): Promise => { + const { data } = await axiosInstance.put>( + `/notes/${noteId}`, + updatedNote, + ); + return data.data; + }, + + // 🟢 Delete + deleteNote: async (noteId: string): Promise<{ success: boolean }> => { + const { data } = await axiosInstance.delete< + ApiResponse<{ success: boolean }> + >(`/notes/${noteId}`); + return data.data; + }, +}; diff --git a/apps/web/src/services/quizesService.tsx b/apps/web/src/services/quizesService.tsx new file mode 100644 index 0000000..a8033c4 --- /dev/null +++ b/apps/web/src/services/quizesService.tsx @@ -0,0 +1,113 @@ +import axiosInstance from "../config/axiosInstance"; + +// ✅ Shared API Response Wrapper +export interface ApiResponse { + success: boolean; + statusCode: number; + timestamp: string; + data: T; +} + +// ================== Calendar ================== +export interface QuizCalendarDay { + day: number; + hasSubmission: boolean; + score: number | null; +} + +export interface QuizCalendar { + year: number; + month: number; + days: QuizCalendarDay[]; +} + +// ================== Daily Quiz ================== +export interface QuizInfo { + id: string; + userId: string; + date: string; + totalQuestions: number; + submittedAt: string | null; + score: number | null; +} + +export interface QuizQuestion { + id: string; + question: string; + choices: string[]; + difficulty: string; + topic: string; +} + +export interface QuizRecommendationTopic { + topic: string; + difficulty: string; + count: number; +} + +export interface QuizAIRecommendation { + recommendedTopics: QuizRecommendationTopic[]; + reasoning: string; +} + +export interface DailyQuizResponse { + quiz: QuizInfo; + questions: QuizQuestion[]; + aiRecommendation: QuizAIRecommendation; +} + +// ================== Submit ================== +export interface QuizAnswerSubmission { + questionId: string; + choiceIndex: number; +} + +export interface QuizSubmitRequest { + answers: QuizAnswerSubmission[]; +} + +export interface QuizAnswerResult { + questionId: string; + choiceIndex: number; + isCorrect: boolean; + correctChoiceIndex: number; + explanation: string; +} + +export interface QuizSubmitResponse { + score: number; + correctCount: number; + total: number; + answers: QuizAnswerResult[]; +} + +// ================== Service ================== +export const quizService = { + // 🟢 Get Quiz Calendar + getQuizCalendar: async (courseId: string): Promise => { + const { data } = await axiosInstance.get>( + `/courses/${courseId}/quizzes/calendar`, + ); + return data.data; + }, + + // 🟢 Get Daily Quiz + getDailyQuiz: async (courseId: string): Promise => { + const { data } = await axiosInstance.get>( + `/courses/${courseId}/quizzes/daily`, + ); + return data.data; + }, + + // 🟢 Submit Daily Quiz + submitDailyQuiz: async ( + courseId: string, + answers: QuizSubmitRequest, + ): Promise => { + const { data } = await axiosInstance.post>( + `/courses/${courseId}/quizzes/daily/submit`, + answers, + ); + return data.data; + }, +}; diff --git a/apps/web/src/services/topicsService.tsx b/apps/web/src/services/topicsService.tsx new file mode 100644 index 0000000..480b935 --- /dev/null +++ b/apps/web/src/services/topicsService.tsx @@ -0,0 +1,49 @@ +import axiosInstance from "../config/axiosInstance"; + +interface Topic { + id: string; + name: string; + content: string; + courseId: string; + order: number; + completed: boolean; + createdAt: string; + updatedAt: string; +} + +interface ApiResponse { + success: boolean; + statusCode: number; + timestamp: string; + data: T; +} + +export const topicsService = { + // 🟢 Get by ID + getTopicById: async (topicId: string): Promise => { + const { data } = await axiosInstance.get>( + `/topics/${topicId}`, + ); + return data.data; + }, + + // 🟢 Mark completed + markTopicAsCompleted: async ( + topicId: string, + ): Promise<{ success: boolean }> => { + const { data } = await axiosInstance.post< + ApiResponse<{ success: boolean }> + >(`/topics/${topicId}/completion`); + return data.data; + }, + + // 🟢 Unmark completed + unMarkTopicAsCompleted: async ( + topicId: string, + ): Promise<{ success: boolean }> => { + const { data } = await axiosInstance.post< + ApiResponse<{ success: boolean }> + >(`/topics/${topicId}/uncompletion`); + return data.data; + }, +}; diff --git a/apps/web/src/services/tracksService.tsx b/apps/web/src/services/tracksService.tsx new file mode 100644 index 0000000..f1942e1 --- /dev/null +++ b/apps/web/src/services/tracksService.tsx @@ -0,0 +1,42 @@ +import axiosInstance from "../config/axiosInstance"; + +// ✅ Track interface +export interface Track { + id: string; + name: string; + description: string; + icon: string; + createdAt: string; + updatedAt: string; +} + +export interface Pagination { + totalItems: number; + totalPages: number; + currentPage: number; + itemsPerPage: number; +} + +export interface ApiResponse { + success: boolean; + statusCode: number; + timestamp: string; + data: T; + pagination?: Pagination; +} + +export const trackService = { + // 🟢 Get tracks list + getTracksList: async (): Promise => { + const { data } = await axiosInstance.get>("/tracks"); + return data.data; + }, + + // 🟢 Get track details + getTrackDetails: async (trackId: string): Promise => { + const { data } = await axiosInstance.get>( + `/tracks/${trackId}`, + ); + return data.data; + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47e1e85..14066f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,7 +25,7 @@ importers: dependencies: '@adminjs/express': specifier: ^6.1.1 - version: 6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1) + version: 6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1) '@prisma/client': specifier: 6.11.1 version: 6.11.1(prisma@6.12.0(typescript@5.8.2))(typescript@5.8.2) @@ -34,7 +34,7 @@ importers: version: 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) adminjs: specifier: ^7.8.17 - version: 7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8) + version: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) axios: specifier: ^1.11.0 version: 1.11.0 @@ -131,6 +131,9 @@ importers: '@tanstack/react-query-devtools': specifier: ^5.74.11 version: 5.83.0(@tanstack/react-query@5.83.0(react@19.1.0))(react@19.1.0) + better-auth: + specifier: ^1.2.12 + version: 1.3.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -140,6 +143,9 @@ importers: date-fns: specifier: ^4.1.0 version: 4.1.0 + js-cookie: + specifier: ^3.0.5 + version: 3.0.5 lucide-react: specifier: ^0.503.0 version: 0.503.0(react@19.1.0) @@ -176,7 +182,7 @@ importers: version: 9.32.0 '@tailwindcss/vite': specifier: ^4.1.5 - version: 4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.6.3 @@ -186,6 +192,9 @@ importers: '@testing-library/user-event': specifier: ^14.6.1 version: 14.6.1(@testing-library/dom@10.4.0) + '@types/js-cookie': + specifier: ^3.0.6 + version: 3.0.6 '@types/node': specifier: ^22.15.3 version: 22.16.5 @@ -197,7 +206,7 @@ importers: version: 19.1.6(@types/react@19.1.8) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.6) @@ -236,16 +245,16 @@ importers: version: 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.7.3) vite: specifier: ^6.3.1 - version: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + version: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) vite-plugin-svgr: specifier: ^4.3.0 - version: 4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + version: 5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) vitest: specifier: ^3.1.2 - version: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3) + version: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) packages: @@ -2307,6 +2316,9 @@ packages: '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + '@types/js-cookie@3.0.6': + resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -3817,6 +3829,10 @@ packages: jose@5.10.0: resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -5691,9 +5707,9 @@ snapshots: - react-is - supports-color - '@adminjs/express@6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1)': + '@adminjs/express@6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1)': dependencies: - adminjs: 7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8) + adminjs: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) express: 4.21.2 express-formidable: 1.2.0 express-session: 1.18.2 @@ -6966,7 +6982,7 @@ snapshots: '@floating-ui/utils@0.2.10': {} - '@hello-pangea/dnd@16.6.0(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@hello-pangea/dnd@16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.28.2 css-box-model: 1.2.1 @@ -6974,7 +6990,7 @@ snapshots: raf-schd: 4.0.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-redux: 8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) + react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) redux: 4.2.1 use-memo-one: 1.1.3(react@18.3.1) transitivePeerDependencies: @@ -7739,12 +7755,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.11 '@tailwindcss/oxide-win32-x64-msvc': 4.1.11 - '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': + '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': dependencies: '@tailwindcss/node': 4.1.11 '@tailwindcss/oxide': 4.1.11 tailwindcss: 4.1.11 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) '@tanstack/query-core@5.83.0': {} @@ -8056,6 +8072,8 @@ snapshots: '@types/http-errors@2.0.5': {} + '@types/js-cookie@3.0.6': {} + '@types/json-schema@7.0.15': {} '@types/linkify-it@5.0.0': {} @@ -8285,7 +8303,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': + '@vitejs/plugin-react@4.7.0(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0) @@ -8293,7 +8311,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - supports-color @@ -8305,13 +8323,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3))': + '@vitest/mocker@3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -8352,7 +8370,7 @@ snapshots: acorn@8.15.0: {} - adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react@19.1.8): + adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8): dependencies: '@adminjs/design-system': 4.1.1(@babel/core@7.28.0)(@types/react@19.1.8)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) '@babel/core': 7.28.0 @@ -8363,7 +8381,7 @@ snapshots: '@babel/preset-react': 7.27.1(@babel/core@7.28.0) '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) '@babel/register': 7.27.1(@babel/core@7.28.0) - '@hello-pangea/dnd': 16.6.0(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@hello-pangea/dnd': 16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@redux-devtools/extension': 3.3.0(redux@4.2.1) '@rollup/plugin-babel': 6.0.4(@babel/core@7.28.0)(@types/babel__core@7.20.5)(rollup@4.40.2) '@rollup/plugin-commonjs': 25.0.8(rollup@4.40.2) @@ -8386,7 +8404,7 @@ snapshots: react-feather: 2.0.10(react@18.3.1) react-i18next: 12.3.1(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-is: 18.3.1 - react-redux: 8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) + react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) react-router: 6.30.1(react@18.3.1) react-router-dom: 6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) redux: 4.2.1 @@ -8570,6 +8588,24 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + better-auth@1.3.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + '@better-auth/utils': 0.2.5 + '@better-fetch/fetch': 1.1.18 + '@noble/ciphers': 0.6.0 + '@noble/hashes': 1.8.0 + '@simplewebauthn/browser': 13.1.2 + '@simplewebauthn/server': 13.1.2 + better-call: 1.0.12 + defu: 6.1.4 + jose: 5.10.0 + kysely: 0.28.2 + nanostores: 0.11.4 + zod: 4.0.17 + optionalDependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + better-call@1.0.12: dependencies: '@better-fetch/fetch': 1.1.18 @@ -9819,6 +9855,8 @@ snapshots: jose@5.10.0: {} + js-cookie@3.0.5: {} + js-tokens@4.0.0: {} js-tokens@9.0.1: {} @@ -10604,7 +10642,7 @@ snapshots: react-fast-compare: 3.2.2 warning: 4.0.3 - react-redux@8.1.3(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1): + react-redux@8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1): dependencies: '@babel/runtime': 7.28.2 '@types/hoist-non-react-statics': 3.3.7(@types/react@19.1.8) @@ -10615,6 +10653,7 @@ snapshots: use-sync-external-store: 1.5.0(react@18.3.1) optionalDependencies: '@types/react': 19.1.8 + '@types/react-dom': 19.1.6(@types/react@19.1.8) react-dom: 18.3.1(react@18.3.1) redux: 4.2.1 @@ -11427,13 +11466,13 @@ snapshots: vary@1.1.2: {} - vite-node@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3): + vite-node@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): dependencies: cac: 6.7.14 debug: 4.4.1(supports-color@5.5.0) es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - '@types/node' - jiti @@ -11448,29 +11487,29 @@ snapshots: - tsx - yaml - vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)): + vite-plugin-svgr@4.3.0(rollup@4.40.2)(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)): dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.40.2) '@svgr/core': 8.1.0(typescript@5.7.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.7.3)) - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)): + vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.7.3) optionalDependencies: - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) transitivePeerDependencies: - supports-color - typescript - vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3): + vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): dependencies: esbuild: 0.25.4 fdir: 6.4.6(picomatch@4.0.3) @@ -11484,12 +11523,13 @@ snapshots: jiti: 2.5.1 lightningcss: 1.30.1 tsx: 4.20.3 + yaml: 1.10.2 - vitest@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3): + vitest@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)) + '@vitest/mocker': 3.2.4(vite@6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -11507,8 +11547,8 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) - vite-node: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3) + vite: 6.3.5(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) + vite-node: 3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.16.5 From 51fbdf7189f694d88acff80d695188b189eb0ef6 Mon Sep 17 00:00:00 2001 From: Seif El-Din Sweilam Date: Wed, 3 Sep 2025 01:33:56 +0300 Subject: [PATCH 30/31] feat(api): apply cors configuration --- apps/api/package.json | 1 + apps/api/src/app.ts | 8 ++++++++ pnpm-lock.yaml | 10 ++++++++++ 3 files changed, 19 insertions(+) diff --git a/apps/api/package.json b/apps/api/package.json index 96f8545..80782df 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -30,6 +30,7 @@ "devDependencies": { "@better-auth/cli": "^1.2.12", "@eslint/js": "^9.22.0", + "@types/cors": "^2.8.19", "@types/express": "^5.0.1", "@types/node": "^22.15.3", "eslint": "^9.32.0", diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index 2e46f5d..ccf46f9 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -1,5 +1,6 @@ import "express-async-errors"; // For Express 4.x Error Handling import express from "express"; +import cors from "cors"; import { auth } from "./lib/auth.js"; import { toNodeHandler } from "better-auth/node"; import { admin, adminRouter } from "./lib/admin.js"; @@ -9,6 +10,13 @@ import { addEnhancedSendMethod } from "./middlewares/enhanced-send.js"; const app = express(); app.disable("x-powered-by"); +app.use( + cors({ + origin: ["http://localhost:5173", "https://olp.csc.ieeemansb.org"], + credentials: true, + }), +); + app.all("/api/auth/*", toNodeHandler(auth)); app.use(admin.options.rootPath, adminRouter); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14066f4..4a8d895 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,6 +63,9 @@ importers: '@eslint/js': specifier: ^9.22.0 version: 9.32.0 + '@types/cors': + specifier: ^2.8.19 + version: 2.8.19 '@types/express': specifier: ^5.0.1 version: 5.0.3 @@ -2293,6 +2296,9 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/cors@2.8.19': + resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -8046,6 +8052,10 @@ snapshots: dependencies: '@types/node': 22.16.5 + '@types/cors@2.8.19': + dependencies: + '@types/node': 22.16.5 + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.7': {} From b7f3c56035d753e5a5c6c82cdd1afb1ee450516e Mon Sep 17 00:00:00 2001 From: Seif El-Din Sweilam Date: Wed, 3 Sep 2025 01:40:33 +0300 Subject: [PATCH 31/31] fix(api): remove unused adminjs settings for now --- apps/api/package.json | 3 - apps/api/src/app.ts | 4 - apps/api/src/lib/admin.ts | 34 - pnpm-lock.yaml | 3890 +++---------------------------------- 4 files changed, 220 insertions(+), 3711 deletions(-) delete mode 100644 apps/api/src/lib/admin.ts diff --git a/apps/api/package.json b/apps/api/package.json index 80782df..7173701 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -15,10 +15,7 @@ "license": "MIT", "type": "module", "dependencies": { - "@adminjs/express": "^6.1.1", "@prisma/client": "6.11.1", - "@tiptap/extension-horizontal-rule": "2.1.13", - "adminjs": "^7.8.17", "axios": "^1.11.0", "better-auth": "^1.2.12", "cors": "^2.8.5", diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index ccf46f9..0ad1223 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -3,7 +3,6 @@ import express from "express"; import cors from "cors"; import { auth } from "./lib/auth.js"; import { toNodeHandler } from "better-auth/node"; -import { admin, adminRouter } from "./lib/admin.js"; import { router, ROUTES_PREFIX } from "./router.js"; import { addEnhancedSendMethod } from "./middlewares/enhanced-send.js"; @@ -19,9 +18,6 @@ app.use( app.all("/api/auth/*", toNodeHandler(auth)); -app.use(admin.options.rootPath, adminRouter); -console.log(`AdminJS is running under ${admin.options.rootPath}`); - app.use(express.json()); app.use(addEnhancedSendMethod); diff --git a/apps/api/src/lib/admin.ts b/apps/api/src/lib/admin.ts deleted file mode 100644 index ae503bc..0000000 --- a/apps/api/src/lib/admin.ts +++ /dev/null @@ -1,34 +0,0 @@ -import "../env.js"; -import AdminJS from "adminjs"; -import AdminJSExpress from "@adminjs/express"; -import { auth } from "./auth.js"; - -const authenticate = async (email: string, password: string) => { - const res = await auth.api.signInEmail({ - body: { - email, - password, - }, - }); - - return res.user; -}; - -const admin = new AdminJS({ - resources: [], -}); - -const adminRouter = AdminJSExpress.buildAuthenticatedRouter( - admin, - { - authenticate, - cookiePassword: "supersecretpassword", - }, - null, - { - resave: false, - saveUninitialized: false, - }, -); - -export { admin, adminRouter }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a8d895..1240ffd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,24 +23,15 @@ importers: apps/api: dependencies: - '@adminjs/express': - specifier: ^6.1.1 - version: 6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1) '@prisma/client': specifier: 6.11.1 version: 6.11.1(prisma@6.12.0(typescript@5.8.2))(typescript@5.8.2) - '@tiptap/extension-horizontal-rule': - specifier: 2.1.13 - version: 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - adminjs: - specifier: ^7.8.17 - version: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) axios: specifier: ^1.11.0 version: 1.11.0 better-auth: specifier: ^1.2.12 - version: 1.3.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.3.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) cors: specifier: ^2.8.5 version: 2.8.5 @@ -59,7 +50,7 @@ importers: devDependencies: '@better-auth/cli': specifier: ^1.2.12 - version: 1.3.3(@types/react@19.1.8)(kysely@0.28.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.3.3(@types/react@19.1.8)(kysely@0.28.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@eslint/js': specifier: ^9.22.0 version: 9.32.0 @@ -261,21 +252,6 @@ importers: packages: - '@adminjs/design-system@4.1.1': - resolution: {integrity: sha512-aUJjoOwXlBgJWckqDcgUDrRCiDnSrtSHnjFIYzfhhm0dFV107ToHNBemvh72/+krXHtMhRuWCkYkKnrJKh1Bjw==} - peerDependencies: - react: ^18.1.0 - react-dom: ^18.1.0 - - '@adminjs/express@6.1.1': - resolution: {integrity: sha512-Th8Oe9lFkHkfmJb6hUe08zwwZOt5afZ2RRMbMZ1Bq7pzEFnJGnTl8jglYNKdc9Fmxtvbabug0wteQ6qCMZuaVQ==} - peerDependencies: - adminjs: ^7.4.0 - express: '>=4.18.2' - express-formidable: ^1.2.0 - express-session: '>=1.17.3' - tslib: ^2.5.0 - '@adobe/css-tools@4.4.2': resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==} @@ -294,10 +270,6 @@ packages: resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.0': - resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} - engines: {node: '>=6.9.0'} - '@babel/core@7.27.1': resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} engines: {node: '>=6.9.0'} @@ -328,17 +300,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.27.1': - resolution: {integrity: sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-define-polyfill-provider@0.6.5': - resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} @@ -371,12 +332,6 @@ packages: resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.27.1': - resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.27.1': resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} engines: {node: '>=6.9.0'} @@ -399,10 +354,6 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.27.1': - resolution: {integrity: sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==} - engines: {node: '>=6.9.0'} - '@babel/helpers@7.27.1': resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} engines: {node: '>=6.9.0'} @@ -421,54 +372,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1': - resolution: {integrity: sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': - resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': - resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': - resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1': - resolution: {integrity: sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-assertions@7.27.1': - resolution: {integrity: sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-attributes@7.27.1': - resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.27.1': resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} engines: {node: '>=6.9.0'} @@ -481,574 +384,195 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6': - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-transform-arrow-functions@7.27.1': - resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-async-generator-functions@7.28.0': - resolution: {integrity: sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==} + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.27.1': - resolution: {integrity: sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==} + '@babel/plugin-transform-react-display-name@7.28.0': + resolution: {integrity: sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoped-functions@7.27.1': - resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + '@babel/plugin-transform-react-jsx-development@7.27.1': + resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.28.0': - resolution: {integrity: sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==} + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.27.1': - resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==} + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.27.1': - resolution: {integrity: sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - - '@babel/plugin-transform-classes@7.28.0': - resolution: {integrity: sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==} + '@babel/plugin-transform-react-jsx@7.27.1': + resolution: {integrity: sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.27.1': - resolution: {integrity: sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==} + '@babel/plugin-transform-react-pure-annotations@7.27.1': + resolution: {integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.28.0': - resolution: {integrity: sha512-v1nrSMBiKcodhsyJ4Gf+Z0U/yawmJDBOTpEB3mcQY52r9RIyPneGyAS/yM6seP/8I+mWI3elOMtT5dB8GJVs+A==} + '@babel/plugin-transform-typescript@7.28.0': + resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.27.1': - resolution: {integrity: sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==} + '@babel/preset-react@7.27.1': + resolution: {integrity: sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-keys@7.27.1': - resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + '@babel/preset-typescript@7.27.1': + resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1': - resolution: {integrity: sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==} + '@babel/runtime@7.27.1': + resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/plugin-transform-dynamic-import@7.27.1': - resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + '@babel/runtime@7.28.2': + resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-explicit-resource-management@7.28.0': - resolution: {integrity: sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==} + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-exponentiation-operator@7.27.1': - resolution: {integrity: sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==} + '@babel/traverse@7.27.1': + resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-export-namespace-from@7.27.1': - resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + '@babel/traverse@7.28.0': + resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.27.1': - resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + '@babel/types@7.27.1': + resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-function-name@7.27.1': - resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + '@babel/types@7.28.0': + resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-json-strings@7.27.1': - resolution: {integrity: sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==} + '@babel/types@7.28.2': + resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-literals@7.27.1': - resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@better-auth/cli@1.3.3': + resolution: {integrity: sha512-zzhWyt0M8E3Ww09wjqVRXo40+IUE6m9E/u20XcvuJeptJMW9yzOSUhC/pVKGg0FvMaolFzHtAlyXhK+SYZnbyQ==} + hasBin: true - '@babel/plugin-transform-logical-assignment-operators@7.27.1': - resolution: {integrity: sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@better-auth/utils@0.2.5': + resolution: {integrity: sha512-uI2+/8h/zVsH8RrYdG8eUErbuGBk16rZKQfz8CjxQOyCE6v7BqFYEbFwvOkvl1KbUdxhqOnXp78+uE5h8qVEgQ==} - '@babel/plugin-transform-member-expression-literals@7.27.1': - resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@better-fetch/fetch@1.1.18': + resolution: {integrity: sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==} - '@babel/plugin-transform-modules-amd@7.27.1': - resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@chevrotain/cst-dts-gen@10.5.0': + resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==} - '@babel/plugin-transform-modules-commonjs@7.27.1': - resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@chevrotain/gast@10.5.0': + resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==} - '@babel/plugin-transform-modules-systemjs@7.27.1': - resolution: {integrity: sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@chevrotain/types@10.5.0': + resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==} - '@babel/plugin-transform-modules-umd@7.27.1': - resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@chevrotain/utils@10.5.0': + resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==} - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': - resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@clack/core@0.4.2': + resolution: {integrity: sha512-NYQfcEy8MWIxrT5Fj8nIVchfRFA26yYKJcvBS7WlUIlw2OmQOY9DhGGXMovyI5J5PpxrCPGkgUi207EBrjpBvg==} - '@babel/plugin-transform-new-target@7.27.1': - resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@clack/prompts@0.10.1': + resolution: {integrity: sha512-Q0T02vx8ZM9XSv9/Yde0jTmmBQufZhPJfYAg2XrrrxWWaZgq1rr8nU8Hv710BQ1dhoP8rtY7YUdpGej2Qza/cw==} - '@babel/plugin-transform-nullish-coalescing-operator@7.27.1': - resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@csstools/color-helpers@5.0.2': + resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} + engines: {node: '>=18'} - '@babel/plugin-transform-numeric-separator@7.27.1': - resolution: {integrity: sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==} - engines: {node: '>=6.9.0'} + '@csstools/css-calc@2.1.3': + resolution: {integrity: sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==} + engines: {node: '>=18'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 - '@babel/plugin-transform-object-rest-spread@7.28.0': - resolution: {integrity: sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==} - engines: {node: '>=6.9.0'} + '@csstools/css-color-parser@3.0.9': + resolution: {integrity: sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==} + engines: {node: '>=18'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@csstools/css-parser-algorithms': ^3.0.4 + '@csstools/css-tokenizer': ^3.0.3 - '@babel/plugin-transform-object-super@7.27.1': - resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} - engines: {node: '>=6.9.0'} + '@csstools/css-parser-algorithms@3.0.4': + resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==} + engines: {node: '>=18'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@csstools/css-tokenizer': ^3.0.3 - '@babel/plugin-transform-optional-catch-binding@7.27.1': - resolution: {integrity: sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@csstools/css-tokenizer@3.0.3': + resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} + engines: {node: '>=18'} - '@babel/plugin-transform-optional-chaining@7.27.1': - resolution: {integrity: sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/aix-ppc64@0.25.4': + resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] - '@babel/plugin-transform-parameters@7.27.7': - resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/android-arm64@0.25.4': + resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] - '@babel/plugin-transform-private-methods@7.27.1': - resolution: {integrity: sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/android-arm@0.25.4': + resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] - '@babel/plugin-transform-private-property-in-object@7.27.1': - resolution: {integrity: sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/android-x64@0.25.4': + resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] - '@babel/plugin-transform-property-literals@7.27.1': - resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/darwin-arm64@0.25.4': + resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] - '@babel/plugin-transform-react-display-name@7.28.0': - resolution: {integrity: sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/darwin-x64@0.25.4': + resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] - '@babel/plugin-transform-react-jsx-development@7.27.1': - resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx@7.27.1': - resolution: {integrity: sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-pure-annotations@7.27.1': - resolution: {integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-regenerator@7.28.1': - resolution: {integrity: sha512-P0QiV/taaa3kXpLY+sXla5zec4E+4t4Aqc9ggHlfZ7a2cp8/x/Gv08jfwEtn9gnnYIMvHx6aoOZ8XJL8eU71Dg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-regexp-modifiers@7.27.1': - resolution: {integrity: sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/plugin-transform-reserved-words@7.27.1': - resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-runtime@7.28.0': - resolution: {integrity: sha512-dGopk9nZrtCs2+nfIem25UuHyt5moSJamArzIoh9/vezUQPmYDOzjaHDCkAzuGJibCIkPup8rMT2+wYB6S73cA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-shorthand-properties@7.27.1': - resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-spread@7.27.1': - resolution: {integrity: sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-sticky-regex@7.27.1': - resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-template-literals@7.27.1': - resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-typeof-symbol@7.27.1': - resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-typescript@7.28.0': - resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-escapes@7.27.1': - resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-property-regex@7.27.1': - resolution: {integrity: sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-regex@7.27.1': - resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-unicode-sets-regex@7.27.1': - resolution: {integrity: sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/preset-env@7.28.0': - resolution: {integrity: sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/preset-modules@0.1.6-no-external-plugins': - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - - '@babel/preset-react@7.27.1': - resolution: {integrity: sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/preset-typescript@7.27.1': - resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/register@7.27.1': - resolution: {integrity: sha512-K13lQpoV54LATKkzBpBAEu1GGSIRzxR9f4IN4V8DCDgiUMo2UDGagEZr3lPeVNJPLkWUi5JE4hCHKneVTwQlYQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/runtime@7.27.1': - resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} - engines: {node: '>=6.9.0'} - - '@babel/runtime@7.28.2': - resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.27.1': - resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.28.0': - resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.27.1': - resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.28.0': - resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.28.2': - resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} - engines: {node: '>=6.9.0'} - - '@better-auth/cli@1.3.3': - resolution: {integrity: sha512-zzhWyt0M8E3Ww09wjqVRXo40+IUE6m9E/u20XcvuJeptJMW9yzOSUhC/pVKGg0FvMaolFzHtAlyXhK+SYZnbyQ==} - hasBin: true - - '@better-auth/utils@0.2.5': - resolution: {integrity: sha512-uI2+/8h/zVsH8RrYdG8eUErbuGBk16rZKQfz8CjxQOyCE6v7BqFYEbFwvOkvl1KbUdxhqOnXp78+uE5h8qVEgQ==} - - '@better-fetch/fetch@1.1.18': - resolution: {integrity: sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==} - - '@chevrotain/cst-dts-gen@10.5.0': - resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==} - - '@chevrotain/gast@10.5.0': - resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==} - - '@chevrotain/types@10.5.0': - resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==} - - '@chevrotain/utils@10.5.0': - resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==} - - '@clack/core@0.4.2': - resolution: {integrity: sha512-NYQfcEy8MWIxrT5Fj8nIVchfRFA26yYKJcvBS7WlUIlw2OmQOY9DhGGXMovyI5J5PpxrCPGkgUi207EBrjpBvg==} - - '@clack/prompts@0.10.1': - resolution: {integrity: sha512-Q0T02vx8ZM9XSv9/Yde0jTmmBQufZhPJfYAg2XrrrxWWaZgq1rr8nU8Hv710BQ1dhoP8rtY7YUdpGej2Qza/cw==} - - '@csstools/color-helpers@5.0.2': - resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} - engines: {node: '>=18'} - - '@csstools/css-calc@2.1.3': - resolution: {integrity: sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.4 - '@csstools/css-tokenizer': ^3.0.3 - - '@csstools/css-color-parser@3.0.9': - resolution: {integrity: sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.4 - '@csstools/css-tokenizer': ^3.0.3 - - '@csstools/css-parser-algorithms@3.0.4': - resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-tokenizer': ^3.0.3 - - '@csstools/css-tokenizer@3.0.3': - resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} - engines: {node: '>=18'} - - '@emotion/babel-plugin@11.13.5': - resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} - - '@emotion/cache@11.14.0': - resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} - - '@emotion/hash@0.9.2': - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} - - '@emotion/is-prop-valid@1.3.1': - resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==} - - '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - - '@emotion/react@11.14.0': - resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} - peerDependencies: - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - - '@emotion/serialize@1.3.3': - resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} - - '@emotion/sheet@1.4.0': - resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} - - '@emotion/stylis@0.8.5': - resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} - - '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - - '@emotion/unitless@0.7.5': - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': - resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} - peerDependencies: - react: '>=16.8.0' - - '@emotion/utils@1.4.2': - resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} - - '@emotion/weak-memoize@0.4.0': - resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - - '@esbuild/aix-ppc64@0.25.4': - resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.25.4': - resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.25.4': - resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.25.4': - resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.25.4': - resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.4': - resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.25.4': - resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] + '@esbuild/freebsd-arm64@0.25.4': + resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] '@esbuild/freebsd-x64@0.25.4': resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} @@ -1196,21 +720,6 @@ packages: resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@floating-ui/core@1.7.2': - resolution: {integrity: sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==} - - '@floating-ui/dom@1.7.2': - resolution: {integrity: sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==} - - '@floating-ui/utils@0.2.10': - resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} - - '@hello-pangea/dnd@16.6.0': - resolution: {integrity: sha512-vfZ4GydqbtUPXSLfAvKvXQ6xwRzIjUSjVU0Sx+70VOhc2xx6CdmJXJ8YhH70RpbTUGjxctslQTHul9sIOxCfFQ==} - peerDependencies: - react: ^16.8.5 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.5 || ^17.0.0 || ^18.0.0 - '@hexagon/base64@1.1.28': resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==} @@ -1239,12 +748,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@hypnosphi/create-react-context@0.3.1': - resolution: {integrity: sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==} - peerDependencies: - prop-types: ^15.0.0 - react: '>=0.14.0' - '@isaacs/fs-minipass@4.0.1': resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} @@ -1321,9 +824,6 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@popperjs/core@2.11.8': - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - '@prisma/client@5.22.0': resolution: {integrity: sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==} engines: {node: '>=16.13'} @@ -1654,79 +1154,9 @@ packages: '@types/react': optional: true - '@redux-devtools/extension@3.3.0': - resolution: {integrity: sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==} - peerDependencies: - redux: ^3.1.0 || ^4.0.0 || ^5.0.0 - - '@remirror/core-constants@2.0.2': - resolution: {integrity: sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==} - - '@remix-run/router@1.23.0': - resolution: {integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==} - engines: {node: '>=14.0.0'} - '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - '@rollup/plugin-babel@6.0.4': - resolution: {integrity: sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@types/babel__core': ^7.1.9 - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - '@types/babel__core': - optional: true - rollup: - optional: true - - '@rollup/plugin-commonjs@25.0.8': - resolution: {integrity: sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.68.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-inject@5.0.5': - resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-json@6.1.0': - resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-node-resolve@15.3.1': - resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/plugin-replace@5.0.7': - resolution: {integrity: sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/pluginutils@5.1.4': resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} @@ -1846,45 +1276,6 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - '@styled-system/background@5.1.2': - resolution: {integrity: sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==} - - '@styled-system/border@5.1.5': - resolution: {integrity: sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==} - - '@styled-system/color@5.1.2': - resolution: {integrity: sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==} - - '@styled-system/core@5.1.2': - resolution: {integrity: sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==} - - '@styled-system/css@5.1.5': - resolution: {integrity: sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==} - - '@styled-system/flexbox@5.1.2': - resolution: {integrity: sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==} - - '@styled-system/grid@5.1.2': - resolution: {integrity: sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==} - - '@styled-system/layout@5.1.2': - resolution: {integrity: sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==} - - '@styled-system/position@5.1.2': - resolution: {integrity: sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==} - - '@styled-system/shadow@5.1.2': - resolution: {integrity: sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==} - - '@styled-system/space@5.1.2': - resolution: {integrity: sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==} - - '@styled-system/typography@5.1.2': - resolution: {integrity: sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==} - - '@styled-system/variant@5.1.5': - resolution: {integrity: sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==} - '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} engines: {node: '>=14'} @@ -2089,186 +1480,6 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' - '@tinymce/tinymce-react@4.3.2': - resolution: {integrity: sha512-wJHZhPf2Mk3yTtdVC/uIGh+kvDgKuTw/qV13uzdChTNo68JI1l7jYMrSQOpyimDyn5LHAw0E1zFByrm1WHAVeA==} - peerDependencies: - react: ^18.0.0 || ^17.0.1 || ^16.7.0 - react-dom: ^18.0.0 || ^17.0.1 || ^16.7.0 - - '@tiptap/core@2.1.13': - resolution: {integrity: sha512-cMC8bgTN63dj1Mv82iDeeLl6sa9kY0Pug8LSalxVEptRmyFVsVxGgu2/6Y3T+9aCYScxfS06EkA8SdzFMAwYTQ==} - peerDependencies: - '@tiptap/pm': ^2.0.0 - - '@tiptap/extension-blockquote@2.26.1': - resolution: {integrity: sha512-viQ6AHRhjCYYipKK6ZepBzwZpkuMvO9yhRHeUZDvlSOAh8rvsUTSre0y74nu8QRYUt4a44lJJ6BpphJK7bEgYA==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-bold@2.26.1': - resolution: {integrity: sha512-zCce9PRuTNhadFir71luLo99HERDpGJ0EEflGm7RN8I1SnNi9gD5ooK42BOIQtejGCJqg3hTPZiYDJC2hXvckQ==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-bubble-menu@2.1.13': - resolution: {integrity: sha512-Hm7e1GX3AI6lfaUmr6WqsS9MMyXIzCkhh+VQi6K8jj4Q4s8kY4KPoAyD/c3v9pZ/dieUtm2TfqrOCkbHzsJQBg==} - peerDependencies: - '@tiptap/core': ^2.0.0 - '@tiptap/pm': ^2.0.0 - - '@tiptap/extension-bullet-list@2.26.1': - resolution: {integrity: sha512-HHakuV4ckYCDOnBbne088FvCEP4YICw+wgPBz/V2dfpiFYQ4WzT0LPK9s7OFMCN+ROraoug+1ryN1Z1KdIgujQ==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-character-count@2.1.13': - resolution: {integrity: sha512-FxPxS/Uqd4MgndInxXOcgNd225541Nsk1lT5e2uNTSNiQnG7dj7cSFG5KXGcSGLpGGt6e/E28WR6KLV+0/u+WA==} - peerDependencies: - '@tiptap/core': ^2.0.0 - '@tiptap/pm': ^2.0.0 - - '@tiptap/extension-code-block@2.26.1': - resolution: {integrity: sha512-/TDDOwONl0qEUc4+B6V9NnWtSjz95eg7/8uCb8Y8iRbGvI9vT4/znRKofFxstvKmW4URu/H74/g0ywV57h0B+A==} - peerDependencies: - '@tiptap/core': ^2.7.0 - '@tiptap/pm': ^2.7.0 - - '@tiptap/extension-code@2.1.13': - resolution: {integrity: sha512-f5fLYlSgliVVa44vd7lQGvo49+peC+Z2H0Fn84TKNCH7tkNZzouoJsHYn0/enLaQ9Sq+24YPfqulfiwlxyiT8w==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-document@2.1.13': - resolution: {integrity: sha512-wLwiTWsVmZTGIE5duTcHRmW4ulVxNW4nmgfpk95+mPn1iKyNGtrVhGWleLhBlTj+DWXDtcfNWZgqZkZNzhkqYQ==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-dropcursor@2.26.1': - resolution: {integrity: sha512-JkDQU2ZYFOuT5mNYb8OiWGwD1HcjbtmX8tLNugQbToECmz9WvVPqJmn7V/q8VGpP81iEECz/IsyRmuf2kSD4uA==} - peerDependencies: - '@tiptap/core': ^2.7.0 - '@tiptap/pm': ^2.7.0 - - '@tiptap/extension-floating-menu@2.1.13': - resolution: {integrity: sha512-9Oz7pk1Nts2+EyY+rYfnREGbLzQ5UFazAvRhF6zAJdvyuDmAYm0Jp6s0GoTrpV0/dJEISoFaNpPdMJOb9EBNRw==} - peerDependencies: - '@tiptap/core': ^2.0.0 - '@tiptap/pm': ^2.0.0 - - '@tiptap/extension-gapcursor@2.26.1': - resolution: {integrity: sha512-KOiMZc3PwJS3hR0nSq5d0TJi2jkNZkLZElcT6pCEnhRHzPH6dRMu9GM5Jj798ZRUy0T9UFcKJalFZaDxnmRnpg==} - peerDependencies: - '@tiptap/core': ^2.7.0 - '@tiptap/pm': ^2.7.0 - - '@tiptap/extension-hard-break@2.26.1': - resolution: {integrity: sha512-d6uStdNKi8kjPlHAyO59M6KGWATNwhLCD7dng0NXfwGndc22fthzIk/6j9F6ltQx30huy5qQram6j3JXwNACoA==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-heading@2.1.13': - resolution: {integrity: sha512-PEmc19QLmlVUTiHWoF0hpgNTNPNU0nlaFmMKskzO+cx5Df4xvHmv/UqoIwp7/UFbPMkfVJT1ozQU7oD1IWn9Hg==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-history@2.26.1': - resolution: {integrity: sha512-m6YR1gkkauIDo3PRl0gP+7Oc4n5OqDzcjVh6LvWREmZP8nmi94hfseYbqOXUb6RPHIc0JKF02eiRifT4MSd2nw==} - peerDependencies: - '@tiptap/core': ^2.7.0 - '@tiptap/pm': ^2.7.0 - - '@tiptap/extension-horizontal-rule@2.1.13': - resolution: {integrity: sha512-7OgjgNqZXvBejgULNdMSma2M1nzv4bbZG+FT5XMFZmEOxR9IB1x/RzChjPdeicff2ZK2sfhMBc4Y9femF5XkUg==} - peerDependencies: - '@tiptap/core': ^2.0.0 - '@tiptap/pm': ^2.0.0 - - '@tiptap/extension-image@2.1.13': - resolution: {integrity: sha512-7oVAos+BU4KR/zQsfltrd8hgIxKxyxZ19dhwb1BJI2Nt3Mnx+yFPRlRSehID6RT9dYqgW4UW5d6vh/3HQcYYYw==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-italic@2.26.1': - resolution: {integrity: sha512-pOs6oU4LyGO89IrYE4jbE8ZYsPwMMIiKkYfXcfeD9NtpGNBnjeVXXF5I9ndY2ANrCAgC8k58C3/powDRf0T2yA==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-link@2.1.13': - resolution: {integrity: sha512-wuGMf3zRtMHhMrKm9l6Tft5M2N21Z0UP1dZ5t1IlOAvOeYV2QZ5UynwFryxGKLO0NslCBLF/4b/HAdNXbfXWUA==} - peerDependencies: - '@tiptap/core': ^2.0.0 - '@tiptap/pm': ^2.0.0 - - '@tiptap/extension-list-item@2.26.1': - resolution: {integrity: sha512-quOXckC73Luc3x+Dcm88YAEBW+Crh3x5uvtQOQtn2GEG91AshrvbnhGRiYnfvEN7UhWIS+FYI5liHFcRKSUKrQ==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-ordered-list@2.26.1': - resolution: {integrity: sha512-UHKNRxq6TBnXMGFSq91knD6QaHsyyOwLOsXMzupmKM5Su0s+CRXEjfav3qKlbb9e4m7D7S/a0aPm8nC9KIXNhQ==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-paragraph@2.26.1': - resolution: {integrity: sha512-UezvM9VDRAVJlX1tykgHWSD1g3MKfVMWWZ+Tg+PE4+kizOwoYkRWznVPgCAxjmyHajxpCKRXgqTZkOxjJ9Kjzg==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-strike@2.26.1': - resolution: {integrity: sha512-CkoRH+pAi6MgdCh7K0cVZl4N2uR4pZdabXAnFSoLZRSg6imLvEUmWHfSi1dl3Z7JOvd3a4yZ4NxerQn5MWbJ7g==} - peerDependencies: - '@tiptap/core': ^2.7.0 - - '@tiptap/extension-table-cell@2.1.13': - resolution: {integrity: sha512-30pyVt2PxGAk8jmsXKxDheql8K/xIRA9FiDo++kS2Kr6Y7I42/kNPQttJ2W+Q1JdRJvedNfQtziQfKWDRLLCNA==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-table-header@2.1.13': - resolution: {integrity: sha512-FwIV5iso5kmpu01QyvrPCjJqZfqxRTjtjMsDyut2uIgx9v5TXk0V5XvMWobx435ANIDJoGTYCMRlIqcgtyqwAQ==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-table-row@2.1.13': - resolution: {integrity: sha512-27Mb9/oYbiLd+/BUFMhQzRIqMd2Z5j1BZMYsktwtDG8vGdYVlaW257UVaoNR9TmiXyIzd3Dh1mOil8G35+HRHg==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-table@2.1.13': - resolution: {integrity: sha512-yMWt2LqotOsWJhLwFNo8fyTwJNLPtnk+eCUxKLlMXP23mJ/lpF+jvTihhHVVic5GqV9vLYZFU2Tn+5k/Vd5P1w==} - peerDependencies: - '@tiptap/core': ^2.0.0 - '@tiptap/pm': ^2.0.0 - - '@tiptap/extension-text-align@2.1.13': - resolution: {integrity: sha512-ZmbGpi5FHGsWyzt+8DceXERr/Vwxhjpm2VKWZyFTVz8uNJVj+/ou196JQJZqxbp5VtKkS7UYujaO++G5eflb0Q==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-text@2.1.13': - resolution: {integrity: sha512-zzsTTvu5U67a8WjImi6DrmpX2Q/onLSaj+LRWPh36A1Pz2WaxW5asZgaS+xWCnR+UrozlCALWa01r7uv69jq0w==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/extension-typography@2.1.13': - resolution: {integrity: sha512-//90Gzkci4/77CCmdWYyRGTcMUvsQ64jv3mqlL+JqWgLCffMHvWPGKhPMgSzoyHRlAIIACMhxniRtB7HixhTHQ==} - peerDependencies: - '@tiptap/core': ^2.0.0 - - '@tiptap/pm@2.1.13': - resolution: {integrity: sha512-zNbA7muWsHuVg12GrTgN/j119rLePPq5M8dZgkKxUwdw8VmU3eUyBp1SihPEXJ2U0MGdZhNhFX7Y74g11u66sg==} - - '@tiptap/react@2.1.13': - resolution: {integrity: sha512-Dq3f8EtJnpImP3iDtJo+7bulnN9SJZRZcVVzxHXccLcC2MxtmDdlPGZjP+wxO800nd8toSIOd5734fPNf/YcfA==} - peerDependencies: - '@tiptap/core': ^2.0.0 - '@tiptap/pm': ^2.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - - '@tiptap/starter-kit@2.1.13': - resolution: {integrity: sha512-ph/mUR/OwPtPkZ5rNHINxubpABn8fHnvJSdhXFrY/q6SKoaO11NZXgegRaiG4aL7O6Sz4LsZVw6Sm0Ae+GJmrg==} - '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -2314,11 +1525,6 @@ packages: '@types/express@5.0.3': resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==} - '@types/hoist-non-react-statics@3.3.7': - resolution: {integrity: sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==} - peerDependencies: - '@types/react': '*' - '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} @@ -2328,24 +1534,12 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/linkify-it@5.0.0': - resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - - '@types/markdown-it@14.1.2': - resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} - - '@types/mdurl@2.0.0': - resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} '@types/node@22.16.5': resolution: {integrity: sha512-bJFoMATwIGaxxx8VJPeM8TonI8t579oRvgAuT8zFugJsJZgzqv0Fu8Mhp68iecjzG7cnN3mO2dJQ5uUM2EFrgQ==} - '@types/parse-json@4.0.2': - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/prompts@2.4.9': resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==} @@ -2360,26 +1554,15 @@ packages: peerDependencies: '@types/react': ^19.0.0 - '@types/react-transition-group@4.4.12': - resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==} - peerDependencies: - '@types/react': '*' - '@types/react@19.1.8': resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} - '@types/resolve@1.20.2': - resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/send@0.17.5': resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==} '@types/serve-static@1.15.8': resolution: {integrity: sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==} - '@types/use-sync-external-store@0.0.3': - resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==} - '@typescript-eslint/eslint-plugin@8.38.0': resolution: {integrity: sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2493,11 +1676,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - adminjs@7.8.17: - resolution: {integrity: sha512-uTGZNMbNf0gsxzygEdQtPkFIdjkQh9Y47G7oeQ2Lmnvn2hUtArzgRnoLzBnyXBmk9pt0nmzEG4XVHG1tiY2sCA==} - engines: {node: '>=16.0.0'} - hasBin: true - agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -2509,10 +1687,6 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -2583,30 +1757,6 @@ packages: axios@1.11.0: resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} - babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} - - babel-plugin-polyfill-corejs2@0.4.14: - resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-corejs3@0.13.0: - resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-regenerator@0.6.5: - resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-styled-components@2.1.4: - resolution: {integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==} - peerDependencies: - styled-components: '>= 2' - balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -2636,9 +1786,6 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - bl@5.1.0: - resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} - body-parser@1.20.3: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -2663,15 +1810,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -2716,9 +1857,6 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - camelize@1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - caniuse-lite@1.0.30001717: resolution: {integrity: sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==} @@ -2776,29 +1914,10 @@ packages: class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - classnames@2.5.1: - resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} - clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} - cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - - clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - - clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -2814,20 +1933,10 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} - commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -2846,26 +1955,16 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - cookie-signature@1.0.7: - resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} - cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - cookie@1.0.2: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} @@ -2877,10 +1976,6 @@ packages: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} - cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - cosmiconfig@8.3.6: resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} @@ -2890,32 +1985,13 @@ packages: typescript: optional: true - crelt@1.0.6: - resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} - - cross-fetch@4.0.0: - resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - css-box-model@1.2.1: - resolution: {integrity: sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==} - - css-color-keywords@1.0.0: - resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} - engines: {node: '>=4'} - - css-to-react-native@3.2.0: - resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} - css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - cssfilter@0.0.10: - resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} - cssstyle@4.3.1: resolution: {integrity: sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==} engines: {node: '>=18'} @@ -2939,10 +2015,6 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} - date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} @@ -2990,13 +2062,6 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} @@ -3040,9 +2105,6 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-helpers@5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -3340,14 +2402,6 @@ packages: peerDependencies: express: ^4.16.2 - express-formidable@1.2.0: - resolution: {integrity: sha512-w1vXjF3gb50UKTNkFaW8/4rqY4dUrKfZ1sAZzwAF9YxCAgj/29QZsycf71di0GkskrZOAkubk9pvGYfxyAMYiw==} - engines: {node: '>= 8'} - - express-session@1.18.2: - resolution: {integrity: sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==} - engines: {node: '>= 0.8.0'} - express@4.21.2: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} @@ -3394,21 +2448,10 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} - find-cache-dir@2.1.0: - resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} - engines: {node: '>=6'} - - find-root@1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} - find-up-simple@1.0.1: resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} engines: {node: '>=18'} - find-up@3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -3417,10 +2460,6 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} @@ -3441,10 +2480,6 @@ packages: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} - formidable@1.2.6: - resolution: {integrity: sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==} - deprecated: 'Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau' - forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -3467,9 +2502,6 @@ packages: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -3526,11 +2558,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -3560,9 +2587,6 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - gud@1.0.0: - resolution: {integrity: sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==} - has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -3594,16 +2618,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} - html-parse-stringify@3.0.1: - resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} - http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -3621,15 +2639,6 @@ packages: engines: {node: '>=18'} hasBin: true - i18next-browser-languagedetector@7.2.2: - resolution: {integrity: sha512-6b7r75uIJDWCcCflmbof+sJ94k9UQO4X0YR62oUfqGI/GjCLVzlCwu8TFdRZIqVLzWbzNcmkmhfqKEr4TLz4HQ==} - - i18next-http-backend@2.7.3: - resolution: {integrity: sha512-FgZxrXdRA5u44xfYsJlEBL4/KH3f2IluBpgV/7riW0YW2VEyM8FzVt2XHAOi6id0Ppj7vZvCZVpp5LrGXnc8Ig==} - - i18next@22.5.1: - resolution: {integrity: sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==} - iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -3649,9 +2658,6 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} - immutable@4.3.7: - resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -3668,10 +2674,6 @@ packages: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} engines: {node: '>=12'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3713,10 +2715,6 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - is-data-view@1.0.2: resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} @@ -3741,17 +2739,10 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} - is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} - is-module@1.0.0: - resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} @@ -3764,16 +2755,9 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -3798,10 +2782,6 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -3820,10 +2800,6 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - jiti@2.4.2: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true @@ -3892,16 +2868,9 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} - jw-paginate@1.0.4: - resolution: {integrity: sha512-W0bv782exgCoynUL/egbRpaYwf/r6T6e02H870H5u3hfSgEYrxgz5POwmFF5aApS6iPi6yhZ0VF8IbafNFsntA==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -3985,46 +2954,16 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - linkify-it@5.0.0: - resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - - linkifyjs@4.3.2: - resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==} - - locate-path@3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.reduce@4.6.0: - resolution: {integrity: sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw==} - - lodash.startswith@4.2.1: - resolution: {integrity: sha512-XClYR1h4/fJ7H+mmCKppbiBmljN/nGs73iq2SjCT9SF4CBPoUHzLvWmH1GtZMhMBZSiRkHXfeA2RY1eIlJ75ww==} - lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - log-symbols@5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - loupe@3.1.3: resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} @@ -4052,28 +2991,14 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - make-dir@2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - - markdown-it@14.1.0: - resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} - hasBin: true - math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - memoize-one@6.0.0: - resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} - merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} @@ -4102,10 +3027,6 @@ packages: engines: {node: '>=4'} hasBin: true - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} @@ -4117,10 +3038,6 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -4199,15 +3116,6 @@ packages: node-fetch-native@1.6.6: resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} @@ -4250,52 +3158,25 @@ packages: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} - on-headers@1.1.0: - resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} - engines: {node: '>= 0.8'} - once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - ora@6.3.1: - resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - orderedmap@2.1.1: - resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} - own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-locate@3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -4311,10 +3192,6 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -4323,9 +3200,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} @@ -4358,18 +3232,6 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - - pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - - pkg-dir@3.0.0: - resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} - engines: {node: '>=6'} - pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -4377,10 +3239,6 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - polished@4.3.1: - resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} - engines: {node: '>=10'} - possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -4499,67 +3357,6 @@ packages: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - - prosemirror-changeset@2.3.1: - resolution: {integrity: sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==} - - prosemirror-collab@1.3.1: - resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} - - prosemirror-commands@1.7.1: - resolution: {integrity: sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==} - - prosemirror-dropcursor@1.8.2: - resolution: {integrity: sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==} - - prosemirror-gapcursor@1.3.2: - resolution: {integrity: sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==} - - prosemirror-history@1.4.1: - resolution: {integrity: sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==} - - prosemirror-inputrules@1.5.0: - resolution: {integrity: sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==} - - prosemirror-keymap@1.2.3: - resolution: {integrity: sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==} - - prosemirror-markdown@1.13.2: - resolution: {integrity: sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==} - - prosemirror-menu@1.2.5: - resolution: {integrity: sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==} - - prosemirror-model@1.25.2: - resolution: {integrity: sha512-BVypCAJ4SL6jOiTsDffP3Wp6wD69lRhI4zg/iT8JXjp3ccZFiq5WyguxvMKmdKFC3prhaig7wSr8dneDToHE1Q==} - - prosemirror-schema-basic@1.2.4: - resolution: {integrity: sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==} - - prosemirror-schema-list@1.5.1: - resolution: {integrity: sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==} - - prosemirror-state@1.4.3: - resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} - - prosemirror-tables@1.7.1: - resolution: {integrity: sha512-eRQ97Bf+i9Eby99QbyAiyov43iOKgWa7QCGly+lrDt7efZ1v8NWolhXiB43hSDGIXT1UXgbs4KJN3a06FGpr1Q==} - - prosemirror-trailing-node@2.0.9: - resolution: {integrity: sha512-YvyIn3/UaLFlFKrlJB6cObvUhmwFNZVhy1Q8OpW/avoTbD/Y7H5EcjK4AZFKhmuS6/N6WkGgt7gWtBWDnmFvHg==} - peerDependencies: - prosemirror-model: ^1.22.1 - prosemirror-state: ^1.4.2 - prosemirror-view: ^1.33.8 - - prosemirror-transform@1.10.4: - resolution: {integrity: sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw==} - - prosemirror-view@1.40.1: - resolution: {integrity: sha512-pbwUjt3G7TlsQQHDiYSupWBhJswpLVB09xXm1YiJPdkjkh9Pe7Y51XdLh5VWIZmROLY8UpUpG03lkdhm9lzIBA==} - proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -4570,10 +3367,6 @@ packages: pump@3.0.3: resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} - punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} - engines: {node: '>=6'} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -4589,20 +3382,9 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} - qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} - engines: {node: '>=0.6'} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - raf-schd@4.0.3: - resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} - - random-bytes@1.0.0: - resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} - engines: {node: '>= 0.8'} - range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -4618,114 +3400,31 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-currency-input-field@3.10.0: - resolution: {integrity: sha512-GRmZogHh1e1LrmgXg/fKHSuRLYUnj/c/AumfvfuDMA0UX1mDR6u2NR0fzDemRdq4tNHNLucJeJ2OKCr3ehqyDA==} - peerDependencies: - react: ^16.9.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - react-datepicker@4.25.0: - resolution: {integrity: sha512-zB7CSi44SJ0sqo8hUQ3BF1saE/knn7u25qEMTO1CQGofY1VAKahO8k9drZtp0cfW1DMfoYLR3uSY1/uMvbEzbg==} - peerDependencies: - react: ^16.9.0 || ^17 || ^18 - react-dom: ^16.9.0 || ^17 || ^18 - react-day-picker@8.10.1: resolution: {integrity: sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==} peerDependencies: date-fns: ^2.28.0 || ^3.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom@18.3.1: - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - react-dom@19.1.0: resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} peerDependencies: react: ^19.1.0 - react-fast-compare@3.2.2: - resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} - - react-feather@2.0.10: - resolution: {integrity: sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==} - peerDependencies: - react: '>=16.8.6' - react-hook-form@7.61.1: resolution: {integrity: sha512-2vbXUFDYgqEgM2RcXcAT2PwDW/80QARi+PKmHy5q2KhuKvOlG8iIYgf7eIlIANR5trW9fJbP4r5aub3a4egsew==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-i18next@12.3.1: - resolution: {integrity: sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==} - peerDependencies: - i18next: '>= 19.0.0' - react: '>= 16.8.0' - react-dom: '*' - react-native: '*' - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - react-icons@5.5.0: resolution: {integrity: sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==} peerDependencies: react: '*' - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - react-onclickoutside@6.13.2: - resolution: {integrity: sha512-h6Hbf1c8b7tIYY4u90mDdBLY4+AGQVMFtIE89HgC0DtVCh/JfKl477gYqUtGLmjZBKK3MJxomP/lFiLbz4sq9A==} - peerDependencies: - react: ^15.5.x || ^16.x || ^17.x || ^18.x - react-dom: ^15.5.x || ^16.x || ^17.x || ^18.x - - react-phone-input-2@2.15.1: - resolution: {integrity: sha512-W03abwhXcwUoq+vUFvC6ch2+LJYMN8qSOiO889UH6S7SyMCQvox/LF3QWt+cZagZrRdi5z2ON3omnjoCUmlaYw==} - peerDependencies: - react: ^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 - react-dom: ^16.12.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 - - react-popper@2.3.0: - resolution: {integrity: sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==} - peerDependencies: - '@popperjs/core': ^2.0.0 - react: ^16.8.0 || ^17 || ^18 - react-dom: ^16.8.0 || ^17 || ^18 - - react-redux@8.1.3: - resolution: {integrity: sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==} - peerDependencies: - '@types/react': ^16.8 || ^17.0 || ^18.0 - '@types/react-dom': ^16.8 || ^17.0 || ^18.0 - react: ^16.8 || ^17.0 || ^18.0 - react-dom: ^16.8 || ^17.0 || ^18.0 - react-native: '>=0.59' - redux: ^4 || ^5.0.0-beta.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - react-dom: - optional: true - react-native: - optional: true - redux: - optional: true - react-refresh@0.17.0: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} @@ -4750,13 +3449,6 @@ packages: '@types/react': optional: true - react-router-dom@6.30.1: - resolution: {integrity: sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' - react-router-dom@7.7.1: resolution: {integrity: sha512-bavdk2BA5r3MYalGKZ01u8PGuDBloQmzpBZVhDLrOOv1N943Wq6dcM9GhB3x8b7AbqPMEezauv4PeGkAJfy7FQ==} engines: {node: '>=20.0.0'} @@ -4764,12 +3456,6 @@ packages: react: '>=18' react-dom: '>=18' - react-router@6.30.1: - resolution: {integrity: sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' - react-router@7.7.1: resolution: {integrity: sha512-jVKHXoWRIsD/qS6lvGveckwb862EekvapdHJN/cGmzw40KnJH5gg53ujOJ4qX6EKIK9LSBfFed/xiQ5yeXNrUA==} engines: {node: '>=20.0.0'} @@ -4780,12 +3466,6 @@ packages: react-dom: optional: true - react-select@5.10.2: - resolution: {integrity: sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-style-singleton@2.2.3: resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} @@ -4796,21 +3476,6 @@ packages: '@types/react': optional: true - react-text-mask@5.5.0: - resolution: {integrity: sha512-SLJlJQxa0uonMXsnXRpv5abIepGmHz77ylQcra0GNd7Jtk4Wj2Mtp85uGQHv1avba2uI8ZvRpIEQPpJKsqRGYw==} - peerDependencies: - react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - - react-transition-group@4.4.5: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' - - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - react@19.1.0: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} @@ -4827,9 +3492,6 @@ packages: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} - redux@4.2.1: - resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} - refa@0.12.1: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -4838,16 +3500,6 @@ packages: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - regenerate-unicode-properties@10.2.0: - resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} - engines: {node: '>=4'} - - regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regexp-ast-analysis@0.7.1: resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -4863,13 +3515,6 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - regexpu-core@6.2.0: - resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} - engines: {node: '>=4'} - - regjsgen@0.8.0: - resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.12.0: resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true @@ -4881,38 +3526,15 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - - restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup-plugin-esbuild-minify@1.3.0: - resolution: {integrity: sha512-y7BDyMMGYhq5901EijNABWgjEzC8myYhOXKmlnU8xIRvX7KQucSWABBR3IEyITuLJFyq/rXIlezDh9zvnR0k2w==} - engines: {node: '>= 14.18'} - peerDependencies: - rollup: ^2 || ^3 || ^4 - - rollup-plugin-polyfill-node@0.13.0: - resolution: {integrity: sha512-FYEvpCaD5jGtyBuBFcQImEGmTxDTPbiHjJdrYIp+mFIwgXiXabxvKUK7ZT9P31ozu2Tqm9llYQMRWsfvTMTAOw==} - peerDependencies: - rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 - rollup@4.40.2: resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - rope-sequence@1.3.4: - resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} - rou3@0.5.1: resolution: {integrity: sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==} @@ -4944,9 +3566,6 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} @@ -4954,10 +3573,6 @@ packages: resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} engines: {node: ^14.0.0 || >=16.0.0} - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -4993,13 +3608,6 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - - shallowequal@1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -5027,9 +3635,6 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} @@ -5039,10 +3644,6 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - slash@5.1.0: - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} - engines: {node: '>=14.16'} - snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -5050,17 +3651,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -5071,10 +3661,6 @@ packages: std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} - stdin-discarder@0.1.0: - resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -5094,10 +3680,6 @@ packages: string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -5117,20 +3699,6 @@ packages: strip-literal@3.0.0: resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} - styled-components@5.3.9: - resolution: {integrity: sha512-Aj3kb13B75DQBo2oRwRa/APdB5rSmwUfN5exyarpX+x/tlM/rwZA2vVk2vQgVSP6WKaZJHWwiFrzgHt+CLtB4A==} - engines: {node: '>=10'} - peerDependencies: - react: '>= 16.8.0' - react-dom: '>= 16.8.0' - react-is: '>= 16.8.0' - - styled-system@5.1.5: - resolution: {integrity: sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==} - - stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -5139,10 +3707,6 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} @@ -5178,12 +3742,6 @@ packages: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} - text-mask-addons@3.8.0: - resolution: {integrity: sha512-VSZSdc/tKn4zGxgpJ+uNBzoW1t472AoAFIlbw1K7hSNXz0DfSBYDJNRxLqgxOfWw1BY2z6DQpm7g0sYZn5qLpg==} - - tiny-invariant@1.3.3: - resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -5194,9 +3752,6 @@ packages: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} - tinymce@6.8.6: - resolution: {integrity: sha512-++XYEs8lKWvZxDCjrr8Baiw7KiikraZ5JkLMg6EdnUVNKJui0IsrAADj5MsyUeFkcEryfn2jd3p09H7REvewyg==} - tinypool@1.1.1: resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} @@ -5209,9 +3764,6 @@ packages: resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} engines: {node: '>=14.0.0'} - tippy.js@6.3.7: - resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} - tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} @@ -5231,9 +3783,6 @@ packages: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@5.1.1: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} @@ -5343,16 +3892,9 @@ packages: engines: {node: '>=14.17'} hasBin: true - uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - ufo@1.6.1: resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} - uid-safe@2.1.5: - resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} - engines: {node: '>= 0.8'} - unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -5363,22 +3905,6 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - unicode-canonical-property-names-ecmascript@2.0.1: - resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} - engines: {node: '>=4'} - - unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - - unicode-match-property-value-ecmascript@2.2.0: - resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} - engines: {node: '>=4'} - - unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} - engines: {node: '>=4'} - universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -5406,20 +3932,6 @@ packages: '@types/react': optional: true - use-isomorphic-layout-effect@1.2.1: - resolution: {integrity: sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - use-memo-one@1.1.3: - resolution: {integrity: sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - use-sidecar@1.1.3: resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} engines: {node: '>=10'} @@ -5430,11 +3942,6 @@ packages: '@types/react': optional: true - use-sync-external-store@1.5.0: - resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -5442,10 +3949,6 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} - uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} - hasBin: true - vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -5536,26 +4039,10 @@ packages: jsdom: optional: true - void-elements@3.1.0: - resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} - engines: {node: '>=0.10.0'} - - w3c-keyname@2.2.8: - resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} - w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} - warning@4.0.3: - resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - - wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -5572,9 +4059,6 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -5627,11 +4111,6 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - xss@1.0.15: - resolution: {integrity: sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==} - engines: {node: '>= 0.10.0'} - hasBin: true - yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -5666,61 +4145,6 @@ packages: snapshots: - '@adminjs/design-system@4.1.1(@babel/core@7.28.0)(@types/react@19.1.8)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1)': - dependencies: - '@hypnosphi/create-react-context': 0.3.1(prop-types@15.8.1)(react@18.3.1) - '@tinymce/tinymce-react': 4.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/extension-bubble-menu': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-character-count': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-code': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-document': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-floating-menu': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-heading': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-image': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-link': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-table': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-table-cell': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-table-header': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-table-row': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-text': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-text-align': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-typography': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/pm': 2.1.13 - '@tiptap/react': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@tiptap/starter-kit': 2.1.13(@tiptap/pm@2.1.13) - date-fns: 2.30.0 - flat: 5.0.2 - hoist-non-react-statics: 3.3.2 - jw-paginate: 1.0.4 - lodash: 4.17.21 - polished: 4.3.1 - react: 18.3.1 - react-currency-input-field: 3.10.0(react@18.3.1) - react-datepicker: 4.25.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-dom: 18.3.1(react@18.3.1) - react-feather: 2.0.10(react@18.3.1) - react-phone-input-2: 2.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-select: 5.10.2(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-text-mask: 5.5.0(react@18.3.1) - styled-components: 5.3.9(@babel/core@7.28.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) - styled-system: 5.1.5 - text-mask-addons: 3.8.0 - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - - prop-types - - react-is - - supports-color - - '@adminjs/express@6.1.1(adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8))(express-formidable@1.2.0)(express-session@1.18.2)(express@4.21.2)(tslib@2.8.1)': - dependencies: - adminjs: 7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8) - express: 4.21.2 - express-formidable: 1.2.0 - express-session: 1.18.2 - tslib: 2.8.1 - '@adobe/css-tools@4.4.2': {} '@ampproject/remapping@2.3.0': @@ -5744,8 +4168,6 @@ snapshots: '@babel/compat-data@7.27.2': {} - '@babel/compat-data@7.28.0': {} - '@babel/core@7.27.1': dependencies: '@ampproject/remapping': 2.3.0 @@ -5822,47 +4244,23 @@ snapshots: '@babel/helper-optimise-call-expression': 7.27.1 '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.1) '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-member-expression-to-functions': 7.27.1 - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) + '@babel/traverse': 7.28.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-annotate-as-pure': 7.27.3 - regexpu-core: 6.2.0 - semver: 6.3.1 + '@babel/helper-globals@7.28.0': {} - '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.0)': + '@babel/helper-member-expression-to-functions@7.27.1': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.1(supports-color@5.5.0) - lodash.debounce: 4.0.8 - resolve: 1.22.10 + '@babel/traverse': 7.28.0 + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-member-expression-to-functions@7.27.1': + '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.28.0(supports-color@5.5.0) + '@babel/traverse': 7.28.0 '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color @@ -5877,703 +4275,144 @@ snapshots: '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) + '@babel/helper-module-imports': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 '@babel/traverse': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/helper-optimise-call-expression@7.27.1': - dependencies: - '@babel/types': 7.28.2 - - '@babel/helper-plugin-utils@7.27.1': {} - - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-wrap-function': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-member-expression-to-functions': 7.27.1 - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-member-expression-to-functions': 7.27.1 - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/helper-skip-transparent-expression-wrappers@7.27.1': - dependencies: - '@babel/traverse': 7.28.0(supports-color@5.5.0) - '@babel/types': 7.28.2 - transitivePeerDependencies: - - supports-color - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.27.1': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helper-wrap-function@7.27.1': - dependencies: - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - '@babel/types': 7.28.2 - transitivePeerDependencies: - - supports-color - - '@babel/helpers@7.27.1': - dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.0 - - '@babel/helpers@7.28.2': - dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.2 - - '@babel/parser@7.27.2': - dependencies: - '@babel/types': 7.28.0 - - '@babel/parser@7.28.0': - dependencies: - '@babel/types': 7.28.2 - - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - - '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-block-scoping@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-class-static-block@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-classes@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/template': 7.27.2 - - '@babel/plugin-transform-destructuring@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-exponentiation-operator@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-logical-assignment-operators@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.1) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-modules-systemjs@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-object-rest-spread@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0) - '@babel/traverse': 7.28.0(supports-color@5.5.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-optional-chaining@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.27.1)': - dependencies: - '@babel/core': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.27.1)': + '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.27.1) + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.0)': + '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.0(supports-color@5.5.0) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.0)': + '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.28.2 - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils@7.27.1': {} - '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.27.1)': + '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.1) - '@babel/types': 7.28.2 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.0)': + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) + '@babel/traverse': 7.28.0 '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.27.1)': + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.27.1': dependencies: - '@babel/core': 7.27.1 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/template': 7.27.2 + '@babel/types': 7.28.0 + + '@babel/helpers@7.28.2': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 - '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.28.0)': + '@babel/parser@7.27.2': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.28.0 - '@babel/plugin-transform-regenerator@7.28.1(@babel/core@7.28.0)': + '@babel/parser@7.28.0': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.28.2 - '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.1)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) + '@babel/core': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.1)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-runtime@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.27.1)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) + '@babel/core': 7.27.1 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.1) '@babel/helper-plugin-utils': 7.27.1 - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.0) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.0) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0) - semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.27.1)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.27.1)': dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/core': 7.27.1 + '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.27.1) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.0)': + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.27.1)': + '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) + '@babel/helper-module-imports': 7.27.1 '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.1) + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.1) + '@babel/types': 7.28.2 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.27.1)': dependencies: - '@babel/core': 7.28.0 + '@babel/core': 7.27.1 '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.28.0) '@babel/helper-plugin-utils': 7.27.1 - '@babel/preset-env@7.28.0(@babel/core@7.28.0)': + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.27.1)': dependencies: - '@babel/compat-data': 7.28.0 - '@babel/core': 7.28.0 - '@babel/helper-compilation-targets': 7.27.2 + '@babel/core': 7.27.1 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.1) '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.0) - '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.0) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-block-scoping': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-class-static-block': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-classes': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-destructuring': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-exponentiation-operator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-logical-assignment-operators': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-systemjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.0) - '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-regenerator': 7.28.1(@babel/core@7.28.0) - '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.0) - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.0) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.0) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.0) - core-js-compat: 3.44.0 - semver: 6.3.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.1) transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/types': 7.28.2 - esutils: 2.0.3 - '@babel/preset-react@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 @@ -6586,18 +4425,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-react@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - '@babel/preset-typescript@7.27.1(@babel/core@7.27.1)': dependencies: '@babel/core': 7.27.1 @@ -6609,26 +4436,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-typescript@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - - '@babel/register@7.27.1(@babel/core@7.28.0)': - dependencies: - '@babel/core': 7.28.0 - clone-deep: 4.0.1 - find-cache-dir: 2.1.0 - make-dir: 2.1.0 - pirates: 4.0.7 - source-map-support: 0.5.21 - '@babel/runtime@7.27.1': {} '@babel/runtime@7.28.2': {} @@ -6646,11 +4453,23 @@ snapshots: '@babel/parser': 7.27.2 '@babel/template': 7.27.2 '@babel/types': 7.28.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color + '@babel/traverse@7.28.0': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.0 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.2 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + '@babel/traverse@7.28.0(supports-color@5.5.0)': dependencies: '@babel/code-frame': 7.27.1 @@ -6678,7 +4497,7 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@better-auth/cli@1.3.3(@types/react@19.1.8)(kysely@0.28.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@better-auth/cli@1.3.3(@types/react@19.1.8)(kysely@0.28.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@babel/core': 7.27.1 '@babel/preset-react': 7.27.1(@babel/core@7.27.1) @@ -6688,13 +4507,13 @@ snapshots: '@prisma/client': 5.22.0(prisma@5.22.0) '@types/better-sqlite3': 7.6.13 '@types/prompts': 2.4.9 - better-auth: 1.3.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + better-auth: 1.3.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) better-sqlite3: 11.10.0 c12: 2.0.4 chalk: 5.4.1 commander: 12.1.0 dotenv: 16.6.1 - drizzle-orm: 0.33.0(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(@types/react@19.1.8)(better-sqlite3@11.10.0)(kysely@0.28.2)(prisma@5.22.0)(react@18.3.1) + drizzle-orm: 0.33.0(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(@types/react@19.1.8)(better-sqlite3@11.10.0)(kysely@0.28.2)(prisma@5.22.0)(react@19.1.0) fs-extra: 11.3.0 get-tsconfig: 4.10.1 prettier: 3.5.3 @@ -6786,78 +4605,6 @@ snapshots: '@csstools/css-tokenizer@3.0.3': {} - '@emotion/babel-plugin@11.13.5': - dependencies: - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/runtime': 7.28.2 - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/serialize': 1.3.3 - babel-plugin-macros: 3.1.0 - convert-source-map: 1.9.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.2.0 - transitivePeerDependencies: - - supports-color - - '@emotion/cache@11.14.0': - dependencies: - '@emotion/memoize': 0.9.0 - '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - stylis: 4.2.0 - - '@emotion/hash@0.9.2': {} - - '@emotion/is-prop-valid@1.3.1': - dependencies: - '@emotion/memoize': 0.9.0 - - '@emotion/memoize@0.9.0': {} - - '@emotion/react@11.14.0(@types/react@19.1.8)(react@18.3.1)': - dependencies: - '@babel/runtime': 7.28.2 - '@emotion/babel-plugin': 11.13.5 - '@emotion/cache': 11.14.0 - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@18.3.1) - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.4.0 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - optionalDependencies: - '@types/react': 19.1.8 - transitivePeerDependencies: - - supports-color - - '@emotion/serialize@1.3.3': - dependencies: - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/unitless': 0.10.0 - '@emotion/utils': 1.4.2 - csstype: 3.1.3 - - '@emotion/sheet@1.4.0': {} - - '@emotion/stylis@0.8.5': {} - - '@emotion/unitless@0.10.0': {} - - '@emotion/unitless@0.7.5': {} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@18.3.1)': - dependencies: - react: 18.3.1 - - '@emotion/utils@1.4.2': {} - - '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.25.4': optional: true @@ -6977,33 +4724,6 @@ snapshots: '@eslint/core': 0.15.1 levn: 0.4.1 - '@floating-ui/core@1.7.2': - dependencies: - '@floating-ui/utils': 0.2.10 - - '@floating-ui/dom@1.7.2': - dependencies: - '@floating-ui/core': 1.7.2 - '@floating-ui/utils': 0.2.10 - - '@floating-ui/utils@0.2.10': {} - - '@hello-pangea/dnd@16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.28.2 - css-box-model: 1.2.1 - memoize-one: 6.0.0 - raf-schd: 4.0.3 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) - redux: 4.2.1 - use-memo-one: 1.1.3(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - - react-native - '@hexagon/base64@1.1.28': {} '@hookform/resolvers@5.2.0(react-hook-form@7.61.1(react@19.1.0))': @@ -7024,13 +4744,6 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@hypnosphi/create-react-context@0.3.1(prop-types@15.8.1)(react@18.3.1)': - dependencies: - gud: 1.0.0 - prop-types: 15.8.1 - react: 18.3.1 - warning: 4.0.3 - '@isaacs/fs-minipass@4.0.1': dependencies: minipass: 7.1.2 @@ -7122,8 +4835,6 @@ snapshots: '@pkgr/core@0.2.9': {} - '@popperjs/core@2.11.8': {} - '@prisma/client@5.22.0(prisma@5.22.0)': optionalDependencies: prisma: 5.22.0 @@ -7424,75 +5135,12 @@ snapshots: '@radix-ui/react-use-size@1.1.1(@types/react@19.1.8)(react@19.1.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - optionalDependencies: - '@types/react': 19.1.8 - - '@redux-devtools/extension@3.3.0(redux@4.2.1)': - dependencies: - '@babel/runtime': 7.28.2 - immutable: 4.3.7 - redux: 4.2.1 - - '@remirror/core-constants@2.0.2': {} - - '@remix-run/router@1.23.0': {} - - '@rolldown/pluginutils@1.0.0-beta.27': {} - - '@rollup/plugin-babel@6.0.4(@babel/core@7.28.0)(@types/babel__core@7.20.5)(rollup@4.40.2)': - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - optionalDependencies: - '@types/babel__core': 7.20.5 - rollup: 4.40.2 - transitivePeerDependencies: - - supports-color - - '@rollup/plugin-commonjs@25.0.8(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 8.1.0 - is-reference: 1.2.1 - magic-string: 0.30.17 - optionalDependencies: - rollup: 4.40.2 - - '@rollup/plugin-inject@5.0.5(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - estree-walker: 2.0.2 - magic-string: 0.30.17 - optionalDependencies: - rollup: 4.40.2 - - '@rollup/plugin-json@6.1.0(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - optionalDependencies: - rollup: 4.40.2 - - '@rollup/plugin-node-resolve@15.3.1(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.10 - optionalDependencies: - rollup: 4.40.2 - - '@rollup/plugin-replace@5.0.7(rollup@4.40.2)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.40.2) - magic-string: 0.30.17 + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.8)(react@19.1.0) + react: 19.1.0 optionalDependencies: - rollup: 4.40.2 + '@types/react': 19.1.8 + + '@rolldown/pluginutils@1.0.0-beta.27': {} '@rollup/pluginutils@5.1.4(rollup@4.40.2)': dependencies: @@ -7576,57 +5224,6 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@styled-system/background@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/border@5.1.5': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/color@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/core@5.1.2': - dependencies: - object-assign: 4.1.1 - - '@styled-system/css@5.1.5': {} - - '@styled-system/flexbox@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/grid@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/layout@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/position@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/shadow@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/space@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/typography@5.1.2': - dependencies: - '@styled-system/core': 5.1.2 - - '@styled-system/variant@5.1.5': - dependencies: - '@styled-system/core': 5.1.2 - '@styled-system/css': 5.1.5 - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 @@ -7818,200 +5415,6 @@ snapshots: dependencies: '@testing-library/dom': 10.4.0 - '@tinymce/tinymce-react@4.3.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - tinymce: 6.8.6 - - '@tiptap/core@2.1.13(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-blockquote@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-bold@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-bubble-menu@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - tippy.js: 6.3.7 - - '@tiptap/extension-bullet-list@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-character-count@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-code-block@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-code@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-document@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-dropcursor@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-floating-menu@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - tippy.js: 6.3.7 - - '@tiptap/extension-gapcursor@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-hard-break@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-heading@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-history@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-horizontal-rule@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-image@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-italic@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-link@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - linkifyjs: 4.3.2 - - '@tiptap/extension-list-item@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-ordered-list@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-paragraph@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-strike@2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-table-cell@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-table-header@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-table-row@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-table@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - - '@tiptap/extension-text-align@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-text@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/extension-typography@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - - '@tiptap/pm@2.1.13': - dependencies: - prosemirror-changeset: 2.3.1 - prosemirror-collab: 1.3.1 - prosemirror-commands: 1.7.1 - prosemirror-dropcursor: 1.8.2 - prosemirror-gapcursor: 1.3.2 - prosemirror-history: 1.4.1 - prosemirror-inputrules: 1.5.0 - prosemirror-keymap: 1.2.3 - prosemirror-markdown: 1.13.2 - prosemirror-menu: 1.2.5 - prosemirror-model: 1.25.2 - prosemirror-schema-basic: 1.2.4 - prosemirror-schema-list: 1.5.1 - prosemirror-state: 1.4.3 - prosemirror-tables: 1.7.1 - prosemirror-trailing-node: 2.0.9(prosemirror-model@1.25.2)(prosemirror-state@1.4.3)(prosemirror-view@1.40.1) - prosemirror-transform: 1.10.4 - prosemirror-view: 1.40.1 - - '@tiptap/react@2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/extension-bubble-menu': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-floating-menu': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/pm': 2.1.13 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@tiptap/starter-kit@2.1.13(@tiptap/pm@2.1.13)': - dependencies: - '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13) - '@tiptap/extension-blockquote': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-bold': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-bullet-list': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-code': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-code-block': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-document': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-dropcursor': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-gapcursor': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-hard-break': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-heading': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-history': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-horizontal-rule': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13))(@tiptap/pm@2.1.13) - '@tiptap/extension-italic': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-list-item': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-ordered-list': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-paragraph': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-strike': 2.26.1(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - '@tiptap/extension-text': 2.1.13(@tiptap/core@2.1.13(@tiptap/pm@2.1.13)) - transitivePeerDependencies: - - '@tiptap/pm' - '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -8075,34 +5478,18 @@ snapshots: '@types/express-serve-static-core': 5.0.6 '@types/serve-static': 1.15.8 - '@types/hoist-non-react-statics@3.3.7(@types/react@19.1.8)': - dependencies: - '@types/react': 19.1.8 - hoist-non-react-statics: 3.3.2 - '@types/http-errors@2.0.5': {} '@types/js-cookie@3.0.6': {} '@types/json-schema@7.0.15': {} - '@types/linkify-it@5.0.0': {} - - '@types/markdown-it@14.1.2': - dependencies: - '@types/linkify-it': 5.0.0 - '@types/mdurl': 2.0.0 - - '@types/mdurl@2.0.0': {} - '@types/mime@1.3.5': {} '@types/node@22.16.5': dependencies: undici-types: 6.21.0 - '@types/parse-json@4.0.2': {} - '@types/prompts@2.4.9': dependencies: '@types/node': 22.16.5 @@ -8116,16 +5503,10 @@ snapshots: dependencies: '@types/react': 19.1.8 - '@types/react-transition-group@4.4.12(@types/react@19.1.8)': - dependencies: - '@types/react': 19.1.8 - '@types/react@19.1.8': dependencies: csstype: 3.1.3 - '@types/resolve@1.20.2': {} - '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 @@ -8137,8 +5518,6 @@ snapshots: '@types/node': 22.16.5 '@types/send': 0.17.5 - '@types/use-sync-external-store@0.0.3': {} - '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.7.3))(eslint@9.32.0(jiti@2.5.1))(typescript@5.7.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -8191,7 +5570,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.8.2) '@typescript-eslint/visitor-keys': 8.38.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 eslint: 9.32.0(jiti@2.5.1) typescript: 5.8.2 transitivePeerDependencies: @@ -8210,7 +5589,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.8.2) '@typescript-eslint/types': 8.38.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 typescript: 5.8.2 transitivePeerDependencies: - supports-color @@ -8245,7 +5624,7 @@ snapshots: '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.8.2) '@typescript-eslint/utils': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.8.2) - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 eslint: 9.32.0(jiti@2.5.1) ts-api-utils: 2.1.0(typescript@5.8.2) typescript: 5.8.2 @@ -8276,7 +5655,7 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.8.2) '@typescript-eslint/types': 8.38.0 '@typescript-eslint/visitor-keys': 8.38.0 - debug: 4.4.1(supports-color@5.5.0) + debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -8380,60 +5759,6 @@ snapshots: acorn@8.15.0: {} - adminjs@7.8.17(@types/babel__core@7.20.5)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8): - dependencies: - '@adminjs/design-system': 4.1.1(@babel/core@7.28.0)(@types/react@19.1.8)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) - '@babel/core': 7.28.0 - '@babel/parser': 7.28.0 - '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-runtime': 7.28.0(@babel/core@7.28.0) - '@babel/preset-env': 7.28.0(@babel/core@7.28.0) - '@babel/preset-react': 7.27.1(@babel/core@7.28.0) - '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) - '@babel/register': 7.27.1(@babel/core@7.28.0) - '@hello-pangea/dnd': 16.6.0(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@redux-devtools/extension': 3.3.0(redux@4.2.1) - '@rollup/plugin-babel': 6.0.4(@babel/core@7.28.0)(@types/babel__core@7.20.5)(rollup@4.40.2) - '@rollup/plugin-commonjs': 25.0.8(rollup@4.40.2) - '@rollup/plugin-json': 6.1.0(rollup@4.40.2) - '@rollup/plugin-node-resolve': 15.3.1(rollup@4.40.2) - '@rollup/plugin-replace': 5.0.7(rollup@4.40.2) - axios: 1.11.0 - commander: 10.0.1 - flat: 5.0.2 - i18next: 22.5.1 - i18next-browser-languagedetector: 7.2.2 - i18next-http-backend: 2.7.3 - lodash: 4.17.21 - ora: 6.3.1 - prop-types: 15.8.1 - punycode: 2.3.1 - qs: 6.14.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-feather: 2.0.10(react@18.3.1) - react-i18next: 12.3.1(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-is: 18.3.1 - react-redux: 8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) - react-router: 6.30.1(react@18.3.1) - react-router-dom: 6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - redux: 4.2.1 - regenerator-runtime: 0.14.1 - rollup: 4.40.2 - rollup-plugin-esbuild-minify: 1.3.0(rollup@4.40.2) - rollup-plugin-polyfill-node: 0.13.0(rollup@4.40.2) - slash: 5.1.0 - uuid: 9.0.1 - xss: 1.0.15 - transitivePeerDependencies: - - '@types/babel__core' - - '@types/react' - - '@types/react-dom' - - debug - - encoding - - react-native - - supports-color - agent-base@7.1.3: {} ajv@6.12.6: @@ -8445,8 +5770,6 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -8534,70 +5857,10 @@ snapshots: transitivePeerDependencies: - debug - babel-plugin-macros@3.1.0: - dependencies: - '@babel/runtime': 7.28.2 - cosmiconfig: 7.1.0 - resolve: 1.22.10 - - babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.0): - dependencies: - '@babel/compat-data': 7.28.0 - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.0): - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) - core-js-compat: 3.44.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.0): - dependencies: - '@babel/core': 7.28.0 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.0) - transitivePeerDependencies: - - supports-color - - babel-plugin-styled-components@2.1.4(@babel/core@7.28.0)(styled-components@5.3.9(@babel/core@7.28.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(supports-color@5.5.0): - dependencies: - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) - lodash: 4.17.21 - picomatch: 2.3.1 - styled-components: 5.3.9(@babel/core@7.28.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) - transitivePeerDependencies: - - '@babel/core' - - supports-color - balanced-match@1.0.2: {} base64-js@1.5.1: {} - better-auth@1.3.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@better-auth/utils': 0.2.5 - '@better-fetch/fetch': 1.1.18 - '@noble/ciphers': 0.6.0 - '@noble/hashes': 1.8.0 - '@simplewebauthn/browser': 13.1.2 - '@simplewebauthn/server': 13.1.2 - better-call: 1.0.12 - defu: 6.1.4 - jose: 5.10.0 - kysely: 0.28.2 - nanostores: 0.11.4 - zod: 4.0.17 - optionalDependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - better-auth@1.3.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@better-auth/utils': 0.2.5 @@ -8638,12 +5901,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - bl@5.1.0: - dependencies: - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 3.6.2 - body-parser@1.20.3: dependencies: bytes: 3.1.2 @@ -8688,18 +5945,11 @@ snapshots: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.1) - buffer-from@1.1.2: {} - buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - builtin-modules@3.3.0: {} builtin-modules@5.0.0: {} @@ -8744,8 +5994,6 @@ snapshots: camelcase@6.3.0: {} - camelize@1.0.1: {} - caniuse-lite@1.0.30001717: {} caniuse-lite@1.0.30001727: {} @@ -8803,26 +6051,10 @@ snapshots: dependencies: clsx: 2.1.1 - classnames@2.5.1: {} - clean-regexp@1.0.0: dependencies: escape-string-regexp: 1.0.5 - cli-cursor@4.0.0: - dependencies: - restore-cursor: 4.0.0 - - cli-spinners@2.9.2: {} - - clone-deep@4.0.1: - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - - clone@1.0.4: {} - clsx@2.1.1: {} color-convert@2.0.1: @@ -8835,14 +6067,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 - commander@10.0.1: {} - commander@12.1.0: {} - commander@2.20.3: {} - - commondir@1.0.1: {} - concat-map@0.0.1: {} confbox@0.1.8: {} @@ -8855,18 +6081,12 @@ snapshots: content-type@1.0.5: {} - convert-source-map@1.9.0: {} - convert-source-map@2.0.0: {} cookie-signature@1.0.6: {} - cookie-signature@1.0.7: {} - cookie@0.7.1: {} - cookie@0.7.2: {} - cookie@1.0.2: {} core-js-compat@3.44.0: @@ -8878,14 +6098,6 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig@7.1.0: - dependencies: - '@types/parse-json': 4.0.2 - import-fresh: 3.3.1 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.7.3): dependencies: import-fresh: 3.3.1 @@ -8895,36 +6107,14 @@ snapshots: optionalDependencies: typescript: 5.7.3 - crelt@1.0.6: {} - - cross-fetch@4.0.0: - dependencies: - node-fetch: 2.7.0 - transitivePeerDependencies: - - encoding - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - css-box-model@1.2.1: - dependencies: - tiny-invariant: 1.3.3 - - css-color-keywords@1.0.0: {} - - css-to-react-native@3.2.0: - dependencies: - camelize: 1.0.1 - css-color-keywords: 1.0.0 - postcss-value-parser: 4.2.0 - css.escape@1.5.1: {} - cssfilter@0.0.10: {} - cssstyle@4.3.1: dependencies: '@asamuzakjp/css-color': 3.1.7 @@ -8955,10 +6145,6 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 - date-fns@2.30.0: - dependencies: - '@babel/runtime': 7.28.2 - date-fns@4.1.0: {} debug@2.6.9: @@ -8969,6 +6155,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.1: + dependencies: + ms: 2.1.3 + debug@4.4.1(supports-color@5.5.0): dependencies: ms: 2.1.3 @@ -8987,12 +6177,6 @@ snapshots: deep-is@0.1.4: {} - deepmerge@4.3.1: {} - - defaults@1.0.4: - dependencies: - clone: 1.0.4 - define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 @@ -9025,11 +6209,6 @@ snapshots: dom-accessibility-api@0.6.3: {} - dom-helpers@5.2.1: - dependencies: - '@babel/runtime': 7.28.2 - csstype: 3.1.3 - dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -9039,7 +6218,7 @@ snapshots: dotenv@17.2.1: {} - drizzle-orm@0.33.0(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(@types/react@19.1.8)(better-sqlite3@11.10.0)(kysely@0.28.2)(prisma@5.22.0)(react@18.3.1): + drizzle-orm@0.33.0(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.13)(@types/react@19.1.8)(better-sqlite3@11.10.0)(kysely@0.28.2)(prisma@5.22.0)(react@19.1.0): optionalDependencies: '@prisma/client': 5.22.0(prisma@5.22.0) '@types/better-sqlite3': 7.6.13 @@ -9047,7 +6226,7 @@ snapshots: better-sqlite3: 11.10.0 kysely: 0.28.2 prisma: 5.22.0 - react: 18.3.1 + react: 19.1.0 dunder-proto@1.0.1: dependencies: @@ -9344,23 +6523,6 @@ snapshots: dependencies: express: 4.21.2 - express-formidable@1.2.0: - dependencies: - formidable: 1.2.6 - - express-session@1.18.2: - dependencies: - cookie: 0.7.2 - cookie-signature: 1.0.7 - debug: 2.6.9 - depd: 2.0.0 - on-headers: 1.1.0 - parseurl: 1.3.3 - safe-buffer: 5.2.1 - uid-safe: 2.1.5 - transitivePeerDependencies: - - supports-color - express@4.21.2: dependencies: accepts: 1.3.8 @@ -9443,20 +6605,8 @@ snapshots: transitivePeerDependencies: - supports-color - find-cache-dir@2.1.0: - dependencies: - commondir: 1.0.1 - make-dir: 2.1.0 - pkg-dir: 3.0.0 - - find-root@1.1.0: {} - find-up-simple@1.0.1: {} - find-up@3.0.0: - dependencies: - locate-path: 3.0.0 - find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -9467,8 +6617,6 @@ snapshots: flatted: 3.3.3 keyv: 4.5.4 - flat@5.0.2: {} - flatted@3.3.3: {} follow-redirects@1.15.9: {} @@ -9485,8 +6633,6 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 - formidable@1.2.6: {} - forwarded@0.2.0: {} fraction.js@4.3.7: {} @@ -9505,8 +6651,6 @@ snapshots: dependencies: minipass: 3.3.6 - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true @@ -9577,14 +6721,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - globals@11.12.0: {} globals@14.0.0: {} @@ -9604,11 +6740,10 @@ snapshots: graphemer@1.4.0: {} - gud@1.0.0: {} - has-bigints@1.1.0: {} - has-flag@3.0.0: {} + has-flag@3.0.0: + optional: true has-flag@4.0.0: {} @@ -9628,20 +6763,12 @@ snapshots: hasown@2.0.2: dependencies: - function-bind: 1.1.2 - - hoist-non-react-statics@3.3.2: - dependencies: - react-is: 16.13.1 + function-bind: 1.1.2 html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 - html-parse-stringify@3.0.1: - dependencies: - void-elements: 3.1.0 - http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -9666,20 +6793,6 @@ snapshots: husky@9.1.7: {} - i18next-browser-languagedetector@7.2.2: - dependencies: - '@babel/runtime': 7.28.2 - - i18next-http-backend@2.7.3: - dependencies: - cross-fetch: 4.0.0 - transitivePeerDependencies: - - encoding - - i18next@22.5.1: - dependencies: - '@babel/runtime': 7.28.2 - iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -9694,8 +6807,6 @@ snapshots: ignore@7.0.5: {} - immutable@4.3.7: {} - import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -9707,11 +6818,6 @@ snapshots: indent-string@5.0.0: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} ini@1.3.8: {} @@ -9755,10 +6861,6 @@ snapshots: is-callable@1.2.7: {} - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - is-data-view@1.0.2: dependencies: call-bound: 1.0.4 @@ -9787,12 +6889,8 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-interactive@2.0.0: {} - is-map@2.0.3: {} - is-module@1.0.0: {} - is-negative-zero@2.0.3: {} is-number-object@1.1.1: @@ -9802,16 +6900,8 @@ snapshots: is-number@7.0.0: {} - is-plain-object@2.0.4: - dependencies: - isobject: 3.0.1 - is-potential-custom-element-name@1.0.1: {} - is-reference@1.2.1: - dependencies: - '@types/estree': 1.0.8 - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -9840,8 +6930,6 @@ snapshots: dependencies: which-typed-array: 1.1.19 - is-unicode-supported@1.3.0: {} - is-weakmap@2.0.2: {} is-weakref@1.1.1: @@ -9857,8 +6945,6 @@ snapshots: isexe@2.0.0: {} - isobject@3.0.1: {} - jiti@2.4.2: {} jiti@2.5.1: {} @@ -9929,14 +7015,10 @@ snapshots: object.assign: 4.1.7 object.values: 1.2.1 - jw-paginate@1.0.4: {} - keyv@4.5.4: dependencies: json-buffer: 3.0.1 - kind-of@6.0.3: {} - kleur@3.0.3: {} kysely@0.28.2: {} @@ -9995,42 +7077,14 @@ snapshots: lines-and-columns@1.2.4: {} - linkify-it@5.0.0: - dependencies: - uc.micro: 2.1.0 - - linkifyjs@4.3.2: {} - - locate-path@3.0.0: - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - locate-path@6.0.0: dependencies: p-locate: 5.0.0 - lodash.debounce@4.0.8: {} - - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} - lodash.reduce@4.6.0: {} - - lodash.startswith@4.2.1: {} - lodash@4.17.21: {} - log-symbols@5.1.0: - dependencies: - chalk: 5.4.1 - is-unicode-supported: 1.3.0 - - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - loupe@3.1.3: {} loupe@3.2.0: {} @@ -10055,28 +7109,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - make-dir@2.1.0: - dependencies: - pify: 4.0.1 - semver: 5.7.2 - - markdown-it@14.1.0: - dependencies: - argparse: 2.0.1 - entities: 4.5.0 - linkify-it: 5.0.0 - mdurl: 2.0.0 - punycode.js: 2.3.1 - uc.micro: 2.1.0 - math-intrinsics@1.1.0: {} - mdurl@2.0.0: {} - media-typer@0.3.0: {} - memoize-one@6.0.0: {} - merge-descriptors@1.0.3: {} merge2@1.4.1: {} @@ -10096,8 +7132,6 @@ snapshots: mime@1.6.0: {} - mimic-fn@2.1.0: {} - mimic-response@3.1.0: {} min-indent@1.0.1: {} @@ -10106,10 +7140,6 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.2 - minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 @@ -10171,10 +7201,6 @@ snapshots: node-fetch-native@1.6.6: {} - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - node-releases@2.0.19: {} normalize-range@0.1.2: {} @@ -10218,16 +7244,10 @@ snapshots: dependencies: ee-first: 1.1.1 - on-headers@1.1.0: {} - once@1.4.0: dependencies: wrappy: 1.0.2 - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -10237,44 +7257,20 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - ora@6.3.1: - dependencies: - chalk: 5.4.1 - cli-cursor: 4.0.0 - cli-spinners: 2.9.2 - is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - stdin-discarder: 0.1.0 - strip-ansi: 7.1.0 - wcwidth: 1.0.1 - - orderedmap@2.1.1: {} - own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 object-keys: 1.1.1 safe-push-apply: 1.0.0 - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - p-locate@3.0.0: - dependencies: - p-limit: 2.3.0 - p-locate@5.0.0: dependencies: p-limit: 3.1.0 - p-try@2.2.0: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -10292,14 +7288,10 @@ snapshots: parseurl@1.3.3: {} - path-exists@3.0.0: {} - path-exists@4.0.0: {} path-key@3.1.1: {} - path-parse@1.0.7: {} - path-to-regexp@0.1.12: {} path-type@4.0.0: {} @@ -10318,14 +7310,6 @@ snapshots: picomatch@4.0.3: {} - pify@4.0.1: {} - - pirates@4.0.7: {} - - pkg-dir@3.0.0: - dependencies: - find-up: 3.0.0 - pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -10334,10 +7318,6 @@ snapshots: pluralize@8.0.0: {} - polished@4.3.1: - dependencies: - '@babel/runtime': 7.28.2 - possible-typed-array-names@1.1.0: {} postcss-value-parser@4.2.0: {} @@ -10401,115 +7381,6 @@ snapshots: kleur: 3.0.3 sisteransi: 1.0.5 - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - prosemirror-changeset@2.3.1: - dependencies: - prosemirror-transform: 1.10.4 - - prosemirror-collab@1.3.1: - dependencies: - prosemirror-state: 1.4.3 - - prosemirror-commands@1.7.1: - dependencies: - prosemirror-model: 1.25.2 - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - - prosemirror-dropcursor@1.8.2: - dependencies: - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - prosemirror-view: 1.40.1 - - prosemirror-gapcursor@1.3.2: - dependencies: - prosemirror-keymap: 1.2.3 - prosemirror-model: 1.25.2 - prosemirror-state: 1.4.3 - prosemirror-view: 1.40.1 - - prosemirror-history@1.4.1: - dependencies: - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - prosemirror-view: 1.40.1 - rope-sequence: 1.3.4 - - prosemirror-inputrules@1.5.0: - dependencies: - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - - prosemirror-keymap@1.2.3: - dependencies: - prosemirror-state: 1.4.3 - w3c-keyname: 2.2.8 - - prosemirror-markdown@1.13.2: - dependencies: - '@types/markdown-it': 14.1.2 - markdown-it: 14.1.0 - prosemirror-model: 1.25.2 - - prosemirror-menu@1.2.5: - dependencies: - crelt: 1.0.6 - prosemirror-commands: 1.7.1 - prosemirror-history: 1.4.1 - prosemirror-state: 1.4.3 - - prosemirror-model@1.25.2: - dependencies: - orderedmap: 2.1.1 - - prosemirror-schema-basic@1.2.4: - dependencies: - prosemirror-model: 1.25.2 - - prosemirror-schema-list@1.5.1: - dependencies: - prosemirror-model: 1.25.2 - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - - prosemirror-state@1.4.3: - dependencies: - prosemirror-model: 1.25.2 - prosemirror-transform: 1.10.4 - prosemirror-view: 1.40.1 - - prosemirror-tables@1.7.1: - dependencies: - prosemirror-keymap: 1.2.3 - prosemirror-model: 1.25.2 - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - prosemirror-view: 1.40.1 - - prosemirror-trailing-node@2.0.9(prosemirror-model@1.25.2)(prosemirror-state@1.4.3)(prosemirror-view@1.40.1): - dependencies: - '@remirror/core-constants': 2.0.2 - escape-string-regexp: 4.0.0 - prosemirror-model: 1.25.2 - prosemirror-state: 1.4.3 - prosemirror-view: 1.40.1 - - prosemirror-transform@1.10.4: - dependencies: - prosemirror-model: 1.25.2 - - prosemirror-view@1.40.1: - dependencies: - prosemirror-model: 1.25.2 - prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.4 - proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -10522,8 +7393,6 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 - punycode.js@2.3.1: {} - punycode@2.3.1: {} pvtsutils@1.3.6: @@ -10536,16 +7405,8 @@ snapshots: dependencies: side-channel: 1.1.0 - qs@6.14.0: - dependencies: - side-channel: 1.1.0 - queue-microtask@1.2.3: {} - raf-schd@4.0.3: {} - - random-bytes@1.0.0: {} - range-parser@1.2.1: {} raw-body@2.5.2: @@ -10567,106 +7428,26 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-currency-input-field@3.10.0(react@18.3.1): - dependencies: - react: 18.3.1 - - react-datepicker@4.25.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@popperjs/core': 2.11.8 - classnames: 2.5.1 - date-fns: 2.30.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-onclickoutside: 6.13.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-popper: 2.3.0(@popperjs/core@2.11.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-day-picker@8.10.1(date-fns@4.1.0)(react@19.1.0): dependencies: date-fns: 4.1.0 react: 19.1.0 - react-dom@18.3.1(react@18.3.1): - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - react-dom@19.1.0(react@19.1.0): dependencies: react: 19.1.0 scheduler: 0.26.0 - react-fast-compare@3.2.2: {} - - react-feather@2.0.10(react@18.3.1): - dependencies: - prop-types: 15.8.1 - react: 18.3.1 - react-hook-form@7.61.1(react@19.1.0): dependencies: react: 19.1.0 - react-i18next@12.3.1(i18next@22.5.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.28.2 - html-parse-stringify: 3.0.1 - i18next: 22.5.1 - react: 18.3.1 - optionalDependencies: - react-dom: 18.3.1(react@18.3.1) - react-icons@5.5.0(react@19.1.0): dependencies: react: 19.1.0 - react-is@16.13.1: {} - react-is@17.0.2: {} - react-is@18.3.1: {} - - react-onclickoutside@6.13.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - react-phone-input-2@2.15.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - classnames: 2.5.1 - lodash.debounce: 4.0.8 - lodash.memoize: 4.1.2 - lodash.reduce: 4.6.0 - lodash.startswith: 4.2.1 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - react-popper@2.3.0(@popperjs/core@2.11.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@popperjs/core': 2.11.8 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-fast-compare: 3.2.2 - warning: 4.0.3 - - react-redux@8.1.3(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1): - dependencies: - '@babel/runtime': 7.28.2 - '@types/hoist-non-react-statics': 3.3.7(@types/react@19.1.8) - '@types/use-sync-external-store': 0.0.3 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - react-is: 18.3.1 - use-sync-external-store: 1.5.0(react@18.3.1) - optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.6(@types/react@19.1.8) - react-dom: 18.3.1(react@18.3.1) - redux: 4.2.1 - react-refresh@0.17.0: {} react-remove-scroll-bar@2.3.8(@types/react@19.1.8)(react@19.1.0): @@ -10688,24 +7469,12 @@ snapshots: optionalDependencies: '@types/react': 19.1.8 - react-router-dom@6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@remix-run/router': 1.23.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-router: 6.30.1(react@18.3.1) - react-router-dom@7.7.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) react-router: 7.7.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-router@6.30.1(react@18.3.1): - dependencies: - '@remix-run/router': 1.23.0 - react: 18.3.1 - react-router@7.7.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: cookie: 1.0.2 @@ -10714,23 +7483,6 @@ snapshots: optionalDependencies: react-dom: 19.1.0(react@19.1.0) - react-select@5.10.2(@types/react@19.1.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.28.2 - '@emotion/cache': 11.14.0 - '@emotion/react': 11.14.0(@types/react@19.1.8)(react@18.3.1) - '@floating-ui/dom': 1.7.2 - '@types/react-transition-group': 4.4.12(@types/react@19.1.8) - memoize-one: 6.0.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - use-isomorphic-layout-effect: 1.2.1(@types/react@19.1.8)(react@18.3.1) - transitivePeerDependencies: - - '@types/react' - - supports-color - react-style-singleton@2.2.3(@types/react@19.1.8)(react@19.1.0): dependencies: get-nonce: 1.0.1 @@ -10739,24 +7491,6 @@ snapshots: optionalDependencies: '@types/react': 19.1.8 - react-text-mask@5.5.0(react@18.3.1): - dependencies: - prop-types: 15.8.1 - react: 18.3.1 - - react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.28.2 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - react@18.3.1: - dependencies: - loose-envify: 1.4.0 - react@19.1.0: {} readable-stream@3.6.2: @@ -10772,10 +7506,6 @@ snapshots: indent-string: 4.0.0 strip-indent: 3.0.0 - redux@4.2.1: - dependencies: - '@babel/runtime': 7.28.2 - refa@0.12.1: dependencies: '@eslint-community/regexpp': 4.12.1 @@ -10791,14 +7521,6 @@ snapshots: get-proto: 1.0.1 which-builtin-type: 1.2.1 - regenerate-unicode-properties@10.2.0: - dependencies: - regenerate: 1.4.2 - - regenerate@1.4.2: {} - - regenerator-runtime@0.14.1: {} - regexp-ast-analysis@0.7.1: dependencies: '@eslint-community/regexpp': 4.12.1 @@ -10817,17 +7539,6 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 - regexpu-core@6.2.0: - dependencies: - regenerate: 1.4.2 - regenerate-unicode-properties: 10.2.0 - regjsgen: 0.8.0 - regjsparser: 0.12.0 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.2.0 - - regjsgen@0.8.0: {} - regjsparser@0.12.0: dependencies: jsesc: 3.0.2 @@ -10836,29 +7547,8 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - restore-cursor@4.0.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - reusify@1.1.0: {} - rollup-plugin-esbuild-minify@1.3.0(rollup@4.40.2): - dependencies: - esbuild: 0.25.4 - rollup: 4.40.2 - - rollup-plugin-polyfill-node@0.13.0(rollup@4.40.2): - dependencies: - '@rollup/plugin-inject': 5.0.5(rollup@4.40.2) - rollup: 4.40.2 - rollup@4.40.2: dependencies: '@types/estree': 1.0.7 @@ -10885,8 +7575,6 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.40.2 fsevents: 2.3.3 - rope-sequence@1.3.4: {} - rou3@0.5.1: {} rrweb-cssom@0.8.0: {} @@ -10922,10 +7610,6 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.23.2: - dependencies: - loose-envify: 1.4.0 - scheduler@0.26.0: {} scslre@0.3.0: @@ -10934,8 +7618,6 @@ snapshots: refa: 0.12.1 regexp-ast-analysis: 0.7.1 - semver@5.7.2: {} - semver@6.3.1: {} semver@7.7.2: {} @@ -10993,12 +7675,6 @@ snapshots: setprototypeof@1.2.0: {} - shallow-clone@3.0.1: - dependencies: - kind-of: 6.0.3 - - shallowequal@1.1.0: {} - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -11035,8 +7711,6 @@ snapshots: siginfo@2.0.0: {} - signal-exit@3.0.7: {} - simple-concat@1.0.1: {} simple-get@4.0.1: @@ -11047,8 +7721,6 @@ snapshots: sisteransi@1.0.5: {} - slash@5.1.0: {} - snake-case@3.0.4: dependencies: dot-case: 3.0.4 @@ -11056,25 +7728,12 @@ snapshots: source-map-js@1.2.1: {} - source-map-support@0.5.21: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.5.7: {} - - source-map@0.6.1: {} - stackback@0.0.2: {} statuses@2.0.1: {} std-env@3.9.0: {} - stdin-discarder@0.1.0: - dependencies: - bl: 5.1.0 - stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -11107,10 +7766,6 @@ snapshots: dependencies: safe-buffer: 5.2.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -11127,52 +7782,15 @@ snapshots: dependencies: js-tokens: 9.0.1 - styled-components@5.3.9(@babel/core@7.28.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1): - dependencies: - '@babel/helper-module-imports': 7.27.1(supports-color@5.5.0) - '@babel/traverse': 7.28.0(supports-color@5.5.0) - '@emotion/is-prop-valid': 1.3.1 - '@emotion/stylis': 0.8.5 - '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.1.4(@babel/core@7.28.0)(styled-components@5.3.9(@babel/core@7.28.0)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(supports-color@5.5.0) - css-to-react-native: 3.2.0 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 18.3.1 - shallowequal: 1.1.0 - supports-color: 5.5.0 - transitivePeerDependencies: - - '@babel/core' - - styled-system@5.1.5: - dependencies: - '@styled-system/background': 5.1.2 - '@styled-system/border': 5.1.5 - '@styled-system/color': 5.1.2 - '@styled-system/core': 5.1.2 - '@styled-system/flexbox': 5.1.2 - '@styled-system/grid': 5.1.2 - '@styled-system/layout': 5.1.2 - '@styled-system/position': 5.1.2 - '@styled-system/shadow': 5.1.2 - '@styled-system/space': 5.1.2 - '@styled-system/typography': 5.1.2 - '@styled-system/variant': 5.1.5 - object-assign: 4.1.1 - - stylis@4.2.0: {} - supports-color@5.5.0: dependencies: has-flag: 3.0.0 + optional: true supports-color@7.2.0: dependencies: has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} - svg-parser@2.0.4: {} symbol-tree@3.2.4: {} @@ -11220,10 +7838,6 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 - text-mask-addons@3.8.0: {} - - tiny-invariant@1.3.3: {} - tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -11233,18 +7847,12 @@ snapshots: fdir: 6.4.6(picomatch@4.0.3) picomatch: 4.0.3 - tinymce@6.8.6: {} - tinypool@1.1.1: {} tinyrainbow@2.0.0: {} tinyspy@4.0.3: {} - tippy.js@6.3.7: - dependencies: - '@popperjs/core': 2.11.8 - tldts-core@6.1.86: {} tldts@6.1.86: @@ -11261,8 +7869,6 @@ snapshots: dependencies: tldts: 6.1.86 - tr46@0.0.3: {} - tr46@5.1.1: dependencies: punycode: 2.3.1 @@ -11389,14 +7995,8 @@ snapshots: typescript@5.8.2: {} - uc.micro@2.1.0: {} - ufo@1.6.1: {} - uid-safe@2.1.5: - dependencies: - random-bytes: 1.0.0 - unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -11408,17 +8008,6 @@ snapshots: undici-types@6.21.0: {} - unicode-canonical-property-names-ecmascript@2.0.1: {} - - unicode-match-property-ecmascript@2.0.0: - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.1 - unicode-property-aliases-ecmascript: 2.1.0 - - unicode-match-property-value-ecmascript@2.2.0: {} - - unicode-property-aliases-ecmascript@2.1.0: {} - universalify@2.0.1: {} unpipe@1.0.0: {} @@ -11446,16 +8035,6 @@ snapshots: optionalDependencies: '@types/react': 19.1.8 - use-isomorphic-layout-effect@1.2.1(@types/react@19.1.8)(react@18.3.1): - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 19.1.8 - - use-memo-one@1.1.3(react@18.3.1): - dependencies: - react: 18.3.1 - use-sidecar@1.1.3(@types/react@19.1.8)(react@19.1.0): dependencies: detect-node-es: 1.1.0 @@ -11464,16 +8043,10 @@ snapshots: optionalDependencies: '@types/react': 19.1.8 - use-sync-external-store@1.5.0(react@18.3.1): - dependencies: - react: 18.3.1 - util-deprecate@1.0.2: {} utils-merge@1.0.1: {} - uuid@9.0.1: {} - vary@1.1.2: {} vite-node@3.2.4(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.3)(yaml@1.10.2): @@ -11577,24 +8150,10 @@ snapshots: - tsx - yaml - void-elements@3.1.0: {} - - w3c-keyname@2.2.8: {} - w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 - warning@4.0.3: - dependencies: - loose-envify: 1.4.0 - - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - - webidl-conversions@3.0.1: {} - webidl-conversions@7.0.0: {} whatwg-encoding@3.1.1: @@ -11608,11 +8167,6 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -11673,18 +8227,14 @@ snapshots: xmlchars@2.2.0: {} - xss@1.0.15: - dependencies: - commander: 2.20.3 - cssfilter: 0.0.10 - yallist@3.1.1: {} yallist@4.0.0: {} yallist@5.0.0: {} - yaml@1.10.2: {} + yaml@1.10.2: + optional: true yocto-queue@0.1.0: {}