diff --git a/.env.development b/.env.development
index 602ca4065..a0ff60283 100644
--- a/.env.development
+++ b/.env.development
@@ -60,6 +60,11 @@ STRIPE_SECRET_KEY=sk_test_YOUR_KEY
STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_KEY
STRIPE_WEBHOOK_SECRET=whsec_YOUR_SECRET
+# Brevo Email Service (get key from https://app.brevo.com/settings/keys/api)
+BREVO_API_KEY=
+EMAIL_SENDER_ADDRESS=noreply@manacore.ai
+EMAIL_SENDER_NAME=ManaCore
+
# ============================================
# CHAT PROJECT
# ============================================
diff --git a/.github/workflows/cd-staging.yml b/.github/workflows/cd-staging.yml
index 15e10a72f..aa35e9568 100644
--- a/.github/workflows/cd-staging.yml
+++ b/.github/workflows/cd-staging.yml
@@ -111,6 +111,11 @@ jobs:
JWT_PUBLIC_KEY=${{ secrets.JWT_PUBLIC_KEY }}
JWT_PRIVATE_KEY=${{ secrets.JWT_PRIVATE_KEY }}
+ # Brevo Email Service
+ BREVO_API_KEY=${{ secrets.BREVO_API_KEY }}
+ EMAIL_SENDER_ADDRESS=noreply@manacore.ai
+ EMAIL_SENDER_NAME=ManaCore
+
# Supabase
SUPABASE_URL=${{ secrets.SUPABASE_URL }}
SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }}
diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml
index f54b340ed..6fe02e7d4 100644
--- a/docker-compose.staging.yml
+++ b/docker-compose.staging.yml
@@ -74,6 +74,10 @@ services:
JWT_SECRET: ${JWT_SECRET}
JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY}
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
+ # Brevo Email Service
+ BREVO_API_KEY: ${BREVO_API_KEY}
+ EMAIL_SENDER_ADDRESS: ${EMAIL_SENDER_ADDRESS:-noreply@manacore.ai}
+ EMAIL_SENDER_NAME: ${EMAIL_SENDER_NAME:-ManaCore}
# CORS - Allow all staging web app origins (HTTPS domains + localhost for dev)
CORS_ORIGINS: https://chat.staging.manacore.ai,https://staging.manacore.ai,https://calendar.staging.manacore.ai,https://clock.staging.manacore.ai,https://todo.staging.manacore.ai,http://localhost:3000,http://localhost:5173,http://localhost:5186,http://localhost:5187,http://localhost:5188
ports:
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9a96ca660..78c5f8441 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -116,7 +116,7 @@ importers:
devDependencies:
'@nestjs/cli':
specifier: ^10.4.9
- version: 10.4.9(esbuild@0.19.12)
+ version: 10.4.9(esbuild@0.27.0)
'@nestjs/schematics':
specifier: ^10.2.3
version: 10.2.3(chokidar@3.6.0)(typescript@5.9.3)
@@ -149,7 +149,7 @@ importers:
version: 0.5.21
ts-loader:
specifier: ^9.5.1
- version: 9.5.4(typescript@5.9.3)(webpack@5.97.1(esbuild@0.19.12))
+ version: 9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.27.0))
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3)
@@ -173,14 +173,14 @@ importers:
version: link:../../../../packages/shared-landing-ui
astro:
specifier: ^5.16.0
- version: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
+ version: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
typescript:
specifier: ^5.9.2
version: 5.9.3
devDependencies:
'@astrojs/tailwind':
specifier: ^6.0.2
- version: 6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3))
+ version: 6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3))
'@tailwindcss/typography':
specifier: ^0.5.18
version: 0.5.19(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))
@@ -189,13 +189,13 @@ importers:
version: 20.19.25
eslint:
specifier: ^9.0.0
- version: 9.39.1(jiti@1.21.7)
+ version: 9.39.1(jiti@2.6.1)
eslint-config-prettier:
specifier: ^9.1.0
- version: 9.1.2(eslint@9.39.1(jiti@1.21.7))
+ version: 9.1.2(eslint@9.39.1(jiti@2.6.1))
eslint-plugin-astro:
specifier: ^1.0.0
- version: 1.5.0(eslint@9.39.1(jiti@1.21.7))
+ version: 1.5.0(eslint@9.39.1(jiti@2.6.1))
prettier:
specifier: ^3.6.2
version: 3.6.2
@@ -555,19 +555,19 @@ importers:
version: 18.3.27
'@typescript-eslint/eslint-plugin':
specifier: ^7.7.0
- version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
'@typescript-eslint/parser':
specifier: ^7.7.0
- version: 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ version: 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
dotenv:
specifier: ^16.4.7
version: 16.6.1
eslint:
specifier: ^9.39.1
- version: 9.39.1(jiti@2.6.1)
+ version: 9.39.1(jiti@1.21.7)
eslint-config-universe:
specifier: ^12.0.1
- version: 12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2)(typescript@5.3.3)
+ version: 12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2)(typescript@5.3.3)
prettier:
specifier: ^3.2.5
version: 3.6.2
@@ -4428,7 +4428,7 @@ importers:
version: 1.57.0
jest:
specifier: ^29.0.0
- version: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
+ version: 29.7.0(@types/node@24.10.1)
vitest:
specifier: ^3.0.0
version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
@@ -4467,6 +4467,9 @@ importers:
services/mana-core-auth:
dependencies:
+ '@getbrevo/brevo':
+ specifier: ^3.0.1
+ version: 3.0.1
'@google/generative-ai':
specifier: ^0.24.1
version: 0.24.1
@@ -4548,7 +4551,7 @@ importers:
devDependencies:
'@nestjs/cli':
specifier: ^11.0.0
- version: 11.0.12(@types/node@22.19.1)
+ version: 11.0.12(@types/node@22.19.1)(esbuild@0.19.12)
'@nestjs/schematics':
specifier: ^11.0.0
version: 11.0.9(chokidar@4.0.3)(typescript@5.9.3)
@@ -4602,10 +4605,10 @@ importers:
version: 7.1.4
ts-jest:
specifier: ^29.2.5
- version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3)
+ version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3)
ts-loader:
specifier: ^9.5.1
- version: 9.5.4(typescript@5.9.3)(webpack@5.100.2)
+ version: 9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.19.12))
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3)
@@ -6820,7 +6823,7 @@ packages:
'@expo/bunyan@4.0.1':
resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==}
- engines: {'0': node >=0.10.0}
+ engines: {node: '>=0.10.0'}
'@expo/cli@0.22.26':
resolution: {integrity: sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==}
@@ -7095,6 +7098,9 @@ packages:
'@formatjs/intl-localematcher@0.6.2':
resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==}
+ '@getbrevo/brevo@3.0.1':
+ resolution: {integrity: sha512-BS5hlgb9qPHhXqjV+VbEOciygnsEVZV8BgoX+JYpD+I+R9u3U05y/euqdmk8nATfcEUCUlQq+aWdWOWTF4cEjQ==}
+
'@google/genai@1.30.0':
resolution: {integrity: sha512-3MRcgczBFbUat1wIlZoLJ0vCCfXgm7Qxjh59cZi2X08RgWLtm9hKOspzp7TOg1TV2e26/MLxR2GR5yD5GmBV2w==}
engines: {node: '>=20.0.0'}
@@ -11022,6 +11028,9 @@ packages:
blake3-wasm@2.1.5:
resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
+ bluebird@3.7.2:
+ resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
+
blurhash@2.0.5:
resolution: {integrity: sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==}
@@ -17586,6 +17595,9 @@ packages:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ rewire@7.0.0:
+ resolution: {integrity: sha512-DyyNyzwMtGYgu0Zl/ya0PR/oaunM+VuCuBxCuhYJHHaV0V+YvYa3bBGxb5OZ71vndgmp1pYY8F4YOwQo1siRGw==}
+
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
@@ -20010,16 +20022,6 @@ snapshots:
transitivePeerDependencies:
- ts-node
- '@astrojs/tailwind@6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3))':
- dependencies:
- astro: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
- autoprefixer: 10.4.22(postcss@8.5.6)
- postcss: 8.5.6
- postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3))
- tailwindcss: 3.4.18(tsx@4.20.6)(yaml@2.8.1)
- transitivePeerDependencies:
- - ts-node
-
'@astrojs/tailwind@6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3))':
dependencies:
astro: 5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
@@ -21544,7 +21546,7 @@ snapshots:
'@bcoe/v8-coverage@1.0.2': {}
- '@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@4.2.0))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)':
+ '@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@3.25.76))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)':
dependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.18
@@ -21555,9 +21557,9 @@ snapshots:
nanostores: 1.1.0
zod: 4.2.0
- '@better-auth/telemetry@1.4.4(@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@4.2.0))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0))':
+ '@better-auth/telemetry@1.4.4(@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@3.25.76))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0))':
dependencies:
- '@better-auth/core': 1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@4.2.0))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)
+ '@better-auth/core': 1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@3.25.76))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.18
@@ -22533,7 +22535,7 @@ snapshots:
wrap-ansi: 7.0.0
ws: 8.18.3
optionalDependencies:
- expo-router: 6.0.15(5e7ih2rh6mb55wruwvjljgzihq)
+ expo-router: 6.0.15(jiucxy5ca3jdtbnulaxuc46jdq)
react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
transitivePeerDependencies:
- '@modelcontextprotocol/sdk'
@@ -22687,7 +22689,7 @@ snapshots:
wrap-ansi: 7.0.0
ws: 8.18.3
optionalDependencies:
- expo-router: 6.0.15(nttrd3tw67nnyhowcwgdzipb5e)
+ expo-router: 6.0.15(ohit2up6tuxb3x34brxduivol4)
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
transitivePeerDependencies:
- '@modelcontextprotocol/sdk'
@@ -23463,6 +23465,15 @@ snapshots:
dependencies:
tslib: 2.8.1
+ '@getbrevo/brevo@3.0.1':
+ dependencies:
+ axios: 1.13.2
+ bluebird: 3.7.2
+ rewire: 7.0.0
+ transitivePeerDependencies:
+ - debug
+ - supports-color
+
'@google/genai@1.30.0':
dependencies:
google-auth-library: 10.5.0
@@ -23948,6 +23959,41 @@ snapshots:
jest-util: 30.2.0
slash: 3.0.0
+ '@jest/core@29.7.0':
+ dependencies:
+ '@jest/console': 29.7.0
+ '@jest/reporters': 29.7.0
+ '@jest/test-result': 29.7.0
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 22.19.1
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ exit: 0.1.2
+ graceful-fs: 4.2.11
+ jest-changed-files: 29.7.0
+ jest-config: 29.7.0(@types/node@22.19.1)
+ jest-haste-map: 29.7.0
+ jest-message-util: 29.7.0
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-resolve-dependencies: 29.7.0
+ jest-runner: 29.7.0
+ jest-runtime: 29.7.0
+ jest-snapshot: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ jest-watcher: 29.7.0
+ micromatch: 4.0.8
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-ansi: 6.0.1
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
'@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))':
dependencies:
'@jest/console': 29.7.0
@@ -23983,78 +24029,6 @@ snapshots:
- supports-color
- ts-node
- '@jest/core@29.7.0(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))':
- dependencies:
- '@jest/console': 29.7.0
- '@jest/reporters': 29.7.0
- '@jest/test-result': 29.7.0
- '@jest/transform': 29.7.0
- '@jest/types': 29.6.3
- '@types/node': 22.19.1
- ansi-escapes: 4.3.2
- chalk: 4.1.2
- ci-info: 3.9.0
- exit: 0.1.2
- graceful-fs: 4.2.11
- jest-changed-files: 29.7.0
- jest-config: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
- jest-haste-map: 29.7.0
- jest-message-util: 29.7.0
- jest-regex-util: 29.6.3
- jest-resolve: 29.7.0
- jest-resolve-dependencies: 29.7.0
- jest-runner: 29.7.0
- jest-runtime: 29.7.0
- jest-snapshot: 29.7.0
- jest-util: 29.7.0
- jest-validate: 29.7.0
- jest-watcher: 29.7.0
- micromatch: 4.0.8
- pretty-format: 29.7.0
- slash: 3.0.0
- strip-ansi: 6.0.1
- transitivePeerDependencies:
- - babel-plugin-macros
- - supports-color
- - ts-node
-
- '@jest/core@30.2.0(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))':
- dependencies:
- '@jest/console': 30.2.0
- '@jest/pattern': 30.0.1
- '@jest/reporters': 30.2.0
- '@jest/test-result': 30.2.0
- '@jest/transform': 30.2.0
- '@jest/types': 30.2.0
- '@types/node': 22.19.1
- ansi-escapes: 4.3.2
- chalk: 4.1.2
- ci-info: 4.3.1
- exit-x: 0.2.2
- graceful-fs: 4.2.11
- jest-changed-files: 30.2.0
- jest-config: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
- jest-haste-map: 30.2.0
- jest-message-util: 30.2.0
- jest-regex-util: 30.0.1
- jest-resolve: 30.2.0
- jest-resolve-dependencies: 30.2.0
- jest-runner: 30.2.0
- jest-runtime: 30.2.0
- jest-snapshot: 30.2.0
- jest-util: 30.2.0
- jest-validate: 30.2.0
- jest-watcher: 30.2.0
- micromatch: 4.0.8
- pretty-format: 30.2.0
- slash: 3.0.0
- transitivePeerDependencies:
- - babel-plugin-macros
- - esbuild-register
- - supports-color
- - ts-node
- optional: true
-
'@jest/core@30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))':
dependencies:
'@jest/console': 30.2.0
@@ -24483,32 +24457,6 @@ snapshots:
- uglify-js
- webpack-cli
- '@nestjs/cli@10.4.9(esbuild@0.19.12)':
- dependencies:
- '@angular-devkit/core': 17.3.11(chokidar@3.6.0)
- '@angular-devkit/schematics': 17.3.11(chokidar@3.6.0)
- '@angular-devkit/schematics-cli': 17.3.11(chokidar@3.6.0)
- '@nestjs/schematics': 10.2.3(chokidar@3.6.0)(typescript@5.7.2)
- chalk: 4.1.2
- chokidar: 3.6.0
- cli-table3: 0.6.5
- commander: 4.1.1
- fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.7.2)(webpack@5.97.1(esbuild@0.19.12))
- glob: 10.4.5
- inquirer: 8.2.6
- node-emoji: 1.11.0
- ora: 5.4.1
- tree-kill: 1.2.2
- tsconfig-paths: 4.2.0
- tsconfig-paths-webpack-plugin: 4.2.0
- typescript: 5.7.2
- webpack: 5.97.1(esbuild@0.19.12)
- webpack-node-externals: 3.0.0
- transitivePeerDependencies:
- - esbuild
- - uglify-js
- - webpack-cli
-
'@nestjs/cli@10.4.9(esbuild@0.27.0)':
dependencies:
'@angular-devkit/core': 17.3.11(chokidar@3.6.0)
@@ -24535,7 +24483,7 @@ snapshots:
- uglify-js
- webpack-cli
- '@nestjs/cli@11.0.12(@types/node@22.19.1)':
+ '@nestjs/cli@11.0.12(@types/node@22.19.1)(esbuild@0.19.12)':
dependencies:
'@angular-devkit/core': 19.2.19(chokidar@4.0.3)
'@angular-devkit/schematics': 19.2.19(chokidar@4.0.3)
@@ -24546,14 +24494,14 @@ snapshots:
chokidar: 4.0.3
cli-table3: 0.6.5
commander: 4.1.1
- fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.100.2)
+ fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.100.2(esbuild@0.19.12))
glob: 12.0.0
node-emoji: 1.11.0
ora: 5.4.1
tsconfig-paths: 4.2.0
tsconfig-paths-webpack-plugin: 4.2.0
typescript: 5.9.3
- webpack: 5.100.2
+ webpack: 5.100.2(esbuild@0.19.12)
webpack-node-externals: 3.0.0
transitivePeerDependencies:
- '@types/node'
@@ -27412,7 +27360,7 @@ snapshots:
react-test-renderer: 19.1.0(react@19.1.0)
redent: 3.0.0
- '@testing-library/react-native@13.3.3(jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)':
+ '@testing-library/react-native@13.3.3(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
jest-matcher-utils: 30.2.0
picocolors: 1.1.1
@@ -27422,7 +27370,20 @@ snapshots:
react-test-renderer: 19.1.0(react@19.1.0)
redent: 3.0.0
optionalDependencies:
- jest: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ optional: true
+
+ '@testing-library/react-native@13.3.3(jest@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)':
+ dependencies:
+ jest-matcher-utils: 30.2.0
+ picocolors: 1.1.1
+ pretty-format: 30.2.0
+ react: 19.1.0
+ react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
+ react-test-renderer: 19.1.0(react@19.1.0)
+ redent: 3.0.0
+ optionalDependencies:
+ jest: 30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0))
optional: true
'@testing-library/react-native@13.3.3(jest@30.2.0(@types/node@24.10.1)(esbuild-register@3.6.0(esbuild@0.27.0)))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)':
@@ -27956,16 +27917,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
'@typescript-eslint/scope-manager': 6.21.0
- '@typescript-eslint/type-utils': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
- '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ '@typescript-eslint/type-utils': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
+ '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
'@typescript-eslint/visitor-keys': 6.21.0
debug: 4.4.3
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
@@ -28014,15 +27975,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ '@typescript-eslint/parser': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
'@typescript-eslint/scope-manager': 7.18.0
- '@typescript-eslint/type-utils': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
- '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ '@typescript-eslint/type-utils': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
+ '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
'@typescript-eslint/visitor-keys': 7.18.0
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
@@ -28114,14 +28075,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
'@typescript-eslint/scope-manager': 6.21.0
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3)
'@typescript-eslint/visitor-keys': 6.21.0
debug: 4.4.3
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
optionalDependencies:
typescript: 5.3.3
transitivePeerDependencies:
@@ -28153,14 +28114,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/parser@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
'@typescript-eslint/scope-manager': 7.18.0
'@typescript-eslint/types': 7.18.0
'@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3)
'@typescript-eslint/visitor-keys': 7.18.0
debug: 4.4.3
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
optionalDependencies:
typescript: 5.3.3
transitivePeerDependencies:
@@ -28286,12 +28247,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/type-utils@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/type-utils@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
'@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3)
- '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ '@typescript-eslint/utils': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
debug: 4.4.3
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
ts-api-utils: 1.4.3(typescript@5.3.3)
optionalDependencies:
typescript: 5.3.3
@@ -28322,12 +28283,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/type-utils@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/type-utils@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
'@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3)
- '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ '@typescript-eslint/utils': 7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
debug: 4.4.3
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
ts-api-utils: 1.4.3(typescript@5.3.3)
optionalDependencies:
typescript: 5.3.3
@@ -28509,15 +28470,15 @@ snapshots:
- supports-color
- typescript
- '@typescript-eslint/utils@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/utils@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1))
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7))
'@types/json-schema': 7.0.15
'@types/semver': 7.7.1
'@typescript-eslint/scope-manager': 6.21.0
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3)
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
semver: 7.7.3
transitivePeerDependencies:
- supports-color
@@ -28548,13 +28509,13 @@ snapshots:
- supports-color
- typescript
- '@typescript-eslint/utils@7.18.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)':
+ '@typescript-eslint/utils@7.18.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1))
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7))
'@typescript-eslint/scope-manager': 7.18.0
'@typescript-eslint/types': 7.18.0
'@typescript-eslint/typescript-estree': 7.18.0(typescript@5.3.3)
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
transitivePeerDependencies:
- supports-color
- typescript
@@ -29355,108 +29316,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1):
- dependencies:
- '@astrojs/compiler': 2.13.0
- '@astrojs/internal-helpers': 0.7.5
- '@astrojs/markdown-remark': 6.3.9
- '@astrojs/telemetry': 3.3.0
- '@capsizecss/unpack': 3.0.1
- '@oslojs/encoding': 1.1.0
- '@rollup/pluginutils': 5.3.0(rollup@4.53.3)
- acorn: 8.15.0
- aria-query: 5.3.2
- axobject-query: 4.1.0
- boxen: 8.0.1
- ci-info: 4.3.1
- clsx: 2.1.1
- common-ancestor-path: 1.0.1
- cookie: 1.1.0
- cssesc: 3.0.0
- debug: 4.4.3
- deterministic-object-hash: 2.0.2
- devalue: 5.5.0
- diff: 5.2.0
- dlv: 1.1.3
- dset: 3.1.4
- es-module-lexer: 1.7.0
- esbuild: 0.25.12
- estree-walker: 3.0.3
- flattie: 1.1.1
- fontace: 0.3.1
- github-slugger: 2.0.0
- html-escaper: 3.0.3
- http-cache-semantics: 4.2.0
- import-meta-resolve: 4.2.0
- js-yaml: 4.1.1
- magic-string: 0.30.21
- magicast: 0.5.1
- mrmime: 2.0.1
- neotraverse: 0.6.18
- p-limit: 6.2.0
- p-queue: 8.1.1
- package-manager-detector: 1.5.0
- piccolore: 0.1.3
- picomatch: 4.0.3
- prompts: 2.4.2
- rehype: 13.0.2
- semver: 7.7.3
- shiki: 3.15.0
- smol-toml: 1.5.2
- svgo: 4.0.0
- tinyexec: 1.0.2
- tinyglobby: 0.2.15
- tsconfck: 3.1.6(typescript@5.9.3)
- ultrahtml: 1.6.0
- unifont: 0.6.0
- unist-util-visit: 5.0.0
- unstorage: 1.17.3(@netlify/blobs@10.4.1)(ioredis@5.8.2)
- vfile: 6.0.3
- vite: 6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
- vitefu: 1.1.1(vite@6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))
- xxhash-wasm: 1.1.0
- yargs-parser: 21.1.1
- yocto-spinner: 0.2.3
- zod: 3.25.76
- zod-to-json-schema: 3.25.0(zod@3.25.76)
- zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76)
- optionalDependencies:
- sharp: 0.34.5
- transitivePeerDependencies:
- - '@azure/app-configuration'
- - '@azure/cosmos'
- - '@azure/data-tables'
- - '@azure/identity'
- - '@azure/keyvault-secrets'
- - '@azure/storage-blob'
- - '@capacitor/preferences'
- - '@deno/kv'
- - '@netlify/blobs'
- - '@planetscale/database'
- - '@types/node'
- - '@upstash/redis'
- - '@vercel/blob'
- - '@vercel/functions'
- - '@vercel/kv'
- - aws4fetch
- - db0
- - idb-keyval
- - ioredis
- - jiti
- - less
- - lightningcss
- - rollup
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - supports-color
- - terser
- - tsx
- - typescript
- - uploadthing
- - yaml
-
astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@20.19.25)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1):
dependencies:
'@astrojs/compiler': 2.13.0
@@ -29990,8 +29849,8 @@ snapshots:
better-auth@1.4.4(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.44.0)(vite@7.2.4(@types/node@22.19.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.44.0)(vite@7.2.4(@types/node@22.19.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(svelte@5.44.0):
dependencies:
- '@better-auth/core': 1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@4.2.0))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)
- '@better-auth/telemetry': 1.4.4(@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@4.2.0))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0))
+ '@better-auth/core': 1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@3.25.76))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)
+ '@better-auth/telemetry': 1.4.4(@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@3.25.76))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0))
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.18
'@noble/ciphers': 2.0.1
@@ -30011,8 +29870,8 @@ snapshots:
better-auth@1.4.4(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.44.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.44.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(svelte@5.44.0):
dependencies:
- '@better-auth/core': 1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@4.2.0))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)
- '@better-auth/telemetry': 1.4.4(@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@4.2.0))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0))
+ '@better-auth/core': 1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@3.25.76))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0)
+ '@better-auth/telemetry': 1.4.4(@better-auth/core@1.4.4(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.1.3(zod@3.25.76))(jose@6.1.2)(kysely@0.28.8)(nanostores@1.1.0))
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.18
'@noble/ciphers': 2.0.1
@@ -30062,6 +29921,8 @@ snapshots:
blake3-wasm@2.1.5: {}
+ bluebird@3.7.2: {}
+
blurhash@2.0.5: {}
body-parser@1.20.3:
@@ -30699,13 +30560,13 @@ snapshots:
- supports-color
- ts-node
- create-jest@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)):
+ create-jest@29.7.0(@types/node@24.10.1):
dependencies:
'@jest/types': 29.6.3
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.11
- jest-config: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
+ jest-config: 29.7.0(@types/node@24.10.1)
jest-util: 29.7.0
prompts: 2.4.2
transitivePeerDependencies:
@@ -31763,11 +31624,6 @@ snapshots:
optionalDependencies:
source-map: 0.6.1
- eslint-compat-utils@0.6.5(eslint@9.39.1(jiti@1.21.7)):
- dependencies:
- eslint: 9.39.1(jiti@1.21.7)
- semver: 7.7.3
-
eslint-compat-utils@0.6.5(eslint@9.39.1(jiti@2.6.1)):
dependencies:
eslint: 9.39.1(jiti@2.6.1)
@@ -31778,9 +31634,9 @@ snapshots:
'@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.1(jiti@2.6.1)
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1))
eslint-plugin-expo: 1.0.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1))
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1(jiti@2.6.1))
globals: 16.5.0
@@ -31795,9 +31651,9 @@ snapshots:
'@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)
eslint: 9.39.1(jiti@2.6.1)
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1))
eslint-plugin-expo: 0.1.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1))
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1(jiti@2.6.1))
globals: 16.5.0
@@ -31815,14 +31671,14 @@ snapshots:
dependencies:
eslint: 8.57.1
+ eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@1.21.7)):
+ dependencies:
+ eslint: 9.39.1(jiti@1.21.7)
+
eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@2.6.1)):
dependencies:
eslint: 9.39.1(jiti@2.6.1)
- eslint-config-prettier@9.1.2(eslint@9.39.1(jiti@1.21.7)):
- dependencies:
- eslint: 9.39.1(jiti@1.21.7)
-
eslint-config-prettier@9.1.2(eslint@9.39.1(jiti@2.6.1)):
dependencies:
eslint: 9.39.1(jiti@2.6.1)
@@ -31847,17 +31703,17 @@ snapshots:
- supports-color
- typescript
- eslint-config-universe@12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2)(typescript@5.3.3):
+ eslint-config-universe@12.1.0(@types/eslint@9.6.1)(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2)(typescript@5.3.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
- '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
- eslint: 9.39.1(jiti@2.6.1)
- eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@2.6.1))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1))
- eslint-plugin-node: 11.1.0(eslint@9.39.1(jiti@2.6.1))
- eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2)
- eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1))
- eslint-plugin-react-hooks: 4.6.2(eslint@9.39.1(jiti@2.6.1))
+ '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
+ '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
+ eslint: 9.39.1(jiti@1.21.7)
+ eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@1.21.7))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7))
+ eslint-plugin-node: 11.1.0(eslint@9.39.1(jiti@1.21.7))
+ eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@1.21.7)))(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2)
+ eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@1.21.7))
+ eslint-plugin-react-hooks: 4.6.2(eslint@9.39.1(jiti@1.21.7))
optionalDependencies:
prettier: 3.6.2
transitivePeerDependencies:
@@ -31895,7 +31751,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)):
+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
@@ -31906,22 +31762,7 @@ snapshots:
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
- transitivePeerDependencies:
- - supports-color
-
- eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)):
- dependencies:
- '@nolyfill/is-core-module': 1.0.39
- debug: 4.4.3
- eslint: 9.39.1(jiti@2.6.1)
- get-tsconfig: 4.13.0
- is-bun-module: 2.0.0
- stable-hash: 0.0.5
- tinyglobby: 0.2.15
- unrs-resolver: 1.11.1
- optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
@@ -31935,12 +31776,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@2.6.1)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@1.21.7)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
- eslint: 9.39.1(jiti@2.6.1)
+ '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
+ eslint: 9.39.1(jiti@1.21.7)
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
@@ -31955,39 +31796,25 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3)
eslint: 9.39.1(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.1(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-astro@1.5.0(eslint@9.39.1(jiti@1.21.7)):
- dependencies:
- '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7))
- '@jridgewell/sourcemap-codec': 1.5.5
- '@typescript-eslint/types': 8.48.0
- astro-eslint-parser: 1.2.2
- eslint: 9.39.1(jiti@1.21.7)
- eslint-compat-utils: 0.6.5(eslint@9.39.1(jiti@1.21.7))
- globals: 16.5.0
- postcss: 8.5.6
- postcss-selector-parser: 7.1.0
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
@@ -32011,6 +31838,12 @@ snapshots:
eslint-utils: 2.1.0
regexpp: 3.2.0
+ eslint-plugin-es@3.0.1(eslint@9.39.1(jiti@1.21.7)):
+ dependencies:
+ eslint: 9.39.1(jiti@1.21.7)
+ eslint-utils: 2.1.0
+ regexpp: 3.2.0
+
eslint-plugin-es@3.0.1(eslint@9.39.1(jiti@2.6.1)):
dependencies:
eslint: 9.39.1(jiti@2.6.1)
@@ -32064,7 +31897,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint@9.39.1(jiti@2.6.1)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint@9.39.1(jiti@1.21.7)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -32073,9 +31906,9 @@ snapshots:
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
- eslint: 9.39.1(jiti@2.6.1)
+ eslint: 9.39.1(jiti@1.21.7)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@2.6.1))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1(jiti@1.21.7))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -32087,7 +31920,7 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.3.3)
+ '@typescript-eslint/parser': 6.21.0(eslint@9.39.1(jiti@1.21.7))(typescript@5.3.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -32122,7 +31955,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -32133,7 +31966,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.1(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -32151,7 +31984,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -32162,7 +31995,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.1(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -32190,6 +32023,16 @@ snapshots:
resolve: 1.22.11
semver: 6.3.1
+ eslint-plugin-node@11.1.0(eslint@9.39.1(jiti@1.21.7)):
+ dependencies:
+ eslint: 9.39.1(jiti@1.21.7)
+ eslint-plugin-es: 3.0.1(eslint@9.39.1(jiti@1.21.7))
+ eslint-utils: 2.1.0
+ ignore: 5.3.2
+ minimatch: 3.1.2
+ resolve: 1.22.11
+ semver: 6.3.1
+
eslint-plugin-node@11.1.0(eslint@9.39.1(jiti@2.6.1)):
dependencies:
eslint: 9.39.1(jiti@2.6.1)
@@ -32220,6 +32063,16 @@ snapshots:
'@types/eslint': 9.6.1
eslint-config-prettier: 8.10.2(eslint@8.57.1)
+ eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@1.21.7)))(eslint@9.39.1(jiti@1.21.7))(prettier@3.6.2):
+ dependencies:
+ eslint: 9.39.1(jiti@1.21.7)
+ prettier: 3.6.2
+ prettier-linter-helpers: 1.0.0
+ synckit: 0.11.11
+ optionalDependencies:
+ '@types/eslint': 9.6.1
+ eslint-config-prettier: 8.10.2(eslint@9.39.1(jiti@1.21.7))
+
eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@8.10.2(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2):
dependencies:
eslint: 9.39.1(jiti@2.6.1)
@@ -32244,6 +32097,10 @@ snapshots:
dependencies:
eslint: 8.57.1
+ eslint-plugin-react-hooks@4.6.2(eslint@9.39.1(jiti@1.21.7)):
+ dependencies:
+ eslint: 9.39.1(jiti@1.21.7)
+
eslint-plugin-react-hooks@4.6.2(eslint@9.39.1(jiti@2.6.1)):
dependencies:
eslint: 9.39.1(jiti@2.6.1)
@@ -32274,6 +32131,28 @@ snapshots:
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
+ eslint-plugin-react@7.37.5(eslint@9.39.1(jiti@1.21.7)):
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.findlast: 1.2.5
+ array.prototype.flatmap: 1.3.3
+ array.prototype.tosorted: 1.1.4
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.2.1
+ eslint: 9.39.1(jiti@1.21.7)
+ estraverse: 5.3.0
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.9
+ object.fromentries: 2.0.8
+ object.values: 1.2.1
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.12
+ string.prototype.repeat: 1.0.0
+
eslint-plugin-react@7.37.5(eslint@9.39.1(jiti@2.6.1)):
dependencies:
array-includes: 3.1.9
@@ -33493,7 +33372,54 @@ snapshots:
- supports-color
optional: true
- expo-router@6.0.15(nttrd3tw67nnyhowcwgdzipb5e):
+ expo-router@6.0.15(jiucxy5ca3jdtbnulaxuc46jdq):
+ dependencies:
+ '@expo/metro-runtime': 6.1.2(expo@54.0.25)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ '@expo/schema-utils': 0.1.7
+ '@radix-ui/react-slot': 1.2.0(@types/react@19.2.7)(react@19.1.0)
+ '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@react-navigation/bottom-tabs': 7.8.6(@react-navigation/native@7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ '@react-navigation/native': 7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ '@react-navigation/native-stack': 7.8.0(@react-navigation/native@7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ client-only: 0.0.1
+ debug: 4.4.3
+ escape-string-regexp: 4.0.0
+ expo: 54.0.25(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.15)(react-native-webview@13.12.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ expo-constants: 18.0.10(expo@54.0.25)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))
+ expo-linking: 8.0.9(expo@54.0.25)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ expo-server: 1.0.4
+ fast-deep-equal: 3.1.3
+ invariant: 2.2.4
+ nanoid: 3.3.11
+ query-string: 7.1.3
+ react: 19.1.0
+ react-fast-compare: 3.2.2
+ react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
+ react-native-is-edge-to-edge: 1.2.1(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ react-native-safe-area-context: 5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ react-native-screens: 4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ semver: 7.6.3
+ server-only: 0.0.1
+ sf-symbols-typescript: 2.1.0
+ shallowequal: 1.1.0
+ use-latest-callback: 0.2.6(react@19.1.0)
+ vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ optionalDependencies:
+ '@react-navigation/drawer': 7.7.4(@react-navigation/native@7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-gesture-handler@2.28.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ '@testing-library/react-native': 13.3.3(jest@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)
+ react-dom: 19.1.0(react@19.1.0)
+ react-native-gesture-handler: 2.28.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ react-native-reanimated: 4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
+ react-native-web: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ react-server-dom-webpack: 19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.100.2(esbuild@0.27.0))
+ transitivePeerDependencies:
+ - '@react-native-masked-view/masked-view'
+ - '@types/react'
+ - '@types/react-dom'
+ - supports-color
+ optional: true
+
+ expo-router@6.0.15(ohit2up6tuxb3x34brxduivol4):
dependencies:
'@expo/metro-runtime': 6.1.2(expo@54.0.25)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
'@expo/schema-utils': 0.1.7
@@ -33527,12 +33453,12 @@ snapshots:
vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
optionalDependencies:
'@react-navigation/drawer': 7.7.4(@react-navigation/native@7.1.21(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
- '@testing-library/react-native': 13.3.3(jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)
+ '@testing-library/react-native': 13.3.3(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)
react-dom: 19.1.0(react@19.1.0)
react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
react-native-reanimated: 4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
react-native-web: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- react-server-dom-webpack: 19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.97.1(esbuild@0.19.12))
+ react-server-dom-webpack: 19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.100.2(esbuild@0.19.12))
transitivePeerDependencies:
- '@react-native-masked-view/masked-view'
- '@types/react'
@@ -34410,23 +34336,6 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
- fork-ts-checker-webpack-plugin@9.0.2(typescript@5.7.2)(webpack@5.97.1(esbuild@0.19.12)):
- dependencies:
- '@babel/code-frame': 7.27.1
- chalk: 4.1.2
- chokidar: 3.6.0
- cosmiconfig: 8.3.6(typescript@5.7.2)
- deepmerge: 4.3.1
- fs-extra: 10.1.0
- memfs: 3.5.3
- minimatch: 3.1.2
- node-abort-controller: 3.1.1
- schema-utils: 3.3.0
- semver: 7.7.3
- tapable: 2.3.0
- typescript: 5.7.2
- webpack: 5.97.1(esbuild@0.19.12)
-
fork-ts-checker-webpack-plugin@9.0.2(typescript@5.7.2)(webpack@5.97.1(esbuild@0.27.0)):
dependencies:
'@babel/code-frame': 7.27.1
@@ -34461,6 +34370,23 @@ snapshots:
typescript: 5.7.2
webpack: 5.97.1
+ fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.100.2(esbuild@0.19.12)):
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ chalk: 4.1.2
+ chokidar: 4.0.3
+ cosmiconfig: 8.3.6(typescript@5.9.3)
+ deepmerge: 4.3.1
+ fs-extra: 10.1.0
+ memfs: 3.5.3
+ minimatch: 3.1.2
+ node-abort-controller: 3.1.1
+ schema-utils: 3.3.0
+ semver: 7.7.3
+ tapable: 2.3.0
+ typescript: 5.9.3
+ webpack: 5.100.2(esbuild@0.19.12)
+
fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.100.2(esbuild@0.27.0)):
dependencies:
'@babel/code-frame': 7.27.1
@@ -34478,23 +34404,6 @@ snapshots:
typescript: 5.9.3
webpack: 5.100.2(esbuild@0.27.0)
- fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.100.2):
- dependencies:
- '@babel/code-frame': 7.27.1
- chalk: 4.1.2
- chokidar: 4.0.3
- cosmiconfig: 8.3.6(typescript@5.9.3)
- deepmerge: 4.3.1
- fs-extra: 10.1.0
- memfs: 3.5.3
- minimatch: 3.1.2
- node-abort-controller: 3.1.1
- schema-utils: 3.3.0
- semver: 7.7.3
- tapable: 2.3.0
- typescript: 5.9.3
- webpack: 5.100.2
-
form-data-encoder@1.7.2: {}
form-data@3.0.4:
@@ -35663,16 +35572,16 @@ snapshots:
- supports-color
- ts-node
- jest-cli@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)):
+ jest-cli@29.7.0(@types/node@24.10.1):
dependencies:
- '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
+ '@jest/core': 29.7.0
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
chalk: 4.1.2
- create-jest: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
+ create-jest: 29.7.0(@types/node@24.10.1)
exit: 0.1.2
import-local: 3.2.0
- jest-config: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
+ jest-config: 29.7.0(@types/node@24.10.1)
jest-util: 29.7.0
jest-validate: 29.7.0
yargs: 17.7.2
@@ -35682,15 +35591,15 @@ snapshots:
- supports-color
- ts-node
- jest-cli@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
+ jest-cli@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)):
dependencies:
- '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))
'@jest/test-result': 30.2.0
'@jest/types': 30.2.0
chalk: 4.1.2
exit-x: 0.2.2
import-local: 3.2.0
- jest-config: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest-config: 30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0))
jest-util: 30.2.0
jest-validate: 30.2.0
yargs: 17.7.2
@@ -35779,6 +35688,36 @@ snapshots:
- ts-node
optional: true
+ jest-config@29.7.0(@types/node@22.19.1):
+ dependencies:
+ '@babel/core': 7.28.5
+ '@jest/test-sequencer': 29.7.0
+ '@jest/types': 29.6.3
+ babel-jest: 29.7.0(@babel/core@7.28.5)
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ deepmerge: 4.3.1
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ jest-circus: 29.7.0
+ jest-environment-node: 29.7.0
+ jest-get-type: 29.6.3
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-runner: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 22.19.1
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
jest-config@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
dependencies:
'@babel/core': 7.28.5
@@ -35810,38 +35749,7 @@ snapshots:
- babel-plugin-macros
- supports-color
- jest-config@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)):
- dependencies:
- '@babel/core': 7.28.5
- '@jest/test-sequencer': 29.7.0
- '@jest/types': 29.6.3
- babel-jest: 29.7.0(@babel/core@7.28.5)
- chalk: 4.1.2
- ci-info: 3.9.0
- deepmerge: 4.3.1
- glob: 7.2.3
- graceful-fs: 4.2.11
- jest-circus: 29.7.0
- jest-environment-node: 29.7.0
- jest-get-type: 29.6.3
- jest-regex-util: 29.6.3
- jest-resolve: 29.7.0
- jest-runner: 29.7.0
- jest-util: 29.7.0
- jest-validate: 29.7.0
- micromatch: 4.0.8
- parse-json: 5.2.0
- pretty-format: 29.7.0
- slash: 3.0.0
- strip-json-comments: 3.1.1
- optionalDependencies:
- '@types/node': 22.19.1
- ts-node: 10.9.2(@types/node@24.10.1)(typescript@5.9.3)
- transitivePeerDependencies:
- - babel-plugin-macros
- - supports-color
-
- jest-config@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)):
+ jest-config@29.7.0(@types/node@24.10.1):
dependencies:
'@babel/core': 7.28.5
'@jest/test-sequencer': 29.7.0
@@ -35867,12 +35775,11 @@ snapshots:
strip-json-comments: 3.1.1
optionalDependencies:
'@types/node': 24.10.1
- ts-node: 10.9.2(@types/node@24.10.1)(typescript@5.9.3)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
- jest-config@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
+ jest-config@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)):
dependencies:
'@babel/core': 7.28.5
'@jest/get-type': 30.1.0
@@ -35899,9 +35806,8 @@ snapshots:
slash: 3.0.0
strip-json-comments: 3.1.1
optionalDependencies:
- '@types/node': 22.19.1
- esbuild-register: 3.6.0(esbuild@0.19.12)
- ts-node: 10.9.2(@types/node@22.19.1)(typescript@5.9.3)
+ '@types/node': 20.19.25
+ esbuild-register: 3.6.0(esbuild@0.27.0)
transitivePeerDependencies:
- babel-plugin-macros
- supports-color
@@ -36550,24 +36456,24 @@ snapshots:
- supports-color
- ts-node
- jest@29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)):
+ jest@29.7.0(@types/node@24.10.1):
dependencies:
- '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
+ '@jest/core': 29.7.0
'@jest/types': 29.6.3
import-local: 3.2.0
- jest-cli: 29.7.0(@types/node@24.10.1)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))
+ jest-cli: 29.7.0(@types/node@24.10.1)
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
- supports-color
- ts-node
- jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
+ jest@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)):
dependencies:
- '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))
'@jest/types': 30.2.0
import-local: 3.2.0
- jest-cli: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest-cli: 30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0))
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@@ -40563,6 +40469,16 @@ snapshots:
webpack-sources: 3.3.3
optional: true
+ react-server-dom-webpack@19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.100.2(esbuild@0.19.12)):
+ dependencies:
+ acorn-loose: 8.5.2
+ neo-async: 2.6.2
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ webpack: 5.100.2(esbuild@0.19.12)
+ webpack-sources: 3.3.3
+ optional: true
+
react-server-dom-webpack@19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.100.2(esbuild@0.27.0)):
dependencies:
acorn-loose: 8.5.2
@@ -40572,16 +40488,6 @@ snapshots:
webpack: 5.100.2(esbuild@0.27.0)
webpack-sources: 3.3.3
- react-server-dom-webpack@19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.97.1(esbuild@0.19.12)):
- dependencies:
- acorn-loose: 8.5.2
- neo-async: 2.6.2
- react: 19.1.0
- react-dom: 19.1.0(react@19.1.0)
- webpack: 5.97.1(esbuild@0.19.12)
- webpack-sources: 3.3.3
- optional: true
-
react-style-singleton@2.2.3(@types/react@18.3.27)(react@18.3.1):
dependencies:
get-nonce: 1.0.1
@@ -40934,6 +40840,12 @@ snapshots:
reusify@1.1.0: {}
+ rewire@7.0.0:
+ dependencies:
+ eslint: 8.57.1
+ transitivePeerDependencies:
+ - supports-color
+
rfdc@1.4.1: {}
rimraf@2.6.3:
@@ -41855,14 +41767,14 @@ snapshots:
ansi-escapes: 4.3.2
supports-hyperlinks: 2.3.0
- terser-webpack-plugin@5.3.14(esbuild@0.19.12)(webpack@5.97.1(esbuild@0.19.12)):
+ terser-webpack-plugin@5.3.14(esbuild@0.19.12)(webpack@5.100.2(esbuild@0.19.12)):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
schema-utils: 4.3.3
serialize-javascript: 6.0.2
terser: 5.44.1
- webpack: 5.97.1(esbuild@0.19.12)
+ webpack: 5.100.2(esbuild@0.19.12)
optionalDependencies:
esbuild: 0.19.12
@@ -41888,15 +41800,6 @@ snapshots:
optionalDependencies:
esbuild: 0.27.0
- terser-webpack-plugin@5.3.14(webpack@5.100.2):
- dependencies:
- '@jridgewell/trace-mapping': 0.3.31
- jest-worker: 27.5.1
- schema-utils: 4.3.3
- serialize-javascript: 6.0.2
- terser: 5.44.1
- webpack: 5.100.2
-
terser-webpack-plugin@5.3.14(webpack@5.97.1):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -42058,6 +41961,27 @@ snapshots:
ts-interface-checker@0.1.13: {}
+ ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.19.12)(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3):
+ dependencies:
+ bs-logger: 0.2.6
+ fast-json-stable-stringify: 2.1.0
+ handlebars: 4.7.8
+ jest: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ json5: 2.2.3
+ lodash.memoize: 4.1.2
+ make-error: 1.3.6
+ semver: 7.7.3
+ type-fest: 4.41.0
+ typescript: 5.9.3
+ yargs-parser: 21.1.1
+ optionalDependencies:
+ '@babel/core': 7.28.5
+ '@jest/transform': 30.2.0
+ '@jest/types': 30.2.0
+ babel-jest: 30.2.0(@babel/core@7.28.5)
+ esbuild: 0.19.12
+ jest-util: 30.2.0
+
ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.27.0)(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3):
dependencies:
bs-logger: 0.2.6
@@ -42100,25 +42024,15 @@ snapshots:
esbuild: 0.27.0
jest-util: 30.2.0
- ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3):
+ ts-loader@9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.19.12)):
dependencies:
- bs-logger: 0.2.6
- fast-json-stable-stringify: 2.1.0
- handlebars: 4.7.8
- jest: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
- json5: 2.2.3
- lodash.memoize: 4.1.2
- make-error: 1.3.6
+ chalk: 4.1.2
+ enhanced-resolve: 5.18.3
+ micromatch: 4.0.8
semver: 7.7.3
- type-fest: 4.41.0
+ source-map: 0.7.6
typescript: 5.9.3
- yargs-parser: 21.1.1
- optionalDependencies:
- '@babel/core': 7.28.5
- '@jest/transform': 30.2.0
- '@jest/types': 30.2.0
- babel-jest: 30.2.0(@babel/core@7.28.5)
- jest-util: 30.2.0
+ webpack: 5.100.2(esbuild@0.19.12)
ts-loader@9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.27.0)):
dependencies:
@@ -42130,26 +42044,6 @@ snapshots:
typescript: 5.9.3
webpack: 5.100.2(esbuild@0.27.0)
- ts-loader@9.5.4(typescript@5.9.3)(webpack@5.100.2):
- dependencies:
- chalk: 4.1.2
- enhanced-resolve: 5.18.3
- micromatch: 4.0.8
- semver: 7.7.3
- source-map: 0.7.6
- typescript: 5.9.3
- webpack: 5.100.2
-
- ts-loader@9.5.4(typescript@5.9.3)(webpack@5.97.1(esbuild@0.19.12)):
- dependencies:
- chalk: 4.1.2
- enhanced-resolve: 5.18.3
- micromatch: 4.0.8
- semver: 7.7.3
- source-map: 0.7.6
- typescript: 5.9.3
- webpack: 5.97.1(esbuild@0.19.12)
-
ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
@@ -42756,23 +42650,6 @@ snapshots:
lightningcss: 1.30.2
terser: 5.44.1
- vite@6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1):
- dependencies:
- esbuild: 0.25.12
- fdir: 6.5.0(picomatch@4.0.3)
- picomatch: 4.0.3
- postcss: 8.5.6
- rollup: 4.53.3
- tinyglobby: 0.2.15
- optionalDependencies:
- '@types/node': 20.19.25
- fsevents: 2.3.3
- jiti: 1.21.7
- lightningcss: 1.30.2
- terser: 5.44.1
- tsx: 4.20.6
- yaml: 2.8.1
-
vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1):
dependencies:
esbuild: 0.25.12
@@ -42875,10 +42752,6 @@ snapshots:
tsx: 4.20.6
yaml: 2.8.1
- vitefu@1.1.1(vite@6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)):
- optionalDependencies:
- vite: 6.4.1(@types/node@20.19.25)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
-
vitefu@1.1.1(vite@6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)):
optionalDependencies:
vite: 6.4.1(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
@@ -43135,7 +43008,7 @@ snapshots:
webpack-sources@3.3.3: {}
- webpack@5.100.2:
+ webpack@5.100.2(esbuild@0.19.12):
dependencies:
'@types/eslint-scope': 3.7.7
'@types/estree': 1.0.8
@@ -43159,7 +43032,7 @@ snapshots:
neo-async: 2.6.2
schema-utils: 4.3.3
tapable: 2.3.0
- terser-webpack-plugin: 5.3.14(webpack@5.100.2)
+ terser-webpack-plugin: 5.3.14(esbuild@0.19.12)(webpack@5.100.2(esbuild@0.19.12))
watchpack: 2.4.4
webpack-sources: 3.3.3
transitivePeerDependencies:
@@ -43229,36 +43102,6 @@ snapshots:
- esbuild
- uglify-js
- webpack@5.97.1(esbuild@0.19.12):
- dependencies:
- '@types/eslint-scope': 3.7.7
- '@types/estree': 1.0.8
- '@webassemblyjs/ast': 1.14.1
- '@webassemblyjs/wasm-edit': 1.14.1
- '@webassemblyjs/wasm-parser': 1.14.1
- acorn: 8.15.0
- browserslist: 4.28.0
- chrome-trace-event: 1.0.4
- enhanced-resolve: 5.18.3
- es-module-lexer: 1.7.0
- eslint-scope: 5.1.1
- events: 3.3.0
- glob-to-regexp: 0.4.1
- graceful-fs: 4.2.11
- json-parse-even-better-errors: 2.3.1
- loader-runner: 4.3.1
- mime-types: 2.1.35
- neo-async: 2.6.2
- schema-utils: 3.3.0
- tapable: 2.3.0
- terser-webpack-plugin: 5.3.14(esbuild@0.19.12)(webpack@5.97.1(esbuild@0.19.12))
- watchpack: 2.4.4
- webpack-sources: 3.3.3
- transitivePeerDependencies:
- - '@swc/core'
- - esbuild
- - uglify-js
-
webpack@5.97.1(esbuild@0.27.0):
dependencies:
'@types/eslint-scope': 3.7.7
diff --git a/services/mana-core-auth/.env.example b/services/mana-core-auth/.env.example
index 3a98a8cea..f4a288005 100644
--- a/services/mana-core-auth/.env.example
+++ b/services/mana-core-auth/.env.example
@@ -35,3 +35,10 @@ CREDITS_DAILY_FREE=5
# Rate Limiting
RATE_LIMIT_TTL=60
RATE_LIMIT_MAX=100
+
+# Email (Brevo)
+# Get your API key from: https://app.brevo.com/settings/keys/api
+# Without this key, emails are logged to console only (dev mode)
+BREVO_API_KEY=
+EMAIL_SENDER_ADDRESS=noreply@manacore.app
+EMAIL_SENDER_NAME=ManaCore
diff --git a/services/mana-core-auth/CLAUDE.md b/services/mana-core-auth/CLAUDE.md
index 0b6a09904..8926e36d9 100644
--- a/services/mana-core-auth/CLAUDE.md
+++ b/services/mana-core-auth/CLAUDE.md
@@ -57,6 +57,7 @@ jwt.verify(token, publicKey, { algorithms: ['RS256'] });
- **Auth**: Better Auth with JWT + Organization plugins
- **Database**: PostgreSQL with Drizzle ORM
- **JWT Library**: `jose` (NOT `jsonwebtoken`)
+- **Email**: Brevo (transactional emails)
## Commands
@@ -89,6 +90,10 @@ services/mana-core-auth/
│ │ ├── auth.controller.ts # Auth endpoints
│ │ └── dto/ # Request DTOs
│ ├── credits/ # Credit system
+│ ├── email/
+│ │ ├── email.module.ts # NestJS email module
+│ │ ├── email.service.ts # Email service (for NestJS DI)
+│ │ └── brevo-client.ts # Standalone Brevo client
│ ├── db/
│ │ ├── schema/ # Drizzle schemas
│ │ ├── migrations/ # Generated migration files
@@ -118,6 +123,8 @@ Key points:
| `src/auth/better-auth.config.ts` | Better Auth configuration with JWT + Org plugins |
| `src/auth/services/better-auth.service.ts` | Main auth service - ALL auth logic here |
| `src/auth/types/better-auth.types.ts` | Type definitions (inferred + manual) |
+| `src/email/email.service.ts` | NestJS email service (use in controllers) |
+| `src/email/brevo-client.ts` | Standalone Brevo client (used by Better Auth) |
| `src/db/schema/auth.schema.ts` | User, session, account, jwks tables |
| `docs/AUTHENTICATION_ARCHITECTURE.md` | Comprehensive auth documentation |
| `docs/BETTER_AUTH_TYPING_IMPROVEMENTS.md` | TypeScript typing decisions and limitations |
@@ -133,6 +140,12 @@ JWT_AUDIENCE=manacore
# NOT required for Better Auth JWT (auto-generates EdDSA keys)
# JWT_PRIVATE_KEY=... # DON'T USE - Better Auth uses jwks table
# JWT_PUBLIC_KEY=... # DON'T USE - Better Auth uses jwks table
+
+# Email (Brevo) - optional for development
+# Without BREVO_API_KEY, emails are logged to console
+BREVO_API_KEY=your-api-key-here
+EMAIL_SENDER_ADDRESS=noreply@manacore.app
+EMAIL_SENDER_NAME=ManaCore
```
## Common Tasks
@@ -189,6 +202,60 @@ user: {
},
```
+## Email Configuration
+
+### Overview
+
+Transactional emails are sent via **Brevo** (formerly Sendinblue). The email system supports:
+
+- Password reset emails
+- Organization invitation emails
+- Email verification (future)
+
+### Architecture
+
+There are two email implementations:
+
+1. **`brevo-client.ts`** - Standalone client for Better Auth config (no NestJS DI)
+2. **`email.service.ts`** - NestJS service for use in controllers
+
+Better Auth hooks (`sendResetPassword`, `sendInvitationEmail`) use the standalone client because they run before NestJS DI is available.
+
+### Development Mode
+
+Without `BREVO_API_KEY`, emails are **logged to console** instead of being sent. This is useful for development and testing.
+
+### Production Setup
+
+1. Get your API key from: https://app.brevo.com/settings/keys/api
+2. Set environment variables:
+ ```env
+ BREVO_API_KEY=xkeysib-...
+ EMAIL_SENDER_ADDRESS=noreply@manacore.app
+ EMAIL_SENDER_NAME=ManaCore
+ ```
+3. Verify your sender domain in Brevo dashboard for better deliverability
+
+### Using EmailService in Controllers
+
+```typescript
+import { EmailService } from '../email';
+
+@Controller('api')
+export class MyController {
+ constructor(private emailService: EmailService) {}
+
+ @Post('notify')
+ async sendNotification() {
+ await this.emailService.sendEmail({
+ to: 'user@example.com',
+ subject: 'Notification',
+ htmlContent: '
Hello!
',
+ });
+ }
+}
+```
+
## Debugging
### Token not validating?
diff --git a/services/mana-core-auth/package.json b/services/mana-core-auth/package.json
index 1eb6fb0fc..c8e4843a0 100644
--- a/services/mana-core-auth/package.json
+++ b/services/mana-core-auth/package.json
@@ -21,6 +21,7 @@
"db:studio": "drizzle-kit studio"
},
"dependencies": {
+ "@getbrevo/brevo": "^3.0.1",
"@google/generative-ai": "^0.24.1",
"@nestjs/common": "^10.4.15",
"@nestjs/config": "^3.3.0",
diff --git a/services/mana-core-auth/src/app.module.ts b/services/mana-core-auth/src/app.module.ts
index 0cb0ce214..b6423ab33 100644
--- a/services/mana-core-auth/src/app.module.ts
+++ b/services/mana-core-auth/src/app.module.ts
@@ -5,6 +5,7 @@ import { APP_FILTER } from '@nestjs/core';
import configuration from './config/configuration';
import { AuthModule } from './auth/auth.module';
import { CreditsModule } from './credits/credits.module';
+import { EmailModule } from './email/email.module';
import { FeedbackModule } from './feedback/feedback.module';
import { ReferralsModule } from './referrals/referrals.module';
import { SettingsModule } from './settings/settings.module';
@@ -28,6 +29,7 @@ import { HttpExceptionFilter } from './common/filters/http-exception.filter';
AiModule,
AuthModule,
CreditsModule,
+ EmailModule,
FeedbackModule,
HealthModule,
ReferralsModule,
diff --git a/services/mana-core-auth/src/auth/better-auth.config.ts b/services/mana-core-auth/src/auth/better-auth.config.ts
index 74efe8cd7..24daa9846 100644
--- a/services/mana-core-auth/src/auth/better-auth.config.ts
+++ b/services/mana-core-auth/src/auth/better-auth.config.ts
@@ -22,6 +22,7 @@ import { z } from 'zod';
import { getDb } from '../db/connection';
import { organizations, members, invitations } from '../db/schema/organizations.schema';
import { users, sessions, accounts, verificationTokens, jwks } from '../db/schema/auth.schema';
+import { sendPasswordResetEmail, sendOrganizationInviteEmail } from '../email/brevo-client';
/**
* User role schema with Zod runtime validation
@@ -121,21 +122,18 @@ export function createBetterAuth(databaseUrl: string) {
* - auth.api.requestPasswordReset({ body: { email } }) - Sends reset email
* - auth.api.resetPassword({ body: { newPassword, token } }) - Resets password
*
+ * Uses Brevo API to send transactional emails.
+ * Set BREVO_API_KEY environment variable to enable email sending.
+ * Without the API key, emails are logged to console (dev mode).
+ *
* @see https://www.better-auth.com/docs/authentication/email-password#password-reset
*/
- sendResetPassword: async ({ user, url, token }) => {
- // TODO: Implement email sending service (e.g., Resend, SendGrid)
- // For now, log the reset URL for development
- console.log('[Password Reset] User:', user.email);
- console.log('[Password Reset] Reset URL:', url);
- console.log('[Password Reset] Token:', token);
-
- // In production, send an email like:
- // await sendEmail({
- // to: user.email,
- // subject: 'Reset your password',
- // html: `Reset your password`
- // });
+ sendResetPassword: async ({ user, url }) => {
+ await sendPasswordResetEmail({
+ email: user.email,
+ name: user.name || undefined,
+ resetUrl: url,
+ });
},
},
@@ -201,15 +199,24 @@ export function createBetterAuth(databaseUrl: string) {
// Allow users to create their own organizations
allowUserToCreateOrganization: true,
- // Email invitation handler
+ /**
+ * Email invitation handler
+ *
+ * Uses Brevo API to send organization invitation emails.
+ * Set BREVO_API_KEY environment variable to enable email sending.
+ * Without the API key, emails are logged to console (dev mode).
+ */
async sendInvitationEmail(data) {
- const { email, organization } = data;
+ const { email, organization, role, inviter } = data;
+ const baseUrl = process.env.BASE_URL || 'http://localhost:3001';
+ const inviteUrl = `${baseUrl}/accept-invitation?id=${data.id}`;
- // TODO: Implement email sending service
- console.log('TODO: Send invitation email', {
- to: email,
- organization: organization.name,
- invitationId: data.id,
+ await sendOrganizationInviteEmail({
+ email,
+ organizationName: organization.name,
+ inviterName: inviter?.user?.name || undefined,
+ inviteUrl,
+ role: role || 'member',
});
},
diff --git a/services/mana-core-auth/src/config/configuration.ts b/services/mana-core-auth/src/config/configuration.ts
index 398221369..bf3871ce2 100644
--- a/services/mana-core-auth/src/config/configuration.ts
+++ b/services/mana-core-auth/src/config/configuration.ts
@@ -49,4 +49,10 @@ export default () => ({
ai: {
geminiApiKey: process.env.GOOGLE_GENAI_API_KEY || '',
},
+
+ email: {
+ brevoApiKey: process.env.BREVO_API_KEY || '',
+ senderAddress: process.env.EMAIL_SENDER_ADDRESS || 'noreply@manacore.app',
+ senderName: process.env.EMAIL_SENDER_NAME || 'ManaCore',
+ },
});
diff --git a/services/mana-core-auth/src/email/brevo-client.ts b/services/mana-core-auth/src/email/brevo-client.ts
new file mode 100644
index 000000000..2ff53c871
--- /dev/null
+++ b/services/mana-core-auth/src/email/brevo-client.ts
@@ -0,0 +1,252 @@
+/**
+ * Standalone Brevo Email Client
+ *
+ * This is a standalone email client that can be used outside of NestJS DI,
+ * specifically for Better Auth email handlers which are initialized before
+ * the NestJS application context is available.
+ *
+ * For regular application code, use the EmailService instead.
+ */
+
+import * as brevo from '@getbrevo/brevo';
+
+interface BrevoConfig {
+ apiKey: string | undefined;
+ senderEmail: string;
+ senderName: string;
+}
+
+interface SendEmailParams {
+ to: string;
+ subject: string;
+ htmlContent: string;
+ textContent?: string;
+}
+
+/**
+ * Get Brevo configuration from environment variables
+ */
+function getConfig(): BrevoConfig {
+ return {
+ apiKey: process.env.BREVO_API_KEY,
+ senderEmail: process.env.EMAIL_SENDER_ADDRESS || 'noreply@manacore.app',
+ senderName: process.env.EMAIL_SENDER_NAME || 'ManaCore',
+ };
+}
+
+/**
+ * Send an email using Brevo API
+ *
+ * Falls back to console logging if BREVO_API_KEY is not set
+ */
+export async function sendEmail(params: SendEmailParams): Promise {
+ const config = getConfig();
+ const { to, subject, htmlContent, textContent } = params;
+
+ if (!config.apiKey) {
+ console.log('[Email - DEV MODE] Would send email:');
+ console.log(` To: ${to}`);
+ console.log(` Subject: ${subject}`);
+ console.log(` Content preview: ${htmlContent.substring(0, 200)}...`);
+ return true;
+ }
+
+ try {
+ const apiInstance = new brevo.TransactionalEmailsApi();
+ apiInstance.setApiKey(brevo.TransactionalEmailsApiApiKeys.apiKey, config.apiKey);
+
+ const sendSmtpEmail = new brevo.SendSmtpEmail();
+ sendSmtpEmail.subject = subject;
+ sendSmtpEmail.htmlContent = htmlContent;
+ sendSmtpEmail.textContent = textContent;
+ sendSmtpEmail.sender = {
+ name: config.senderName,
+ email: config.senderEmail,
+ };
+ sendSmtpEmail.to = [{ email: to }];
+
+ const response = await apiInstance.sendTransacEmail(sendSmtpEmail);
+ console.log(`[Email] Sent to ${to}, messageId: ${response.body.messageId}`);
+ return true;
+ } catch (error) {
+ console.error(`[Email] Failed to send to ${to}:`, error);
+ return false;
+ }
+}
+
+/**
+ * Send password reset email
+ */
+export async function sendPasswordResetEmail(params: {
+ email: string;
+ name?: string;
+ resetUrl: string;
+}): Promise {
+ const { email, name, resetUrl } = params;
+ const displayName = name || 'there';
+
+ const htmlContent = `
+
+
+
+
+
+ Reset Your Password
+
+
+
+
+
+
+
+
+ Reset Your Password
+
+ Hi ${displayName},
+
+
+ We received a request to reset the password for your ManaCore account. Click the button below to choose a new password:
+
+
+
+ This link will expire in 1 hour. If you didn't request a password reset, you can safely ignore this email.
+
+
+
+ If the button above doesn't work, copy and paste this URL into your browser:
+ ${resetUrl}
+
+ |
+
+
+ |
+
+ © ${new Date().getFullYear()} ManaCore. All rights reserved.
+
+ |
+
+
+ |
+
+
+
+
+`;
+
+ const textContent = `
+Reset Your Password
+
+Hi ${displayName},
+
+We received a request to reset the password for your ManaCore account.
+
+Reset your password by visiting this link:
+${resetUrl}
+
+This link will expire in 1 hour. If you didn't request a password reset, you can safely ignore this email.
+
+© ${new Date().getFullYear()} ManaCore. All rights reserved.
+`;
+
+ return sendEmail({
+ to: email,
+ subject: 'Reset Your Password - ManaCore',
+ htmlContent,
+ textContent,
+ });
+}
+
+/**
+ * Send organization invitation email
+ */
+export async function sendOrganizationInviteEmail(params: {
+ email: string;
+ organizationName: string;
+ inviterName?: string;
+ inviteUrl: string;
+ role: string;
+}): Promise {
+ const { email, organizationName, inviterName, inviteUrl, role } = params;
+ const inviterText = inviterName ? `${inviterName} has invited you` : 'You have been invited';
+
+ const htmlContent = `
+
+
+
+
+
+ Organization Invitation
+
+
+
+
+
+
+
+
+ You're Invited!
+
+ ${inviterText} to join ${organizationName} on ManaCore as a ${role}.
+
+
+
+ This invitation will expire in 7 days. If you don't want to join this organization, you can safely ignore this email.
+
+
+
+ If the button above doesn't work, copy and paste this URL into your browser:
+ ${inviteUrl}
+
+ |
+
+
+ |
+
+ © ${new Date().getFullYear()} ManaCore. All rights reserved.
+
+ |
+
+
+ |
+
+
+
+
+`;
+
+ const textContent = `
+You're Invited!
+
+${inviterText} to join ${organizationName} on ManaCore as a ${role}.
+
+Accept your invitation by visiting this link:
+${inviteUrl}
+
+This invitation will expire in 7 days. If you don't want to join this organization, you can safely ignore this email.
+
+© ${new Date().getFullYear()} ManaCore. All rights reserved.
+`;
+
+ return sendEmail({
+ to: email,
+ subject: `You're invited to join ${organizationName} - ManaCore`,
+ htmlContent,
+ textContent,
+ });
+}
diff --git a/services/mana-core-auth/src/email/email.module.ts b/services/mana-core-auth/src/email/email.module.ts
new file mode 100644
index 000000000..77a1d3b1c
--- /dev/null
+++ b/services/mana-core-auth/src/email/email.module.ts
@@ -0,0 +1,16 @@
+import { Global, Module } from '@nestjs/common';
+import { EmailService } from './email.service';
+
+/**
+ * Email Module
+ *
+ * Provides transactional email functionality using Brevo.
+ * This module is marked as Global so the EmailService can be
+ * injected anywhere without importing the module.
+ */
+@Global()
+@Module({
+ providers: [EmailService],
+ exports: [EmailService],
+})
+export class EmailModule {}
diff --git a/services/mana-core-auth/src/email/email.service.ts b/services/mana-core-auth/src/email/email.service.ts
new file mode 100644
index 000000000..7a13d3320
--- /dev/null
+++ b/services/mana-core-auth/src/email/email.service.ts
@@ -0,0 +1,262 @@
+/**
+ * Email Service using Brevo API
+ *
+ * Handles transactional emails for:
+ * - Password reset
+ * - Organization invitations
+ * - Email verification (future)
+ *
+ * @see https://developers.brevo.com/reference/sendtransacemail
+ */
+
+import { Injectable, Logger } from '@nestjs/common';
+import { ConfigService } from '@nestjs/config';
+import * as brevo from '@getbrevo/brevo';
+
+export interface SendEmailOptions {
+ to: string;
+ subject: string;
+ htmlContent: string;
+ textContent?: string;
+}
+
+export interface PasswordResetEmailOptions {
+ email: string;
+ name?: string;
+ resetUrl: string;
+}
+
+export interface OrganizationInviteEmailOptions {
+ email: string;
+ organizationName: string;
+ inviterName?: string;
+ inviteUrl: string;
+ role: string;
+}
+
+@Injectable()
+export class EmailService {
+ private readonly logger = new Logger(EmailService.name);
+ private readonly apiInstance: brevo.TransactionalEmailsApi;
+ private readonly senderEmail: string;
+ private readonly senderName: string;
+ private readonly isEnabled: boolean;
+
+ constructor(private readonly configService: ConfigService) {
+ const apiKey = this.configService.get('BREVO_API_KEY');
+ this.senderEmail =
+ this.configService.get('EMAIL_SENDER_ADDRESS') || 'noreply@manacore.app';
+ this.senderName = this.configService.get('EMAIL_SENDER_NAME') || 'ManaCore';
+ this.isEnabled = !!apiKey;
+
+ this.apiInstance = new brevo.TransactionalEmailsApi();
+
+ if (apiKey) {
+ this.apiInstance.setApiKey(brevo.TransactionalEmailsApiApiKeys.apiKey, apiKey);
+ this.logger.log('Brevo email service initialized');
+ } else {
+ this.logger.warn('BREVO_API_KEY not set - emails will be logged to console only');
+ }
+ }
+
+ /**
+ * Send a transactional email
+ */
+ async sendEmail(options: SendEmailOptions): Promise {
+ const { to, subject, htmlContent, textContent } = options;
+
+ if (!this.isEnabled) {
+ this.logger.log('[DEV MODE] Email would be sent:');
+ this.logger.log(` To: ${to}`);
+ this.logger.log(` Subject: ${subject}`);
+ this.logger.log(` Content: ${htmlContent.substring(0, 200)}...`);
+ return true;
+ }
+
+ try {
+ const sendSmtpEmail = new brevo.SendSmtpEmail();
+ sendSmtpEmail.subject = subject;
+ sendSmtpEmail.htmlContent = htmlContent;
+ sendSmtpEmail.textContent = textContent;
+ sendSmtpEmail.sender = {
+ name: this.senderName,
+ email: this.senderEmail,
+ };
+ sendSmtpEmail.to = [{ email: to }];
+
+ const response = await this.apiInstance.sendTransacEmail(sendSmtpEmail);
+ this.logger.log(`Email sent successfully to ${to}, messageId: ${response.body.messageId}`);
+ return true;
+ } catch (error) {
+ this.logger.error(`Failed to send email to ${to}:`, error);
+ return false;
+ }
+ }
+
+ /**
+ * Send password reset email
+ */
+ async sendPasswordResetEmail(options: PasswordResetEmailOptions): Promise {
+ const { email, name, resetUrl } = options;
+ const displayName = name || 'there';
+
+ const htmlContent = `
+
+
+
+
+
+ Reset Your Password
+
+
+
+
+
+
+
+
+ Reset Your Password
+
+ Hi ${displayName},
+
+
+ We received a request to reset the password for your ManaCore account. Click the button below to choose a new password:
+
+
+
+ This link will expire in 1 hour. If you didn't request a password reset, you can safely ignore this email.
+
+
+
+ If the button above doesn't work, copy and paste this URL into your browser:
+ ${resetUrl}
+
+ |
+
+
+ |
+
+ © ${new Date().getFullYear()} ManaCore. All rights reserved.
+
+ |
+
+
+ |
+
+
+
+
+`;
+
+ const textContent = `
+Reset Your Password
+
+Hi ${displayName},
+
+We received a request to reset the password for your ManaCore account.
+
+Reset your password by visiting this link:
+${resetUrl}
+
+This link will expire in 1 hour. If you didn't request a password reset, you can safely ignore this email.
+
+© ${new Date().getFullYear()} ManaCore. All rights reserved.
+`;
+
+ return this.sendEmail({
+ to: email,
+ subject: 'Reset Your Password - ManaCore',
+ htmlContent,
+ textContent,
+ });
+ }
+
+ /**
+ * Send organization invitation email
+ */
+ async sendOrganizationInviteEmail(options: OrganizationInviteEmailOptions): Promise {
+ const { email, organizationName, inviterName, inviteUrl, role } = options;
+ const inviterText = inviterName ? `${inviterName} has invited you` : 'You have been invited';
+
+ const htmlContent = `
+
+
+
+
+
+ Organization Invitation
+
+
+
+
+
+
+
+
+ You're Invited!
+
+ ${inviterText} to join ${organizationName} on ManaCore as a ${role}.
+
+
+
+ This invitation will expire in 7 days. If you don't want to join this organization, you can safely ignore this email.
+
+
+
+ If the button above doesn't work, copy and paste this URL into your browser:
+ ${inviteUrl}
+
+ |
+
+
+ |
+
+ © ${new Date().getFullYear()} ManaCore. All rights reserved.
+
+ |
+
+
+ |
+
+
+
+
+`;
+
+ const textContent = `
+You're Invited!
+
+${inviterText} to join ${organizationName} on ManaCore as a ${role}.
+
+Accept your invitation by visiting this link:
+${inviteUrl}
+
+This invitation will expire in 7 days. If you don't want to join this organization, you can safely ignore this email.
+
+© ${new Date().getFullYear()} ManaCore. All rights reserved.
+`;
+
+ return this.sendEmail({
+ to: email,
+ subject: `You're invited to join ${organizationName} - ManaCore`,
+ htmlContent,
+ textContent,
+ });
+ }
+}
diff --git a/services/mana-core-auth/src/email/index.ts b/services/mana-core-auth/src/email/index.ts
new file mode 100644
index 000000000..2ab32d884
--- /dev/null
+++ b/services/mana-core-auth/src/email/index.ts
@@ -0,0 +1,10 @@
+export { EmailModule } from './email.module';
+export { EmailService } from './email.service';
+export type {
+ SendEmailOptions,
+ PasswordResetEmailOptions,
+ OrganizationInviteEmailOptions,
+} from './email.service';
+
+// Standalone email client for use outside NestJS DI (e.g., Better Auth config)
+export { sendEmail, sendPasswordResetEmail, sendOrganizationInviteEmail } from './brevo-client';