Merge pull request #373 from Portabase/dev

Dev
This commit is contained in:
Charles GTE
2026-07-13 17:22:00 +02:00
committed by GitHub
82 changed files with 657 additions and 128 deletions
+3 -1
View File
@@ -46,6 +46,8 @@ public/uploads/*
private/uploads/*
private/keys/*
private/telemetry/*
/.env
seeds/pocket-id/*.db
@@ -64,4 +66,4 @@ certificates
.codex
/docs
.worktrees
.superpowers
.superpowers
+1 -1
View File
@@ -90,7 +90,7 @@ See the [Database Servers documentation](https://portabase.io/docs/agent/db) for
## License
Distributed under the Apache License. See `LICENSE.txt` for more details.
Distributed under the Apache License. See `LICENSE.txt` for more details.
[Docker]: https://img.shields.io/badge/Docker-2496ED?logo=docker&logoColor=fff&style=for-the-badge
+5
View File
@@ -25,6 +25,11 @@
"@hookform/resolvers": "^5.4.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"@onboardjs/react": "1.0.0-rc.5",
"@opentelemetry/api": "^1.9.1",
"@opentelemetry/exporter-metrics-otlp-http": "^0.220.0",
"@opentelemetry/resources": "^2.9.0",
"@opentelemetry/sdk-metrics": "^2.9.0",
"@opentelemetry/semantic-conventions": "^1.42.0",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-avatar": "^1.1.11",
+198 -53
View File
@@ -16,16 +16,16 @@ importers:
version: 12.33.0
'@better-auth/api-key':
specifier: 1.6.11
version: 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(better-auth@1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))
version: 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(better-auth@1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))
'@better-auth/core':
specifier: 1.6.11
version: 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
version: 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/passkey':
specifier: 1.6.11
version: 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))(nanostores@1.3.0)
version: 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))(nanostores@1.3.0)
'@better-auth/sso':
specifier: 1.6.11
version: 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))
version: 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))
'@google-cloud/storage':
specifier: ^7.19.0
version: 7.21.0
@@ -38,6 +38,21 @@ importers:
'@onboardjs/react':
specifier: 1.0.0-rc.5
version: 1.0.0-rc.5(@onboardjs/core@1.0.0-rc.4)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
'@opentelemetry/api':
specifier: ^1.9.1
version: 1.9.1
'@opentelemetry/exporter-metrics-otlp-http':
specifier: ^0.220.0
version: 0.220.0(@opentelemetry/api@1.9.1)
'@opentelemetry/resources':
specifier: ^2.9.0
version: 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/sdk-metrics':
specifier: ^2.9.0
version: 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/semantic-conventions':
specifier: ^1.42.0
version: 1.42.0
'@radix-ui/react-accordion':
specifier: ^1.2.12
version: 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
@@ -115,7 +130,7 @@ importers:
version: 6.4.24
better-auth:
specifier: 1.6.11
version: 1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
version: 1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
canvas-confetti:
specifier: ^1.9.4
version: 1.9.4
@@ -136,10 +151,10 @@ importers:
version: 16.6.1
drizzle-orm:
specifier: 0.45.2
version: 0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
version: 0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
drizzle-zod:
specifier: 0.8.3
version: 0.8.3(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(zod@4.3.6)
version: 0.8.3(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(zod@4.3.6)
googleapis:
specifier: ^170.1.0
version: 170.1.0
@@ -157,10 +172,10 @@ importers:
version: 12.42.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next:
specifier: 16.2.3
version: 16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
version: 16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next-safe-action:
specifier: ^7.10.8
version: 7.10.8(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.3.6)
version: 7.10.8(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.3.6)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
@@ -227,7 +242,7 @@ importers:
version: 6.0.2(react@19.2.7)
'@react-email/preview-server':
specifier: 4.3.2
version: 4.3.2(postcss@8.5.10)
version: 4.3.2(@opentelemetry/api@1.9.1)(postcss@8.5.10)
'@react-email/render':
specifier: ^2.0.8
version: 2.0.9(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
@@ -1990,10 +2005,70 @@ packages:
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
'@opentelemetry/api-logs@0.220.0':
resolution: {integrity: sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w==}
engines: {node: '>=8.0.0'}
'@opentelemetry/api@1.9.1':
resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==}
engines: {node: '>=8.0.0'}
'@opentelemetry/core@2.9.0':
resolution: {integrity: sha512-m2nckMT80NnmjTYSPjJQObBJ+8dgkoajEOUbznL8AHZ3T3yHRk2P7gI1PhEBc1+lOnrYE9UWrWHqJDsmqjmNbw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': '>=1.0.0 <1.10.0'
'@opentelemetry/exporter-metrics-otlp-http@0.220.0':
resolution: {integrity: sha512-Yqt3RBw/bRVncaE9qIIhk4WfjbAQqXuP9FgAaU+IKPndnLEp/cUqZlSC324+bpmduRz7DoTjig8Ub0PeILWXUA==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
'@opentelemetry/otlp-exporter-base@0.220.0':
resolution: {integrity: sha512-CXYo8UD5Mn9YbgebO2EL4wejtA+gxLmLiu6HCk2KH2BR7XhFN6/6p1UlCb23DYCjeYkndevLHuejCCN1yx4+OQ==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
'@opentelemetry/otlp-transformer@0.220.0':
resolution: {integrity: sha512-lXGrv7KXZ0gNH9SVNUaa6vv6phVYGvJxfXAlMbzbakiXru75f5MZl8Z7oqiMMQD77riVHJCFlQvbZs/VVN2/4A==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': ^1.3.0
'@opentelemetry/resources@2.9.0':
resolution: {integrity: sha512-jyA5MBLQ+Dkl3+JsZkUoUvL7yHvU64kLsvpXKarWm6347Sl1t1bXFTFykUePNpT5WH5pm9a2Qtt03iIYQhZ1Fg==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': '>=1.3.0 <1.10.0'
'@opentelemetry/sdk-logs@0.220.0':
resolution: {integrity: sha512-WywcTkQtv2iNmt+6y5Kcd4rzvx9bLVsBa2Nwcmg01IUaBTkTow3W4d9KE5vNBpEDtb9tp21WcRBY/lANRrApYA==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': '>=1.4.0 <1.10.0'
'@opentelemetry/sdk-metrics@2.9.0':
resolution: {integrity: sha512-Xx8RGS4H5XEBl01WuCreMIpiah9cCXMbSkeuIePPdD2cUpq/vUzYmj8E/MK1OsbOc93FuAD4jfn2WOacKwLn7Q==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': '>=1.9.0 <1.10.0'
'@opentelemetry/sdk-trace@2.9.0':
resolution: {integrity: sha512-sGA19HvtrrSKYsseHphluH6j3p6Xa3fqc7c7y8f/7mYWejc1lyDFcpSdD1kYa50HCLUeEo4zA5bW0pniaPszuw==}
engines: {node: ^18.19.0 || >=20.6.0}
peerDependencies:
'@opentelemetry/api': '>=1.3.0 <1.10.0'
'@opentelemetry/semantic-conventions@1.41.1':
resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==}
engines: {node: '>=14'}
'@opentelemetry/semantic-conventions@1.42.0':
resolution: {integrity: sha512-icc5xCzndZfhuJMy5oqk5AvloWquR7jtae74qzpkKkhGp8BivK+oCcEXgGnjCdTfp8hA44l+w8gE8yYJbocJJw==}
engines: {node: '>=14'}
'@peculiar/asn1-android@2.8.0':
resolution: {integrity: sha512-skLbS+IOGv1lUgDqtChr8xvtvEr3HMse/JGBaL2r1J1o/n7a8wqOrovMtlRq/UXLhxvmLaONP67hwtshgzwfzA==}
@@ -7966,75 +8041,77 @@ snapshots:
'@babel/helper-string-parser': 7.29.7
'@babel/helper-validator-identifier': 7.29.7
'@better-auth/api-key@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(better-auth@1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))':
'@better-auth/api-key@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(better-auth@1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
better-auth: 1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
better-auth: 1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
zod: 4.3.6
'@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)':
'@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)':
dependencies:
'@better-auth/utils': 0.4.0
'@better-fetch/fetch': 1.1.21
'@opentelemetry/semantic-conventions': 1.41.1
'@opentelemetry/semantic-conventions': 1.42.0
'@standard-schema/spec': 1.1.0
better-call: 1.3.5(zod@4.3.6)
jose: 6.2.3
kysely: 0.28.17
nanostores: 1.3.0
zod: 4.3.6
optionalDependencies:
'@opentelemetry/api': 1.9.1
'@better-auth/drizzle-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))':
'@better-auth/drizzle-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
optionalDependencies:
drizzle-orm: 0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
drizzle-orm: 0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
'@better-auth/kysely-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(kysely@0.28.17)':
'@better-auth/kysely-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(kysely@0.28.17)':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
optionalDependencies:
kysely: 0.28.17
'@better-auth/memory-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)':
'@better-auth/memory-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
'@better-auth/mongo-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)':
'@better-auth/mongo-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
'@better-auth/passkey@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))(nanostores@1.3.0)':
'@better-auth/passkey@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))(nanostores@1.3.0)':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
'@better-fetch/fetch': 1.1.21
'@simplewebauthn/browser': 13.3.0
'@simplewebauthn/server': 13.3.2
better-auth: 1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
better-auth: 1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
better-call: 1.3.5(zod@4.3.6)
nanostores: 1.3.0
zod: 4.3.6
'@better-auth/prisma-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(prisma@6.7.0(typescript@5.9.3))':
'@better-auth/prisma-adapter@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(prisma@6.7.0(typescript@5.9.3))':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
optionalDependencies:
'@prisma/client': 6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3)
prisma: 6.7.0(typescript@5.9.3)
'@better-auth/sso@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))':
'@better-auth/sso@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-auth@1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(better-call@1.3.5(zod@4.3.6))':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
'@better-fetch/fetch': 1.1.21
better-auth: 1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
better-auth: 1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
better-call: 1.3.5(zod@4.3.6)
fast-xml-parser: 5.9.3
jose: 6.2.3
@@ -8042,9 +8119,9 @@ snapshots:
tldts: 6.1.86
zod: 4.3.6
'@better-auth/telemetry@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)':
'@better-auth/telemetry@1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)':
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/utils': 0.4.0
'@better-fetch/fetch': 1.1.21
@@ -9065,8 +9142,73 @@ snapshots:
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
'@opentelemetry/api-logs@0.220.0':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/api@1.9.1': {}
'@opentelemetry/core@2.9.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/semantic-conventions': 1.41.1
'@opentelemetry/exporter-metrics-otlp-http@0.220.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/otlp-exporter-base': 0.220.0(@opentelemetry/api@1.9.1)
'@opentelemetry/otlp-transformer': 0.220.0(@opentelemetry/api@1.9.1)
'@opentelemetry/resources': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/sdk-metrics': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/otlp-exporter-base@0.220.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/otlp-transformer': 0.220.0(@opentelemetry/api@1.9.1)
'@opentelemetry/otlp-transformer@0.220.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/api-logs': 0.220.0
'@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/resources': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/sdk-logs': 0.220.0(@opentelemetry/api@1.9.1)
'@opentelemetry/sdk-metrics': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/sdk-trace': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/resources@2.9.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/semantic-conventions': 1.41.1
'@opentelemetry/sdk-logs@0.220.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/api-logs': 0.220.0
'@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/resources': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/semantic-conventions': 1.41.1
'@opentelemetry/sdk-metrics@2.9.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/resources': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/sdk-trace@2.9.0(@opentelemetry/api@1.9.1)':
dependencies:
'@opentelemetry/api': 1.9.1
'@opentelemetry/core': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/resources': 2.9.0(@opentelemetry/api@1.9.1)
'@opentelemetry/semantic-conventions': 1.41.1
'@opentelemetry/semantic-conventions@1.41.1': {}
'@opentelemetry/semantic-conventions@1.42.0': {}
'@peculiar/asn1-android@2.8.0':
dependencies:
'@peculiar/asn1-schema': 2.8.0
@@ -10191,7 +10333,7 @@ snapshots:
md-to-react-email: 5.0.6(react@19.2.7)
react: 19.2.7
'@react-email/preview-server@4.3.2(postcss@8.5.10)':
'@react-email/preview-server@4.3.2(@opentelemetry/api@1.9.1)(postcss@8.5.10)':
dependencies:
'@babel/core': 7.26.10
'@babel/parser': 7.27.0
@@ -10217,7 +10359,7 @@ snapshots:
json5: 2.2.3
log-symbols: 4.1.0
module-punycode: punycode@2.3.1
next: 15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
next: 15.5.2(@babel/core@7.26.10)(@opentelemetry/api@1.9.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
node-html-parser: 7.0.1
ora: 5.4.1
pretty-bytes: 6.1.1
@@ -11087,15 +11229,15 @@ snapshots:
before-after-hook@4.0.0: {}
better-auth@1.6.11(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
better-auth@1.6.11(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
dependencies:
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/drizzle-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))
'@better-auth/kysely-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(kysely@0.28.17)
'@better-auth/memory-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)
'@better-auth/mongo-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)
'@better-auth/prisma-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(prisma@6.7.0(typescript@5.9.3))
'@better-auth/telemetry': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)
'@better-auth/core': 1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0)
'@better-auth/drizzle-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))
'@better-auth/kysely-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(kysely@0.28.17)
'@better-auth/memory-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)
'@better-auth/mongo-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)
'@better-auth/prisma-adapter': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(prisma@6.7.0(typescript@5.9.3))
'@better-auth/telemetry': 1.6.11(@better-auth/core@1.6.11(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.1)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)
'@better-auth/utils': 0.4.0
'@better-fetch/fetch': 1.1.21
'@noble/ciphers': 2.2.0
@@ -11109,8 +11251,8 @@ snapshots:
optionalDependencies:
'@prisma/client': 6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3)
drizzle-kit: 0.31.10
drizzle-orm: 0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
next: 16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
drizzle-orm: 0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
next: 16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
pg: 8.22.0
prisma: 6.7.0(typescript@5.9.3)
react: 19.2.7
@@ -11641,17 +11783,18 @@ snapshots:
esbuild: 0.25.12
tsx: 4.22.4
drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)):
drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)):
optionalDependencies:
'@opentelemetry/api': 1.9.1
'@prisma/client': 6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3)
'@types/pg': 8.20.0
kysely: 0.28.17
pg: 8.22.0
prisma: 6.7.0(typescript@5.9.3)
drizzle-zod@0.8.3(drizzle-orm@0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(zod@4.3.6):
drizzle-zod@0.8.3(drizzle-orm@0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3)))(zod@4.3.6):
dependencies:
drizzle-orm: 0.45.2(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
drizzle-orm: 0.45.2(@opentelemetry/api@1.9.1)(@prisma/client@6.7.0(prisma@6.7.0(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.20.0)(kysely@0.28.17)(pg@8.22.0)(prisma@6.7.0(typescript@5.9.3))
zod: 4.3.6
dunder-proto@1.0.1:
@@ -13362,9 +13505,9 @@ snapshots:
dependencies:
type-fest: 2.19.0
next-safe-action@7.10.8(next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.3.6):
next-safe-action@7.10.8(next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.3.6):
dependencies:
next: 16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
next: 16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
optionalDependencies:
@@ -13375,7 +13518,7 @@ snapshots:
react: 19.2.7
react-dom: 19.2.7(react@19.2.7)
next@15.5.2(@babel/core@7.26.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
next@15.5.2(@babel/core@7.26.10)(@opentelemetry/api@1.9.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
'@next/env': 15.5.2
'@swc/helpers': 0.5.15
@@ -13393,12 +13536,13 @@ snapshots:
'@next/swc-linux-x64-musl': 15.5.2
'@next/swc-win32-arm64-msvc': 15.5.2
'@next/swc-win32-x64-msvc': 15.5.2
'@opentelemetry/api': 1.9.1
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
next@16.2.3(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
next@16.2.3(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
dependencies:
'@next/env': 16.2.3
'@swc/helpers': 0.5.15
@@ -13417,6 +13561,7 @@ snapshots:
'@next/swc-linux-x64-musl': 16.2.3
'@next/swc-win32-arm64-msvc': 16.2.3
'@next/swc-win32-x64-msvc': 16.2.3
'@opentelemetry/api': 1.9.1
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
+1 -1
View File
@@ -55,7 +55,7 @@ export function DateTimePicker({ name }: DateTimePickerProps) {
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" className={cn("w-full pl-3 text-left font-normal", !value && "text-muted-foreground")}>
{value ? format(value, "MM/dd/yyyy hh:mm aa") : <span>MM/DD/YYYY hh:mm aa</span>}
{value ? format(value, "dd/MM/yyyy hh:mm aa") : <span>DD/MM/YYYY hh:mm aa</span>}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</PopoverTrigger>
+7
View File
@@ -122,6 +122,11 @@ export const env = createEnv({
.enum(["true", "false"])
.default("false")
.transform((val) => val === "true"),
TELEMETRY: z
.enum(["true", "false"])
.default("true")
.transform((val) => val === "true"),
},
client: {
NEXT_PUBLIC_PROJECT_VERSION: z.string().optional(),
@@ -204,6 +209,8 @@ export const env = createEnv({
DEMO_ENABLED: process.env.DEMO_ENABLED,
TELEMETRY: process.env.TELEMETRY,
},
});
@@ -43,7 +43,7 @@ export const ChannelAddEditModal = ({
}: ChannelAddModalProps) => {
const isMobile = useIsMobile();
const [openInternal, setOpen] = useState(open);
const isLocalSystem = channel?.provider == "local";
const isLocalSystem = channel?.provider === "local";
const isCreate = !Boolean(channel);
@@ -33,7 +33,7 @@ export const EditChannelButton = ({
}: EditChannelButtonProps) => {
const router = useRouter();
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
const isLocalSystem = channel.provider == "local";
const isLocalSystem = channel.provider === "local";
const mutation = useMutation({
@@ -51,10 +51,10 @@ export const EditChannelButton = ({
};
let result: any;
if (kind == "notification") {
if (kind === "notification") {
// @ts-expect-error — payload type varies between notification and storage
result = await updateNotificationChannelAction(payload)
} else if (kind == "storage") {
} else if (kind === "storage") {
// @ts-expect-error — payload type varies between notification and storage
result = await updateStorageChannelAction(payload)
} else {
@@ -224,13 +224,11 @@ export const ChannelForm = ({onSuccessAction, organization, defaultValues, kind}
<div className="flex justify-between mt-4">
<div>
{(!isCreate || kind == "storage") && (
<ChannelTestButton
kind={kind}
organizationId={organization?.id}
channel={form.getValues()}
/>
)}
<ChannelTestButton
kind={kind}
organizationId={organization?.id}
channel={form.getValues()}
/>
</div>
<div className="flex gap-2">
<Button
@@ -13,6 +13,7 @@ import {cn} from "@/lib/utils";
import {StorageChannel} from "@/db/schema/12_storage-channel";
import {ChannelKind} from "@/features/channel/components/channels-helpers";
import type {StorageInput} from "@/features/storages/types";
import type {NotificationChannelFormType} from "@/features/channel/schemas/channel-form.schema";
import {dispatchStorage} from "@/features/storages/utils/storages.dispatch";
@@ -34,7 +35,7 @@ export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestC
message: `We are testing channel ${channel.name}`,
level: 'info',
};
const result = await dispatchNotification(payload, undefined, channel.id, organizationId);
const result = await dispatchNotification(payload, undefined, undefined, organizationId, channel as unknown as NotificationChannelFormType);
if (result.success) {
toast.success(result.message);
@@ -1,49 +1,49 @@
import {UseFormReturn} from "react-hook-form";
import {
NotifierSmtpForm
} from "@/features/channel/components/notifications/smtp.form";
} from "@/features/channel/components/notifications/smtp/smtp.form";
import {
NotifierSlackForm
} from "@/features/channel/components/notifications/slack.form";
} from "@/features/channel/components/notifications/slack/slack.form";
import {
NotifierDiscordForm
} from "@/features/channel/components/notifications/discord.form";
} from "@/features/channel/components/notifications/discord/discord.form";
import {
NotifierTelegramForm
} from "@/features/channel/components/notifications/telegram.form";
} from "@/features/channel/components/notifications/telegram/telegram.form";
import {
NotifierGotifyForm
} from "@/features/channel/components/notifications/gotify.form";
} from "@/features/channel/components/notifications/gotify/gotify.form";
import {
NotifierNtfyForm
} from "@/features/channel/components/notifications/ntfy.form";
} from "@/features/channel/components/notifications/ntfy/ntfy.form";
import {
NotifierWebhookForm
} from "@/features/channel/components/notifications/webhook.form";
} from "@/features/channel/components/notifications/webhook/webhook.form";
import {
NotifierNextcloudForm
} from "@/features/channel/components/notifications/nextcloud.form";
} from "@/features/channel/components/notifications/nextcloud/nextcloud.form";
import {
NotifierPushoverForm
} from "@/features/channel/components/notifications/pushover.form";
} from "@/features/channel/components/notifications/pushover/pushover.form";
import {
notificationProviders,
} from "@/features/channel/components/channels-notification-helper";
import {
NotifierTeamsForm
} from "@/features/channel/components/notifications/teams.form";
} from "@/features/channel/components/notifications/teams/teams.form";
import {storageProviders} from "@/features/channel/components/channels-storage-helper";
import {ForwardRefExoticComponent, JSX, RefAttributes, SVGProps} from "react";
import {LucideProps} from "lucide-react";
import {
StorageS3Form
} from "@/features/channel/components/storages/s3.form";
} from "@/features/channel/components/storages/s3/s3.form";
import {
StorageGoogleDriveForm
} from "@/features/channel/components/storages/google-drive/google-drive.form";
import {
StorageBlobForm
} from "@/features/channel/components/storages/az-blob.form";
} from "@/features/channel/components/storages/az-blob/az-blob.form";
import {
StorageGoogleCloudStorageForm
} from "@/features/channel/components/storages/google-cloud-storage/google-cloud-storage.form";
@@ -0,0 +1 @@
export * from "./discord";
@@ -0,0 +1 @@
export * from "./gotify";
@@ -0,0 +1 @@
export * from "./nextcloud";
@@ -0,0 +1 @@
export * from "./ntfy";
@@ -0,0 +1 @@
export * from "./pushover";
@@ -4,7 +4,7 @@ import {Input} from "@/components/ui/input";
import {Separator} from "@/components/ui/separator";
import {PasswordInput} from "@/components/ui/password-input";
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select";
import {PUSHOVER_PRIORITIES} from "@/features/channel/components/notifications/pushover.schema";
import {PUSHOVER_PRIORITIES} from "@/features/channel/components/notifications/pushover/pushover.schema";
type NotifierPushoverFormProps = {
form: UseFormReturn<any, any, any>;
@@ -0,0 +1 @@
export * from "./slack";
@@ -0,0 +1 @@
export * from "./smtp";
@@ -0,0 +1 @@
export * from "./teams";
@@ -0,0 +1 @@
export * from "./telegram";
@@ -0,0 +1 @@
export * from "./webhook";
@@ -0,0 +1 @@
export * from "./az-blob";
@@ -0,0 +1 @@
export * from "./local";
@@ -0,0 +1 @@
export * from "./s3";
@@ -1,18 +1,18 @@
import {z} from "zod";
import {SlackChannelConfigSchema} from "@/features/channel/components/notifications/slack.schema";
import {SmtpChannelConfigSchema} from "@/features/channel/components/notifications/smtp.schema";
import {DiscordChannelConfigSchema} from "@/features/channel/components/notifications/discord.schema";
import {TelegramChannelConfigSchema} from "@/features/channel/components/notifications/telegram.schema";
import {GotifyChannelConfigSchema} from "@/features/channel/components/notifications/gotify.schema";
import {NtfyChannelConfigSchema} from "@/features/channel/components/notifications/ntfy.schema";
import {WebhookChannelConfigSchema} from "@/features/channel/components/notifications/webhook.schema";
import {NextcloudChannelConfigSchema} from "@/features/channel/components/notifications/nextcloud.schema";
import {PushoverChannelConfigSchema} from "@/features/channel/components/notifications/pushover.schema";
import {S3ChannelConfigSchema} from "@/features/channel/components/storages/s3.schema";
import {SlackChannelConfigSchema} from "@/features/channel/components/notifications/slack/slack.schema";
import {SmtpChannelConfigSchema} from "@/features/channel/components/notifications/smtp/smtp.schema";
import {DiscordChannelConfigSchema} from "@/features/channel/components/notifications/discord/discord.schema";
import {TelegramChannelConfigSchema} from "@/features/channel/components/notifications/telegram/telegram.schema";
import {GotifyChannelConfigSchema} from "@/features/channel/components/notifications/gotify/gotify.schema";
import {NtfyChannelConfigSchema} from "@/features/channel/components/notifications/ntfy/ntfy.schema";
import {WebhookChannelConfigSchema} from "@/features/channel/components/notifications/webhook/webhook.schema";
import {NextcloudChannelConfigSchema} from "@/features/channel/components/notifications/nextcloud/nextcloud.schema";
import {PushoverChannelConfigSchema} from "@/features/channel/components/notifications/pushover/pushover.schema";
import {S3ChannelConfigSchema} from "@/features/channel/components/storages/s3/s3.schema";
import {GoogleDriveChannelConfigSchema} from "@/features/channel/components/storages/google-drive/google-drive.schema";
import {LocalChannelConfigSchema} from "@/features/channel/components/storages/local.schema";
import {TeamsChannelConfigSchema} from "@/features/channel/components/notifications/teams.schema";
import {BlobChannelConfigSchema} from "@/features/channel/components/storages/az-blob.schema";
import {LocalChannelConfigSchema} from "@/features/channel/components/storages/local/local.schema";
import {TeamsChannelConfigSchema} from "@/features/channel/components/notifications/teams/teams.schema";
import {BlobChannelConfigSchema} from "@/features/channel/components/storages/az-blob/az-blob.schema";
import {
GoogleCloudStorageChannelConfigSchema
} from "@/features/channel/components/storages/google-cloud-storage/google-cloud-storage.schema";
@@ -92,7 +92,7 @@ function getOldestLog(logs: HealthcheckLog[]): HealthcheckLog {
}
function formatTime(date: Date): string {
return date.toLocaleTimeString("en-US", {
return date.toLocaleTimeString("en-GB", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
@@ -6,13 +6,15 @@ import * as drizzleDb from "@/db";
import {db} from "@/db";
import {notificationLog} from "@/db/schema/11_notification-log";
import {NotificationChannel} from "@/db/schema/09_notification-channel";
import {NotificationChannelFormType} from "@/features/channel/schemas/channel-form.schema";
import {Json} from "drizzle-zod";
export async function dispatchNotification(
payload: EventPayload,
policyId?: string,
channelId?: string,
organizationId?: string
organizationId?: string,
channelData?: NotificationChannelFormType
): Promise<DispatchResult> {
try {
let channel: NotificationChannel | null = null;
@@ -69,6 +71,10 @@ export async function dispatchNotification(
};
}
if (channelData) {
channel = {...channelData, config: channelData.config as Json};
}
if (!channel) {
return {
success: false,
@@ -95,28 +101,30 @@ export async function dispatchNotification(
channel.id
);
const [log] = await db
.insert(notificationLog)
.values({
channelId: channel.id,
policyId: policyId || null,
organizationId: organizationId || null,
if (!channelData) {
await db
.insert(notificationLog)
.values({
channelId: channel.id,
policyId: policyId || null,
organizationId: organizationId || null,
provider: channel.provider,
providerName: channel.name,
event: payload.event as EventKind,
provider: channel.provider,
providerName: channel.name,
event: payload.event as EventKind,
title: payload.title,
message: payload.message,
level: payload.level,
payload: payload.data || null,
success: result.success,
error: result.success ? null : result.error,
providerResponse: result.response || null,
})
.returning({id: notificationLog.id});
title: payload.title,
message: payload.message,
level: payload.level,
payload: payload.data || null,
success: result.success,
error: result.success ? null : result.error,
providerResponse: result.response || null,
})
.returning({id: notificationLog.id});
}
return {...result, channelId: channel.id};
return {...result, channelId: channel.id ?? ""};
} catch (err: any) {
return {
@@ -19,6 +19,7 @@ import {
OrganizationMemberChangeRoleModal
} from "@/features/organizations/components/organization-member-change-role";
import {MemberWithUser, OrganizationWithMembersAndUsers} from "@/db/schema/03_organization";
import {formatDayOnly} from "@/utils/date-formatting";
type OrganizationMemberCardProps = {
member: MemberWithUser;
@@ -56,7 +57,7 @@ export const OrganizationMemberCard = ({member, organization}: OrganizationMembe
<div className="font-medium">{member.user.name}</div>
<div className="text-sm text-muted-foreground">{member.user.email}</div>
<div
className="text-xs text-muted-foreground">Joined {new Date(member.createdAt).toLocaleDateString()}</div>
className="text-xs text-muted-foreground">Joined {formatDayOnly(member.createdAt)}</div>
</div>
</div>
<div className="flex items-center space-x-2 mt-4 md:mt-0">
@@ -44,7 +44,6 @@ import { Account, Session, User } from "@/db/schema/02_user";
import { Icon } from "@iconify/react";
import Image from "next/image";
import type { AuthProviderConfig } from "@/lib/auth/config";
import { is } from "date-fns/locale";
interface ProfileSecurityProps {
user: User;
@@ -6,6 +6,7 @@ import {Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter} from "@/
import {Button} from "@/components/ui/button";
import {Input} from "@/components/ui/input";
import type {RestorePreviewRow} from "@/features/database/actions/bulk-restore.action";
import {formatLocalizedDate} from "@/utils/date-formatting";
const CONFIRM_WORD = "restore";
@@ -54,7 +55,7 @@ export const BulkRestoreModal = (props: BulkRestoreModalProps) => {
<td className={`p-2 ${r.restorable ? "" : "opacity-50"}`}>{r.name}</td>
<td className="p-2">
{r.restorable
? <span className="text-green-600">{r.backupDate ? new Date(r.backupDate).toLocaleString() : "latest backup"}</span>
? <span className="text-green-600">{r.backupDate ? formatLocalizedDate(r.backupDate) : "latest backup"}</span>
: <span className="text-amber-500">{r.reason ?? "no successful backup"} skipped</span>}
</td>
</tr>
@@ -0,0 +1,22 @@
"use server";
import { z } from "zod";
import { action } from "@/lib/safe-actions/actions";
import { env } from "@/env.mjs";
import { collectRawTelemetry } from "@/features/telemetry/queries/telemetry.queries";
import { getOrCreateInstance } from "@/features/telemetry/services/instance";
import { buildTelemetryPayload } from "@/features/telemetry/services/anonymize";
export const compileTelemetryAction = action
.schema(z.object({}))
.action(async () => {
const [raw, instance] = await Promise.all([
collectRawTelemetry(),
getOrCreateInstance(),
]);
return buildTelemetryPayload(raw, {
secret: env.PROJECT_SECRET,
version: env.NEXT_PUBLIC_PROJECT_VERSION ?? "unknown",
instanceId: instance.id,
});
});
+14
View File
@@ -0,0 +1,14 @@
export const SERVICE_NAME = "portabase-dashboard";
export const TELEMETRY_METER_NAME = "portabase-telemetry";
// NOTE: This token is intentionally in plaintext, it's a write-only telemetry
// ingestion token (send-only, no read access), so it's public by design, just
// like a Sentry DSN or a PostHog public key. Not a leaked secret.
export const OTLP_AUTH_TOKEN =
"4625713e72b4ec4eaac8a93716f3a83a3afc7fe17dfb8424c57aa82c459d4a8e";
export function getOtlpEndpoint(): string {
return process.env.NODE_ENV === "production"
? "https://telemetry.portabase.io"
: "http://localhost:4318"
}
+37
View File
@@ -0,0 +1,37 @@
import cron from "node-cron";
import { logger } from "@/lib/logger";
import { getOrCreateInstance } from "@/features/telemetry/services/instance";
import { runTelemetry } from "@/features/telemetry/run";
import { env } from "@/env.mjs";
const log = logger.child({ module: "telemetry/cron" });
export async function startTelemetryCron(): Promise<void> {
const { schedule, created } = await getOrCreateInstance();
if (created) {
console.warn(
"\n" +
"══════════════════════════════════════════════════════════════════════\n" +
"\n" +
" Portabase sends anonymous, aggregated usage metrics to help us\n" +
" understand how it is used in production. Only counts and enum labels\n" +
" are sent. Never personal data, database contents, names, hosts,\n" +
" credentials or configuration. The instance id is a random UUID,\n" +
" hashed before it ever leaves your server.\n" +
"\n" +
` Details & what we collect: https://portabase.io/privacy\n` +
"\n" +
"══════════════════════════════════════════════════════════════════════" +
"\n",
);
}
cron.schedule(env.NODE_ENV === "production" ? schedule : "* * * * *", async () => {
try {
await runTelemetry();
} catch (err) {
log.error({ job: "cron", name: "telemetryJob", error: err }, "Telemetry Error");
}
});
}
+5
View File
@@ -0,0 +1,5 @@
export { runTelemetry } from "@/features/telemetry/run";
export { startTelemetryCron } from "@/features/telemetry/cron";
export { compileTelemetryAction } from "@/features/telemetry/actions/telemetry.action";
export { getOtlpEndpoint } from "@/features/telemetry/constants";
export type { TelemetryPayload } from "@/features/telemetry/schemas/telemetry.schema";
+43
View File
@@ -0,0 +1,43 @@
import type { Meter } from "@opentelemetry/api";
import { getMeterProvider } from "@/features/telemetry/otel/instrumentation";
import { TELEMETRY_METER_NAME } from "@/features/telemetry/constants";
import type {
DistributionEntry,
TelemetryPayload,
} from "@/features/telemetry/schemas/telemetry.schema";
function recordDistribution(
meter: Meter,
name: string,
attrKey: string,
entries: DistributionEntry[],
): void {
const gauge = meter.createGauge(name);
for (const entry of entries) {
gauge.record(entry.count, { [attrKey]: entry.label });
}
}
export async function exportTelemetry(payload: TelemetryPayload): Promise<void> {
const provider = getMeterProvider(payload.instanceId);
const meter = provider.getMeter(TELEMETRY_METER_NAME);
meter.createGauge("portabase.users.total").record(payload.usersTotal);
meter.createGauge("portabase.organizations.total").record(payload.orgsTotal);
meter.createGauge("portabase.agents.total").record(payload.agentsTotal);
meter.createGauge("portabase.databases.total").record(payload.databasesTotal);
meter
.createGauge("portabase.instance.info")
.record(1, { dashboard_version: payload.dashboardVersion });
meter.createGauge("portabase.encryption.enabled").record(payload.encryptionEnabled ? 1 : 0);
recordDistribution(meter, "portabase.databases.by_type", "db_type", payload.databasesByType);
recordDistribution(meter, "portabase.storage.backends", "backend", payload.storageByBackend);
recordDistribution(meter, "portabase.notification.channels", "channel", payload.notificationsByChannel);
recordDistribution(meter, "portabase.agents.by_version", "agent_version", payload.agentsByVersion);
await provider.forceFlush();
await provider.shutdown();
}
@@ -0,0 +1,25 @@
import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import { env } from "@/env.mjs";
import { getOtlpEndpoint, OTLP_AUTH_TOKEN, SERVICE_NAME } from "@/features/telemetry/constants";
export function getMeterProvider(instanceId: string): MeterProvider {
const exporter = new OTLPMetricExporter({
url: `${getOtlpEndpoint()}/v1/metrics`,
headers: { Authorization: `Bearer ${OTLP_AUTH_TOKEN}` },
});
const reader = new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 24 * 60 * 60 * 1000,
});
return new MeterProvider({
resource: resourceFromAttributes({
[ATTR_SERVICE_NAME]: SERVICE_NAME,
[ATTR_SERVICE_VERSION]: env.NEXT_PUBLIC_PROJECT_VERSION ?? "unknown",
"service.instance.id": instanceId,
}),
readers: [reader],
});
}
@@ -0,0 +1,77 @@
import { and, count, eq, isNull } from "drizzle-orm";
import { db, schemas } from "@/db";
export type RawCount = { key: string | null; count: number };
export type RawTelemetry = {
orgsTotal: number;
usersTotal: number;
agentsTotal: number;
databasesTotal: number;
databasesByType: RawCount[];
storageByBackend: RawCount[];
notificationsByChannel: RawCount[];
agentsByVersion: RawCount[];
encryptionEnabled: boolean;
};
export async function collectRawTelemetry(): Promise<RawTelemetry> {
const [
orgs,
users,
agents,
databases,
databasesByType,
storageByBackend,
notificationsByChannel,
agentsByVersion,
settingRow,
] = await Promise.all([
db
.select({ c: count() })
.from(schemas.organization)
.where(isNull(schemas.organization.deletedAt)),
db.select({ c: count() }).from(schemas.user).where(isNull(schemas.user.deletedAt)),
db
.select({ c: count() })
.from(schemas.agent)
.where(and(isNull(schemas.agent.deletedAt), eq(schemas.agent.isArchived, false))),
db
.select({ c: count() })
.from(schemas.database)
.where(isNull(schemas.database.deletedAt)),
db
.select({ key: schemas.database.dbms, count: count() })
.from(schemas.database)
.where(isNull(schemas.database.deletedAt))
.groupBy(schemas.database.dbms),
db
.select({ key: schemas.storageChannel.provider, count: count() })
.from(schemas.storageChannel)
.where(isNull(schemas.storageChannel.deletedAt))
.groupBy(schemas.storageChannel.provider),
db
.select({ key: schemas.notificationChannel.provider, count: count() })
.from(schemas.notificationChannel)
.where(isNull(schemas.notificationChannel.deletedAt))
.groupBy(schemas.notificationChannel.provider),
db
.select({ key: schemas.agent.version, count: count() })
.from(schemas.agent)
.where(and(isNull(schemas.agent.deletedAt), eq(schemas.agent.isArchived, false)))
.groupBy(schemas.agent.version),
db.select({ encryption: schemas.setting.encryption }).from(schemas.setting).limit(1),
]);
return {
orgsTotal: orgs[0]?.c ?? 0,
usersTotal: users[0]?.c ?? 0,
agentsTotal: agents[0]?.c ?? 0,
databasesTotal: databases[0]?.c ?? 0,
databasesByType,
storageByBackend,
notificationsByChannel,
agentsByVersion,
encryptionEnabled: settingRow[0]?.encryption ?? false,
};
}
+21
View File
@@ -0,0 +1,21 @@
import { logger } from "@/lib/logger";
import { compileTelemetryAction } from "@/features/telemetry/actions/telemetry.action";
import { exportTelemetry } from "@/features/telemetry/otel/export";
const log = logger.child({ module: "telemetry" });
export async function runTelemetry(): Promise<void> {
const result = await compileTelemetryAction({});
const payload = result?.data;
if (!payload) {
log.error(
{ serverError: result?.serverError, validationErrors: result?.validationErrors },
"Telemetry compile failed",
);
return;
}
await exportTelemetry(payload);
log.info({ instanceId: payload.instanceId }, `Telemetry exported (${payload.instanceId})`);
}
@@ -0,0 +1,23 @@
import { z } from "zod";
export const distributionEntrySchema = z.object({
label: z.string(),
count: z.number().int().nonnegative(),
});
export const telemetryPayloadSchema = z.object({
instanceId: z.string(),
dashboardVersion: z.string(),
orgsTotal: z.number().int().nonnegative(),
usersTotal: z.number().int().nonnegative(),
agentsTotal: z.number().int().nonnegative(),
databasesTotal: z.number().int().nonnegative(),
databasesByType: z.array(distributionEntrySchema),
storageByBackend: z.array(distributionEntrySchema),
notificationsByChannel: z.array(distributionEntrySchema),
agentsByVersion: z.array(distributionEntrySchema),
encryptionEnabled: z.boolean(),
});
export type DistributionEntry = z.infer<typeof distributionEntrySchema>;
export type TelemetryPayload = z.infer<typeof telemetryPayloadSchema>;
@@ -0,0 +1,40 @@
import { createHash } from "crypto";
import type { RawTelemetry, RawCount } from "@/features/telemetry/queries/telemetry.queries";
import {
telemetryPayloadSchema,
type DistributionEntry,
type TelemetryPayload,
} from "@/features/telemetry/schemas/telemetry.schema";
export type AnonymizeContext = { secret: string; version: string; instanceId: string };
export function hashInstanceId(instanceId: string, secret: string): string {
return createHash("sha256").update(`${instanceId}${secret}`).digest("hex");
}
function mapDistribution(rows: RawCount[]): DistributionEntry[] {
return rows.map((r) => ({
label: r.key ?? "unknown",
count: r.count,
}));
}
export function buildTelemetryPayload(
raw: RawTelemetry,
ctx: AnonymizeContext,
): TelemetryPayload {
const payload: TelemetryPayload = {
instanceId: hashInstanceId(ctx.instanceId, ctx.secret),
dashboardVersion: ctx.version,
orgsTotal: raw.orgsTotal,
usersTotal: raw.usersTotal,
agentsTotal: raw.agentsTotal,
databasesTotal: raw.databasesTotal,
databasesByType: mapDistribution(raw.databasesByType),
storageByBackend: mapDistribution(raw.storageByBackend),
notificationsByChannel: mapDistribution(raw.notificationsByChannel),
agentsByVersion: mapDistribution(raw.agentsByVersion),
encryptionEnabled: raw.encryptionEnabled,
};
return telemetryPayloadSchema.parse(payload);
}
@@ -0,0 +1,35 @@
import { promises as fs } from "fs";
import path from "path";
import { randomUUID } from "crypto";
import { env } from "@/env.mjs";
export type InstanceData = { id: string; schedule: string; created: boolean };
function randomDailySchedule(): string {
const minute = Math.floor(Math.random() * 60);
const hour = Math.floor(Math.random() * 24);
return `${minute} ${hour} * * *`;
}
export async function getOrCreateInstance(
filePath = path.join(env.PRIVATE_PATH!, "telemetry", "data.json"),
): Promise<InstanceData> {
await fs.mkdir(path.dirname(filePath), { recursive: true });
let data: Partial<InstanceData> = {};
try {
const raw = await fs.readFile(filePath, "utf8");
data = JSON.parse(raw) as Partial<InstanceData>;
} catch {
}
const created = !data.id;
const id = data.id ?? randomUUID();
const schedule = data.schedule ?? randomDailySchedule();
if (data.id !== id || data.schedule !== schedule) {
await fs.writeFile(filePath, JSON.stringify({ id, schedule }, null, 2), { mode: 0o600 });
}
return { id, schedule, created };
}
+1 -1
View File
@@ -7,7 +7,7 @@ const level = (process.env.LOG_LEVEL ?? defaultLevel) as pino.Level;
function getLocalTimestamp() {
const date = new Date();
const formatted = new Intl.DateTimeFormat("en-US", {
const formatted = new Intl.DateTimeFormat("en-GB", {
timeZone: process.env.TZ,
year: "numeric",
month: "2-digit",
+10 -8
View File
@@ -1,23 +1,24 @@
import {formatDistanceToNow} from "date-fns";
/**
* Get user's locale and timezone from the browser
* Detect the user's timezone from the browser (or server during SSR fallback).
*/
const TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone;
const LOCALE = Intl.DateTimeFormat().resolvedOptions().locale;
/**
* Format a date in DD/MM/YYYY HH:mm 24-hour format
* Format a date to DD/MM/YYYY HH:mm in 24-hour format using the en-GB locale.
* en-GB natively orders day before month, which matches the desired DD/MM/YYYY layout
* regardless of the runtime environment (SSR vs client).
*/
export function formatLocalizedDate(date: string | number | Date) {
const d = new Date(date);
return new Intl.DateTimeFormat(LOCALE, {
return new Intl.DateTimeFormat("en-GB", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
hour12: false, // 24-hour format
hour12: false,
timeZone: TIMEZONE,
}).format(d);
}
@@ -37,13 +38,14 @@ export function formatDateLastContact(lastContact: string | number | Date | null
: "Never connected.";
}
export function formatDayOnly(date: Date) {
return new Intl.DateTimeFormat(LOCALE, {
export function formatDayOnly(date: string | number | Date) {
const d = new Date(date);
return new Intl.DateTimeFormat("en-GB", {
day: "2-digit",
month: "2-digit",
year: "numeric",
timeZone: TIMEZONE,
}).format(date);
}).format(d);
}
export function getTodayISODate() {
+6 -1
View File
@@ -1,5 +1,7 @@
import {cleaningHealthcheckLogsJob, cleaningJob, healthcheckAgentAndDatabaseJob, retentionJob} from "@/lib/tasks";
import {logger} from "@/lib/logger";
import { env } from "@/env.mjs";
import { startTelemetryCron } from "@/features/telemetry/cron";
const log = logger.child({module: "init/cron"});
@@ -10,5 +12,8 @@ export async function setupCronJobs() {
cleaningJob.start();
cleaningHealthcheckLogsJob.start();
healthcheckAgentAndDatabaseJob.start();
if (env.TELEMETRY) {
await startTelemetryCron();
}
log.info("==== Cron jobs started ====");
}
}