alepha 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
- package/assets/swagger-ui/swagger-ui-standalone-preset.js +1 -1
- package/dist/api/audits/index.browser.js +49 -52
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.d.ts +629 -565
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +206 -98
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.browser.js +44 -44
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +292 -293
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +61 -64
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +61 -59
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +546 -347
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +165 -86
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +242 -230
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/keys/index.js +63 -66
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js +40 -38
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +339 -209
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +108 -60
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/oauth/index.d.ts +190 -78
- package/dist/api/oauth/index.d.ts.map +1 -1
- package/dist/api/oauth/index.js +290 -68
- package/dist/api/oauth/index.js.map +1 -1
- package/dist/api/organizations/index.browser.js +14 -14
- package/dist/api/organizations/index.browser.js.map +1 -1
- package/dist/api/organizations/index.d.ts +158 -134
- package/dist/api/organizations/index.d.ts.map +1 -1
- package/dist/api/organizations/index.js +18 -18
- package/dist/api/organizations/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +74 -53
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +607 -513
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +205 -127
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.d.ts +652 -449
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/payments/index.js +159 -93
- package/dist/api/payments/index.js.map +1 -1
- package/dist/api/subscriptions/index.d.ts +1032 -762
- package/dist/api/subscriptions/index.d.ts.map +1 -1
- package/dist/api/subscriptions/index.js +166 -185
- package/dist/api/subscriptions/index.js.map +1 -1
- package/dist/api/users/index.browser.js +48 -71
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +1297 -1109
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +454 -369
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.browser.js +17 -17
- package/dist/api/verifications/index.browser.js.map +1 -1
- package/dist/api/verifications/index.d.ts +169 -157
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +47 -95
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/background/index.d.ts +0 -1
- package/dist/background/index.d.ts.map +1 -1
- package/dist/background/index.js.map +1 -1
- package/dist/background/index.workerd.js.map +1 -1
- package/dist/batch/index.d.ts +0 -1
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js.map +1 -1
- package/dist/bin/index.js +1 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/bucket/index.d.ts +27 -32
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +56 -26
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +52 -24
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cache/core/index.d.ts +4 -6
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +4 -10
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js +4 -10
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/cache/database/index.d.ts +22 -23
- package/dist/cache/database/index.d.ts.map +1 -1
- package/dist/cache/database/index.js +11 -20
- package/dist/cache/database/index.js.map +1 -1
- package/dist/cache/redis/index.d.ts +3 -4
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js +2 -2
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/captcha/index.d.ts.map +1 -1
- package/dist/captcha/index.js +4 -4
- package/dist/captcha/index.js.map +1 -1
- package/dist/cli/config/index.d.ts +0 -1
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/core/index.d.ts +244 -475
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +308 -383
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +3 -9
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js +3 -3
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/i18n/index.d.ts +20 -39
- package/dist/cli/i18n/index.d.ts.map +1 -1
- package/dist/cli/i18n/index.js +51 -17
- package/dist/cli/i18n/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +89 -82
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +27 -33
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/platform-lib/index.d.ts +383 -410
- package/dist/cli/platform-lib/index.d.ts.map +1 -1
- package/dist/cli/platform-lib/index.js +300 -258
- package/dist/cli/platform-lib/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +17 -41
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js +10 -13
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/command/index.d.ts +82 -194
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +160 -563
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +845 -859
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +787 -527
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +845 -859
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +845 -859
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +845 -859
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/crypto/index.browser.js +1 -1
- package/dist/crypto/index.browser.js.map +1 -1
- package/dist/crypto/index.d.ts +3 -4
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js +6 -3
- package/dist/crypto/index.js.map +1 -1
- package/dist/datetime/index.d.ts +12 -2
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +6 -1
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/brevo/index.d.ts +0 -1
- package/dist/email/brevo/index.d.ts.map +1 -1
- package/dist/email/brevo/index.js +4 -4
- package/dist/email/brevo/index.js.map +1 -1
- package/dist/email/cloudflare/index.d.ts +0 -1
- package/dist/email/cloudflare/index.d.ts.map +1 -1
- package/dist/email/cloudflare/index.js +2 -2
- package/dist/email/cloudflare/index.js.map +1 -1
- package/dist/email/core/index.d.ts +15 -7
- package/dist/email/core/index.d.ts.map +1 -1
- package/dist/email/core/index.js +14 -5
- package/dist/email/core/index.js.map +1 -1
- package/dist/email/core/index.workerd.js +5 -1
- package/dist/email/core/index.workerd.js.map +1 -1
- package/dist/email/smtp/index.d.ts +8 -9
- package/dist/email/smtp/index.d.ts.map +1 -1
- package/dist/email/smtp/index.js +702 -479
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.d.ts +1580 -1238
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +11728 -32131
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +13 -9
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +5 -5
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.d.ts +0 -1
- package/dist/lock/redis/index.d.ts.map +1 -1
- package/dist/lock/redis/index.js.map +1 -1
- package/dist/logger/index.d.ts +81 -69
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +123 -56
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +36 -90
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +65 -70
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +54 -40
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +140 -106
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +145 -150
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +144 -109
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js +64 -54
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +36 -76
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js +67 -57
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +62 -75
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js +48 -71
- package/dist/queue/core/index.js.map +1 -1
- package/dist/queue/core/index.workerd.js +48 -71
- package/dist/queue/core/index.workerd.js.map +1 -1
- package/dist/queue/redis/index.d.ts +3 -4
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/queue/redis/index.js +2 -2
- package/dist/queue/redis/index.js.map +1 -1
- package/dist/react/auth/index.browser.js.map +1 -1
- package/dist/react/auth/index.d.ts +7 -4
- package/dist/react/auth/index.d.ts.map +1 -1
- package/dist/react/auth/index.js.map +1 -1
- package/dist/react/core/index.d.ts +87 -5
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +170 -23
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +4 -6
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +107 -71
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/head/index.browser.js.map +1 -1
- package/dist/react/head/index.d.ts +0 -1
- package/dist/react/head/index.d.ts.map +1 -1
- package/dist/react/head/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +47 -5
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +116 -12
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/intro/index.d.ts +1 -4
- package/dist/react/intro/index.d.ts.map +1 -1
- package/dist/react/intro/index.js.map +1 -1
- package/dist/react/router/index.browser.js +188 -29
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +480 -372
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +261 -47
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/sitemap/index.browser.js +35 -0
- package/dist/react/sitemap/index.browser.js.map +1 -0
- package/dist/react/sitemap/index.d.ts +91 -0
- package/dist/react/sitemap/index.d.ts.map +1 -0
- package/dist/react/sitemap/index.js +131 -0
- package/dist/react/sitemap/index.js.map +1 -0
- package/dist/react/testing/index.d.ts +4 -5
- package/dist/react/testing/index.d.ts.map +1 -1
- package/dist/react/testing/index.js +41 -15
- package/dist/react/testing/index.js.map +1 -1
- package/dist/react/testing/{chunk-BpyX8vjI.js → rolldown-runtime-Bl3dcgcQ.js} +1 -1
- package/dist/react/ui/index.d.ts +35 -34
- package/dist/react/ui/index.d.ts.map +1 -1
- package/dist/react/ui/index.js +12 -17
- package/dist/react/ui/index.js.map +1 -1
- package/dist/redis/index.bun.js +5 -5
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/redis/index.d.ts +6 -7
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js +6 -6
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +0 -1
- package/dist/retry/index.d.ts.map +1 -1
- package/dist/retry/index.js.map +1 -1
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +4 -12
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +9 -4
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js +9 -4
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.browser.js +30 -28
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts +113 -44
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +452 -37
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.browser.js +19 -19
- package/dist/server/auth/index.browser.js.map +1 -1
- package/dist/server/auth/index.d.ts +215 -187
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +1145 -86
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.browser.js +103 -5
- package/dist/server/cookies/index.browser.js.map +1 -1
- package/dist/server/cookies/index.d.ts +86 -4
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +121 -8
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.browser.js +22 -27
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts +134 -85
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +130 -118
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +9 -10
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js +14 -26
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/etag/index.d.ts +2 -3
- package/dist/server/etag/index.d.ts.map +1 -1
- package/dist/server/etag/index.js.map +1 -1
- package/dist/server/health/index.d.ts +18 -19
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/health/index.js +6 -6
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/links/index.browser.js +15 -18
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +66 -67
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +29 -32
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +0 -1
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +10 -3
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +0 -1
- package/dist/server/proxy/index.d.ts.map +1 -1
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +8 -9
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js +6 -12
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +0 -1
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +4 -4
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +37 -25
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +0 -1
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js.map +1 -1
- package/dist/system/index.d.ts +0 -1
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js +2 -1
- package/dist/system/index.js.map +1 -1
- package/dist/system/index.workerd.js.map +1 -1
- package/dist/topic/core/index.d.ts +19 -20
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/core/index.js +8 -8
- package/dist/topic/core/index.js.map +1 -1
- package/dist/topic/redis/index.d.ts +3 -4
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/topic/redis/index.js +2 -2
- package/dist/topic/redis/index.js.map +1 -1
- package/package.json +36 -36
- package/src/api/audits/__tests__/AuditJobs.spec.ts +83 -0
- package/src/api/audits/__tests__/AuditService.spec.ts +139 -1
- package/src/api/audits/controllers/AdminAuditController.ts +41 -41
- package/src/api/audits/entities/audits.ts +22 -22
- package/src/api/audits/index.ts +6 -1
- package/src/api/audits/jobs/AuditJobs.ts +29 -0
- package/src/api/audits/parameters/AuditParameters.ts +51 -0
- package/src/api/audits/primitives/$audit.ts +24 -0
- package/src/api/audits/schemas/auditQuerySchema.ts +13 -13
- package/src/api/audits/schemas/createAuditSchema.ts +18 -18
- package/src/api/audits/services/AuditService.ts +79 -7
- package/src/api/files/__tests__/FileController.spec.ts +5 -5
- package/src/api/files/__tests__/FileJobs.spec.ts +6 -0
- package/src/api/files/controllers/FileController.ts +25 -25
- package/src/api/files/entities/files.ts +15 -15
- package/src/api/files/schemas/fileCreatorSummarySchema.ts +7 -7
- package/src/api/files/schemas/fileQuerySchema.ts +9 -9
- package/src/api/files/schemas/fileResourceSchema.ts +7 -9
- package/src/api/files/schemas/storageStatsSchema.ts +13 -13
- package/src/api/jobs/__tests__/$job-hardening.spec.ts +289 -0
- package/src/api/jobs/__tests__/$job.spec.ts +18 -18
- package/src/api/jobs/controllers/AdminJobController.ts +8 -8
- package/src/api/jobs/entities/jobExecutionEntity.ts +29 -19
- package/src/api/jobs/providers/JobProvider.ts +128 -12
- package/src/api/jobs/providers/JobQueueProvider.ts +2 -2
- package/src/api/jobs/schemas/jobConfigAtom.ts +22 -22
- package/src/api/jobs/schemas/jobExecutionQuerySchema.ts +6 -6
- package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +11 -15
- package/src/api/jobs/schemas/jobRegistrationSchema.ts +20 -19
- package/src/api/jobs/schemas/triggerJobSchema.ts +3 -3
- package/src/api/jobs/services/JobService.ts +6 -6
- package/src/api/keys/__tests__/ApiKeyService.spec.ts +2 -2
- package/src/api/keys/controllers/AdminApiKeyController.ts +10 -10
- package/src/api/keys/entities/apiKeyEntity.ts +15 -15
- package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +4 -4
- package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +15 -15
- package/src/api/keys/schemas/createApiKeyBodySchema.ts +5 -5
- package/src/api/keys/schemas/createApiKeyResponseSchema.ts +9 -9
- package/src/api/keys/schemas/listApiKeyResponseSchema.ts +13 -13
- package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +3 -3
- package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +3 -3
- package/src/api/notifications/__tests__/AlephaApiNotifications.spec.ts +2 -2
- package/src/api/notifications/controllers/AdminNotificationController.ts +38 -14
- package/src/api/notifications/jobs/NotificationJobs.ts +7 -6
- package/src/api/notifications/primitives/$notification.ts +43 -4
- package/src/api/notifications/schemas/notificationContactPreferencesSchema.ts +4 -4
- package/src/api/notifications/schemas/notificationContactSchema.ts +7 -7
- package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +9 -11
- package/src/api/notifications/schemas/notificationPayloadSchema.ts +11 -9
- package/src/api/notifications/schemas/notificationQuerySchema.ts +6 -6
- package/src/api/notifications/schemas/notificationResourceSchema.ts +14 -14
- package/src/api/notifications/services/NotificationSenderService.ts +38 -2
- package/src/api/oauth/__tests__/OAuthClientService.spec.ts +42 -0
- package/src/api/oauth/__tests__/OAuthController.spec.ts +128 -0
- package/src/api/oauth/controllers/OAuthController.ts +132 -12
- package/src/api/oauth/entities/oauthClientEntity.ts +29 -12
- package/src/api/oauth/helpers/oauthMetadata.ts +1 -0
- package/src/api/oauth/helpers/oidcMetadata.ts +19 -0
- package/src/api/oauth/index.ts +1 -0
- package/src/api/oauth/schemas/authorizeDecisionBodySchema.ts +12 -11
- package/src/api/oauth/schemas/authorizeQuerySchema.ts +12 -10
- package/src/api/oauth/schemas/registerClientBodySchema.ts +10 -11
- package/src/api/oauth/schemas/tokenRequestBodySchema.ts +9 -8
- package/src/api/oauth/services/OAuthClientService.ts +228 -15
- package/src/api/organizations/controllers/AdminOrganizationController.ts +8 -8
- package/src/api/organizations/entities/organizations.ts +6 -6
- package/src/api/organizations/schemas/createOrganizationSchema.ts +5 -5
- package/src/api/organizations/schemas/organizationQuerySchema.ts +4 -4
- package/src/api/organizations/schemas/updateOrganizationSchema.ts +1 -2
- package/src/api/parameters/__tests__/$parameter.spec.ts +229 -50
- package/src/api/parameters/controllers/AdminParameterController.ts +9 -12
- package/src/api/parameters/entities/parameters.ts +29 -16
- package/src/api/parameters/primitives/$parameter.ts +3 -3
- package/src/api/parameters/schemas/activateParameterBodySchema.ts +4 -4
- package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +15 -15
- package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +7 -7
- package/src/api/parameters/schemas/parameterCurrentResponseSchema.ts +7 -7
- package/src/api/parameters/schemas/parameterHistoryResponseSchema.ts +3 -3
- package/src/api/parameters/schemas/parameterNameParamSchema.ts +2 -3
- package/src/api/parameters/schemas/parameterNamesResponseSchema.ts +3 -3
- package/src/api/parameters/schemas/parameterResponseSchema.ts +3 -3
- package/src/api/parameters/schemas/parameterStatusSchema.ts +2 -2
- package/src/api/parameters/schemas/parameterTreeNodeSchema.ts +6 -6
- package/src/api/parameters/schemas/parameterVersionParamSchema.ts +5 -6
- package/src/api/parameters/schemas/parameterVersionResponseSchema.ts +3 -3
- package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +6 -9
- package/src/api/parameters/services/ParameterProvider.ts +152 -65
- package/src/api/payments/controllers/AdminPaymentController.ts +7 -7
- package/src/api/payments/controllers/MockCheckoutController.ts +79 -28
- package/src/api/payments/controllers/PaymentController.ts +4 -4
- package/src/api/payments/entities/paymentIntents.ts +11 -11
- package/src/api/payments/entities/paymentMethods.ts +11 -11
- package/src/api/payments/entities/refunds.ts +9 -9
- package/src/api/payments/providers/PaymentProvider.ts +18 -0
- package/src/api/payments/schemas/intentSchemas.ts +25 -25
- package/src/api/payments/schemas/paymentMethodSchemas.ts +3 -3
- package/src/api/payments/services/PaymentService.ts +60 -3
- package/src/api/subscriptions/__tests__/SubscriptionService.spec.ts +14 -0
- package/src/api/subscriptions/controllers/AdminSubscriptionController.ts +11 -11
- package/src/api/subscriptions/controllers/SubscriptionController.ts +5 -4
- package/src/api/subscriptions/entities/subscriptionEvents.ts +15 -15
- package/src/api/subscriptions/entities/subscriptions.ts +22 -22
- package/src/api/subscriptions/notifications/SubscriptionNotifications.ts +22 -22
- package/src/api/subscriptions/schemas/cancelSubscriptionSchema.ts +4 -4
- package/src/api/subscriptions/schemas/changePlanSchema.ts +5 -5
- package/src/api/subscriptions/schemas/createSubscriptionSchema.ts +14 -7
- package/src/api/subscriptions/schemas/entitlementsSchema.ts +10 -10
- package/src/api/subscriptions/schemas/mrrSchema.ts +9 -9
- package/src/api/subscriptions/schemas/planDefinitionSchema.ts +21 -21
- package/src/api/subscriptions/schemas/planResourceSchema.ts +19 -19
- package/src/api/subscriptions/schemas/subscriptionQuerySchema.ts +8 -8
- package/src/api/subscriptions/schemas/subscriptionSettingsSchema.ts +7 -7
- package/src/api/subscriptions/schemas/subscriptionStatsSchema.ts +17 -17
- package/src/api/subscriptions/services/SubscriptionConfig.ts +2 -2
- package/src/api/users/__tests__/ApiKeys-integration.spec.ts +11 -11
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +111 -119
- package/src/api/users/controllers/AdminIdentityController.ts +29 -19
- package/src/api/users/controllers/AdminSessionController.ts +37 -27
- package/src/api/users/controllers/AdminUserController.ts +75 -53
- package/src/api/users/controllers/MySessionController.ts +125 -0
- package/src/api/users/controllers/RealmController.ts +9 -9
- package/src/api/users/controllers/UserController.ts +55 -55
- package/src/api/users/entities/identities.ts +8 -8
- package/src/api/users/entities/sessions.ts +17 -17
- package/src/api/users/entities/users.ts +17 -17
- package/src/api/users/index.ts +3 -0
- package/src/api/users/notifications/UserNotifications.ts +76 -24
- package/src/api/users/primitives/$realm.ts +12 -0
- package/src/api/users/schemas/completePasswordResetRequestSchema.ts +8 -12
- package/src/api/users/schemas/completeRegistrationRequestSchema.ts +17 -20
- package/src/api/users/schemas/createUserSchema.ts +2 -2
- package/src/api/users/schemas/identityQuerySchema.ts +4 -4
- package/src/api/users/schemas/identityResourceSchema.ts +3 -2
- package/src/api/users/schemas/loginSchema.ts +4 -4
- package/src/api/users/schemas/passwordResetIntentResponseSchema.ts +6 -8
- package/src/api/users/schemas/realmConfigSchema.ts +10 -10
- package/src/api/users/schemas/registerQuerySchema.ts +6 -6
- package/src/api/users/schemas/registerRequestSchema.ts +21 -43
- package/src/api/users/schemas/registerResponseSchema.ts +2 -2
- package/src/api/users/schemas/registerSchema.ts +13 -31
- package/src/api/users/schemas/registrationIntentResponseSchema.ts +19 -23
- package/src/api/users/schemas/resetPasswordSchema.ts +10 -17
- package/src/api/users/schemas/sessionQuerySchema.ts +3 -3
- package/src/api/users/schemas/sessionResourceSchema.ts +25 -25
- package/src/api/users/schemas/updateUserSchema.ts +3 -4
- package/src/api/users/schemas/userQuerySchema.ts +7 -7
- package/src/api/users/services/RegistrationService.ts +25 -11
- package/src/api/users/services/UserService.ts +12 -6
- package/src/api/verifications/__tests__/CodeVerification.spec.ts +63 -101
- package/src/api/verifications/__tests__/LinkVerification.spec.ts +23 -92
- package/src/api/verifications/controllers/VerificationController.ts +13 -27
- package/src/api/verifications/entities/verifications.ts +13 -14
- package/src/api/verifications/schemas/requestVerificationCodeResponseSchema.ts +17 -14
- package/src/api/verifications/schemas/validateVerificationCodeResponseSchema.ts +9 -10
- package/src/api/verifications/schemas/verificationSettingsSchema.ts +65 -66
- package/src/api/verifications/schemas/verificationTypeEnumSchema.ts +2 -2
- package/src/api/verifications/services/VerificationService.ts +12 -0
- package/src/background/__tests__/BackgroundTaskProvider.spec.ts +36 -0
- package/src/batch/__tests__/$batch.spec.ts +22 -22
- package/src/batch/__tests__/startup-buffering.spec.ts +9 -9
- package/src/bin/index.ts +1 -1
- package/src/bucket/__tests__/TenantScopedBucket.spec.ts +60 -0
- package/src/bucket/providers/LocalFileStorageProvider.ts +14 -6
- package/src/bucket/providers/MemoryFileStorageProvider.ts +18 -7
- package/src/bucket/providers/R2FileStorageProvider.ts +14 -6
- package/src/bucket/providers/S3FileStorageProvider.ts +31 -15
- package/src/cache/core/primitives/$cache.ts +7 -10
- package/src/cache/database/entities/cacheEntries.ts +16 -27
- package/src/cache/database/providers/DatabaseCacheProvider.ts +15 -13
- package/src/cache/redis/providers/RedisCacheProvider.ts +6 -6
- package/src/captcha/providers/TurnstileCaptchaProvider.ts +4 -4
- package/src/cli/core/__tests__/BuildCloudflareTask.spec.ts +178 -0
- package/src/cli/core/__tests__/BuildDockerTask.spec.ts +0 -2
- package/src/cli/core/__tests__/DbCommand.spec.ts +108 -0
- package/src/cli/core/atoms/appEntryOptions.ts +5 -5
- package/src/cli/core/atoms/buildOptions.ts +76 -88
- package/src/cli/core/atoms/changelogOptions.ts +3 -3
- package/src/cli/core/atoms/devOptions.ts +3 -3
- package/src/cli/core/commands/build.ts +36 -49
- package/src/cli/core/commands/db.ts +171 -83
- package/src/cli/core/commands/dev.ts +8 -8
- package/src/cli/core/commands/gen/changelog.ts +12 -14
- package/src/cli/core/commands/gen/env.ts +6 -6
- package/src/cli/core/commands/gen/openapi.ts +6 -6
- package/src/cli/core/commands/init.ts +28 -33
- package/src/cli/core/commands/pack.ts +10 -10
- package/src/cli/core/commands/root.ts +7 -8
- package/src/cli/core/commands/test.ts +17 -20
- package/src/cli/core/index.ts +0 -3
- package/src/cli/core/tasks/BuildCloudflareTask.ts +138 -245
- package/src/cli/core/tasks/BuildPrerenderTask.ts +44 -7
- package/src/cli/core/templates/apiHelloResponseSchemaTs.ts +4 -4
- package/src/cli/devtools/atoms/devtoolsOptions.ts +6 -6
- package/src/cli/i18n/__tests__/I18nCheckService.spec.ts +48 -0
- package/src/cli/i18n/atoms/i18nOptions.ts +8 -8
- package/src/cli/i18n/services/I18nCheckService.ts +65 -11
- package/src/cli/platform/commands/SecretsCommand.ts +24 -25
- package/src/cli/platform/commands/platform.ts +40 -46
- package/src/cli/platform/index.ts +1 -1
- package/src/cli/platform-lib/__tests__/CloudflareAdapter.spec.ts +0 -4
- package/src/cli/platform-lib/__tests__/PlatformInspector.spec.ts +10 -3
- package/src/cli/platform-lib/__tests__/VercelAdapter.spec.ts +0 -2
- package/src/cli/platform-lib/adapters/CloudflareAdapter.ts +141 -50
- package/src/cli/platform-lib/adapters/VercelAdapter.ts +6 -11
- package/src/cli/platform-lib/atoms/platformOptions.ts +46 -25
- package/src/cli/platform-lib/schemas/cloudflare.ts +87 -87
- package/src/cli/platform-lib/schemas/platform.ts +51 -51
- package/src/cli/platform-lib/schemas/vercel.ts +28 -28
- package/src/cli/platform-lib/services/CloudflareApi.ts +5 -5
- package/src/cli/platform-lib/services/VercelApi.ts +4 -4
- package/src/cli/platform-lib/services/VercelCli.ts +6 -15
- package/src/cli/platform-lib/services/WranglerApi.ts +6 -15
- package/src/cli/vendor/atoms/vendorOptions.ts +9 -9
- package/src/cli/vendor/commands/VendorCommand.ts +11 -12
- package/src/command/__tests__/$command.spec.ts +82 -83
- package/src/command/__tests__/Asker.spec.ts +6 -13
- package/src/command/__tests__/CliProvider.spec.ts +136 -149
- package/src/command/__tests__/Runner.spec.ts +86 -110
- package/src/command/helpers/Asker.ts +23 -58
- package/src/command/helpers/Runner.ts +34 -110
- package/src/command/index.ts +4 -9
- package/src/command/primitives/$command.ts +10 -10
- package/src/command/providers/CliProvider.ts +183 -161
- package/src/core/Alepha.ts +62 -13
- package/src/core/__tests__/$atom.spec.ts +52 -3
- package/src/core/__tests__/$computed.spec.ts +129 -0
- package/src/core/__tests__/$env.spec.ts +13 -13
- package/src/core/__tests__/$inject.spec.ts +4 -4
- package/src/core/__tests__/$module.spec.ts +1 -1
- package/src/core/__tests__/Alepha-graph.spec.ts +1 -1
- package/src/core/__tests__/Alepha-parseEnv.spec.ts +32 -32
- package/src/core/__tests__/Alepha-start.spec.ts +3 -3
- package/src/core/__tests__/CodecManager.spec.ts +113 -94
- package/src/core/__tests__/KeylessJsonSchemaCodec.spec.ts +138 -138
- package/src/core/__tests__/SchemaValidator.spec.ts +43 -44
- package/src/core/__tests__/StateManager.persist.browser.spec.ts +87 -0
- package/src/core/__tests__/StateManager.spec.ts +423 -0
- package/src/core/__tests__/TypeBox-usecases.spec.ts +8 -8
- package/src/core/__tests__/TypeProvider.spec.ts +314 -309
- package/src/core/__tests__/dump.spec.ts +6 -6
- package/src/core/__tests__/pagination.spec.ts +4 -4
- package/src/core/__tests__/scoped-after-start.spec.ts +43 -0
- package/src/core/errors/TypeBoxError.ts +10 -4
- package/src/core/helpers/FileLike.ts +5 -5
- package/src/core/helpers/coerceStrings.ts +70 -0
- package/src/core/helpers/jsonSchemaToZod.ts +112 -0
- package/src/core/index.shared.ts +4 -1
- package/src/core/primitives/$atom.ts +95 -27
- package/src/core/primitives/$computed.ts +148 -0
- package/src/core/primitives/$env.ts +5 -5
- package/src/core/primitives/$state.ts +1 -1
- package/src/core/providers/AlsProvider.ts +26 -0
- package/src/core/providers/CodecManager.ts +1 -2
- package/src/core/providers/JsonSchemaCodec.ts +1 -2
- package/src/core/providers/KeylessJsonSchemaCodec.ts +82 -57
- package/src/core/providers/SchemaValidator.ts +48 -158
- package/src/core/providers/StateManager.ts +383 -9
- package/src/core/providers/TypeProvider.ts +80 -734
- package/src/core/providers/ZodProvider.ts +380 -0
- package/src/core/providers/zodAugment.ts +69 -0
- package/src/core/schemas/pageQuerySchema.ts +19 -21
- package/src/core/schemas/pageSchema.ts +47 -57
- package/src/crypto/__tests__/SecretProvider.spec.ts +31 -0
- package/src/crypto/providers/SecretProvider.ts +16 -10
- package/src/datetime/primitives/$throttle.ts +6 -1
- package/src/email/brevo/providers/BrevoEmailProvider.ts +4 -4
- package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +6 -6
- package/src/email/core/index.ts +7 -2
- package/src/email/core/primitives/$email.ts +5 -1
- package/src/email/core/providers/LocalEmailProvider.ts +5 -5
- package/src/email/smtp/providers/NodemailerEmailProvider.ts +41 -52
- package/src/fake/__tests__/FakeProvider.spec.ts +110 -110
- package/src/fake/__tests__/keyName.example.ts +21 -21
- package/src/fake/__tests__/keyName.spec.ts +41 -41
- package/src/fake/__tests__/module.example.ts +8 -8
- package/src/fake/providers/FakeProvider.ts +122 -121
- package/src/lock/core/__tests__/lock-mutual-exclusion.spec.ts +44 -0
- package/src/lock/core/index.ts +1 -0
- package/src/lock/core/primitives/$lock.ts +13 -6
- package/src/logger/__tests__/CliFormatterProvider.spec.ts +76 -0
- package/src/logger/__tests__/Logger.spec.ts +49 -0
- package/src/logger/index.ts +25 -18
- package/src/logger/providers/CliFormatterProvider.ts +75 -0
- package/src/logger/schemas/logEntrySchema.ts +10 -10
- package/src/logger/services/Logger.ts +18 -0
- package/src/mcp/__tests__/$prompt.spec.ts +21 -23
- package/src/mcp/__tests__/$tool.spec.ts +22 -22
- package/src/mcp/__tests__/McpServerProvider.spec.ts +82 -11
- package/src/mcp/__tests__/StreamableHttpMcpTransport.spec.ts +2 -2
- package/src/mcp/__tests__/integration.spec.ts +33 -33
- package/src/mcp/primitives/$prompt.ts +11 -9
- package/src/mcp/primitives/$tool.ts +27 -86
- package/src/mcp/providers/McpServerProvider.ts +55 -0
- package/src/mcp/transports/StreamableHttpMcpTransport.ts +7 -7
- package/src/orm/__tests__/$repository-tests.ts +133 -27
- package/src/orm/__tests__/$repository.spec.ts +23 -0
- package/src/orm/__tests__/$transactional-tests.ts +4 -4
- package/src/orm/__tests__/ModelBuilder-tests.ts +28 -28
- package/src/orm/__tests__/ModelBuilder.spec.ts +124 -106
- package/src/orm/__tests__/QueryManager.spec.ts +5 -5
- package/src/orm/__tests__/delete-returning-tests.ts +11 -11
- package/src/orm/__tests__/deletedAt-tests.ts +3 -3
- package/src/orm/__tests__/enums.spec.ts +29 -25
- package/src/orm/__tests__/execute-tests.ts +8 -8
- package/src/orm/__tests__/fixtures/bigEntitySchema.ts +48 -48
- package/src/orm/__tests__/fixtures/userEntitySchema.ts +6 -6
- package/src/orm/__tests__/joins-tests.ts +30 -30
- package/src/orm/__tests__/organization-tests.ts +105 -3
- package/src/orm/__tests__/organization.spec.ts +46 -0
- package/src/orm/__tests__/orm-errors.spec.ts +10 -10
- package/src/orm/__tests__/orm-next-tests.ts +29 -29
- package/src/orm/__tests__/orm-showcase-tests.ts +9 -9
- package/src/orm/__tests__/primaryKey.spec.ts +4 -4
- package/src/orm/__tests__/query-date-encoding-tests.ts +17 -17
- package/src/orm/__tests__/ref-auto-onDelete.spec.ts +14 -14
- package/src/orm/__tests__/references.spec.ts +7 -7
- package/src/orm/__tests__/security.spec.ts +17 -17
- package/src/orm/__tests__/string-operators-tests.ts +5 -5
- package/src/orm/__tests__/timestamps-tests.ts +14 -14
- package/src/orm/__tests__/validation-tests.ts +5 -5
- package/src/orm/core/__tests__/BunSqliteProvider.bun.spec.ts +8 -8
- package/src/orm/core/constants/PG_SYMBOLS.ts +13 -1
- package/src/orm/core/entities/alephaSequences.ts +8 -8
- package/src/orm/core/helpers/pgAttr.ts +4 -4
- package/src/orm/core/primitives/$entity.ts +10 -6
- package/src/orm/core/providers/DatabaseTypeProvider.ts +46 -53
- package/src/orm/core/providers/drivers/BunSqliteProvider.ts +8 -8
- package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +3 -5
- package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +8 -8
- package/src/orm/core/schemas/databaseEnvSchema.ts +4 -4
- package/src/orm/core/schemas/insertSchema.ts +14 -18
- package/src/orm/core/schemas/legacyIdSchema.ts +2 -2
- package/src/orm/core/schemas/updateSchema.ts +10 -16
- package/src/orm/core/services/PgRelationManager.ts +2 -2
- package/src/orm/core/services/QueryManager.ts +13 -2
- package/src/orm/core/services/Repository.ts +88 -33
- package/src/orm/core/services/SqliteModelBuilder.ts +38 -45
- package/src/orm/postgres/__tests__/BunPostgresProvider.bun.spec.ts +4 -4
- package/src/orm/postgres/providers/CloudflareHyperdriveProvider.ts +4 -6
- package/src/orm/postgres/schemas/postgresEnvSchema.ts +6 -6
- package/src/orm/postgres/services/PostgresModelBuilder.ts +127 -114
- package/src/queue/core/__tests__/$consumer.spec.ts +4 -4
- package/src/queue/core/__tests__/WorkerProvider.spec.ts +4 -4
- package/src/queue/core/__tests__/shared.ts +6 -6
- package/src/queue/core/primitives/$consumer.ts +5 -5
- package/src/queue/core/primitives/$queue.ts +44 -61
- package/src/queue/core/providers/CloudflareQueueProvider.ts +6 -0
- package/src/queue/core/providers/WorkerProvider.ts +17 -14
- package/src/queue/redis/providers/RedisQueueProvider.ts +3 -3
- package/src/react/core/__tests__/ErrorBoundary.browser.spec.tsx +92 -0
- package/src/react/core/__tests__/Router.spec.tsx +4 -4
- package/src/react/core/__tests__/useComputed.browser.spec.tsx +192 -0
- package/src/react/core/__tests__/useQuery.browser.spec.tsx +48 -0
- package/src/react/core/__tests__/useSelector.browser.spec.tsx +105 -0
- package/src/react/core/__tests__/useStore.browser.spec.tsx +113 -0
- package/src/react/core/components/ErrorBoundary.tsx +42 -0
- package/src/react/core/hooks/useAction.ts +56 -19
- package/src/react/core/hooks/useComputed.ts +91 -0
- package/src/react/core/hooks/useSelector.ts +67 -0
- package/src/react/core/hooks/useStore.ts +36 -17
- package/src/react/core/index.ts +3 -0
- package/src/react/core/utils/shallowEqual.ts +36 -0
- package/src/react/form/__tests__/FormModel-submit-loading.spec.ts +71 -0
- package/src/react/form/__tests__/form-submitting-reactive.browser.spec.tsx +96 -0
- package/src/react/form/__tests__/useForm.browser.spec.tsx +54 -54
- package/src/react/form/errors/FormValidationError.ts +0 -2
- package/src/react/form/hooks/useForm.ts +19 -4
- package/src/react/form/hooks/useFormQuerySync.ts +0 -0
- package/src/react/form/services/FormModel.ts +124 -86
- package/src/react/form/services/parseField.ts +66 -27
- package/src/react/i18n/__tests__/I18nProvider.spec.ts +89 -0
- package/src/react/i18n/__tests__/Localize.spec.tsx +1 -1
- package/src/react/i18n/__tests__/locale-routing.spec.ts +107 -0
- package/src/react/i18n/providers/I18nProvider.ts +173 -14
- package/src/react/router/__tests__/$page.browser.spec.tsx +19 -19
- package/src/react/router/__tests__/$page.spec.tsx +21 -21
- package/src/react/router/__tests__/ReactBrowserProvider.browser.spec.ts +87 -1
- package/src/react/router/__tests__/RouterLocaleProvider.spec.ts +127 -0
- package/src/react/router/atoms/ssrManifestAtom.ts +16 -16
- package/src/react/router/components/NestedView.tsx +11 -3
- package/src/react/router/hooks/useQueryParams.ts +1 -1
- package/src/react/router/index.browser.ts +4 -0
- package/src/react/router/index.shared.ts +1 -0
- package/src/react/router/index.ts +9 -0
- package/src/react/router/primitives/$page.ts +2 -2
- package/src/react/router/providers/ReactBrowserProvider.ts +64 -13
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +15 -1
- package/src/react/router/providers/ReactPageProvider.ts +38 -13
- package/src/react/router/providers/ReactServerProvider.ts +105 -16
- package/src/react/router/providers/RootComponentsProvider.ts +13 -0
- package/src/react/router/providers/RouterLocaleProvider.ts +125 -0
- package/src/react/router/providers/__tests__/RootComponentsProvider.spec.ts +15 -0
- package/src/react/router/providers/__tests__/rootComponents.ssr.browser.spec.tsx +67 -0
- package/src/react/sitemap/__tests__/$sitemap.spec.ts +131 -0
- package/src/react/sitemap/index.browser.ts +21 -0
- package/src/react/sitemap/index.ts +25 -0
- package/src/react/sitemap/primitives/$sitemap.browser.ts +26 -0
- package/src/react/sitemap/primitives/$sitemap.ts +196 -0
- package/src/react/ui/atoms/uiAtom.ts +6 -6
- package/src/react/ui/atoms/uiThemeListAtom.ts +7 -7
- package/src/react/ui/hooks/useColorMode.ts +11 -4
- package/src/react/ui/services/SchemaControl.ts +4 -4
- package/src/redis/providers/BunRedisProvider.ts +19 -11
- package/src/redis/providers/NodeRedisProvider.ts +3 -3
- package/src/scheduler/primitives/$scheduler.ts +21 -8
- package/src/security/__tests__/assertRealmScope.spec.ts +29 -0
- package/src/security/atoms/currentTenantAtom.ts +6 -6
- package/src/security/atoms/currentUserAtom.ts +2 -2
- package/src/security/primitives/$issuer.ts +24 -2
- package/src/security/providers/JwtProvider.ts +100 -0
- package/src/security/providers/SecurityProvider.ts +43 -2
- package/src/security/schemas/permissionSchema.ts +19 -19
- package/src/security/schemas/roleSchema.ts +22 -28
- package/src/security/schemas/userAccountInfoSchema.ts +47 -37
- package/src/server/auth/__tests__/appleClientSecret.spec.ts +34 -0
- package/src/server/auth/__tests__/federationRedirectReplay.spec.ts +44 -0
- package/src/server/auth/helpers/appleClientSecret.ts +24 -0
- package/src/server/auth/helpers/jtiReplayGuard.ts +41 -0
- package/src/server/auth/helpers/safeRedirectPath.ts +19 -0
- package/src/server/auth/index.ts +1 -0
- package/src/server/auth/primitives/$auth.ts +6 -6
- package/src/server/auth/primitives/$authApple.ts +10 -10
- package/src/server/auth/primitives/$authFacebook.ts +10 -10
- package/src/server/auth/primitives/$authFranceConnect.ts +10 -10
- package/src/server/auth/primitives/$authGithub.ts +10 -10
- package/src/server/auth/primitives/$authGoogle.ts +10 -10
- package/src/server/auth/primitives/$authMicrosoft.ts +14 -14
- package/src/server/auth/providers/ServerAuthProvider.ts +67 -52
- package/src/server/auth/schemas/authenticationProviderSchema.ts +9 -12
- package/src/server/auth/schemas/tokenResponseSchema.ts +2 -2
- package/src/server/auth/schemas/tokensSchema.ts +16 -16
- package/src/server/auth/schemas/userinfoResponseSchema.ts +3 -3
- package/src/server/cookies/__tests__/AtomCookieBinding.spec.ts +80 -0
- package/src/server/cookies/__tests__/AtomCookiePersistence.browser.spec.ts +169 -0
- package/src/server/cookies/__tests__/AtomCookiePersistence.spec.ts +294 -0
- package/src/server/cookies/__tests__/ServerCookiesProvider.spec.ts +82 -12
- package/src/server/cookies/index.browser.ts +4 -1
- package/src/server/cookies/index.ts +8 -1
- package/src/server/cookies/primitives/$cookie.browser.ts +1 -1
- package/src/server/cookies/primitives/$cookie.ts +16 -0
- package/src/server/cookies/providers/AtomCookiePersistence.browser.ts +133 -0
- package/src/server/cookies/providers/AtomCookiePersistence.ts +148 -0
- package/src/server/cookies/providers/ServerCookiesProvider.ts +32 -4
- package/src/server/cookies/services/CookieParser.ts +6 -1
- package/src/server/core/__tests__/$action.spec.ts +13 -13
- package/src/server/core/__tests__/$middleware.spec.ts +10 -10
- package/src/server/core/__tests__/$route.spec.ts +9 -9
- package/src/server/core/__tests__/$sse.spec.ts +26 -26
- package/src/server/core/__tests__/BunHttpServerProvider.bun.spec.ts +6 -6
- package/src/server/core/__tests__/HttpClient.spec.ts +2 -2
- package/src/server/core/__tests__/NodeHttpServerProvider.spec.ts +15 -3
- package/src/server/core/__tests__/ServerBodyParserProvider.spec.ts +14 -14
- package/src/server/core/__tests__/ServerMultipartProvider.spec.ts +33 -33
- package/src/server/core/__tests__/ServerRouterProvider-errorHandler.spec.ts +5 -1
- package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +25 -25
- package/src/server/core/__tests__/ServerRouterProvider-serializationError.spec.ts +9 -5
- package/src/server/core/__tests__/ServerRouterProvider-validationError.spec.ts +56 -24
- package/src/server/core/errors/ValidationError.ts +6 -3
- package/src/server/core/helpers/isMultipart.ts +2 -1
- package/src/server/core/index.ts +5 -2
- package/src/server/core/interfaces/ServerRequest.ts +14 -14
- package/src/server/core/primitives/$action.ts +26 -36
- package/src/server/core/primitives/$route.ts +27 -0
- package/src/server/core/primitives/$sse.ts +3 -3
- package/src/server/core/providers/BunHttpServerProvider.ts +8 -9
- package/src/server/core/providers/NodeHttpServerProvider.ts +8 -9
- package/src/server/core/providers/ServerBodyParserProvider.ts +20 -12
- package/src/server/core/providers/ServerCompressProvider.ts +9 -10
- package/src/server/core/providers/ServerHelmetProvider.ts +26 -27
- package/src/server/core/providers/ServerMultipartProvider.ts +19 -19
- package/src/server/core/providers/ServerRouterProvider.ts +44 -15
- package/src/server/core/schemas/errorSchema.ts +20 -25
- package/src/server/core/schemas/okSchema.ts +9 -14
- package/src/server/core/services/HttpClient.ts +13 -1
- package/src/server/core/services/ServerRequestParser.ts +6 -6
- package/src/server/cors/providers/ServerCorsProvider.ts +26 -28
- package/src/server/health/schemas/healthSchema.ts +6 -6
- package/src/server/links/__tests__/$remote.spec.ts +3 -3
- package/src/server/links/__tests__/BatchEndpoint.spec.ts +9 -9
- package/src/server/links/__tests__/LinkProvider.spec.ts +9 -9
- package/src/server/links/__tests__/ServerLinksProvider.spec.ts +23 -23
- package/src/server/links/__tests__/fixtures/CrudApp.ts +21 -21
- package/src/server/links/atoms/apiLinksAtom.ts +2 -2
- package/src/server/links/atoms/linkOptionsAtom.ts +6 -6
- package/src/server/links/primitives/$remote.ts +3 -3
- package/src/server/links/providers/LinkProvider.ts +3 -3
- package/src/server/links/providers/ServerLinksProvider.ts +20 -20
- package/src/server/links/schemas/apiLinksResponseSchema.ts +23 -23
- package/src/server/proxy/__tests__/$proxy.spec.ts +9 -9
- package/src/server/proxy/providers/ServerProxyProvider.ts +5 -0
- package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +18 -20
- package/src/server/swagger/__tests__/$swagger.spec.ts +91 -94
- package/src/server/swagger/__tests__/ui.spec.ts +3 -3
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +66 -43
- package/src/system/__tests__/NodeShellProvider.spec.ts +46 -0
- package/src/system/providers/NodeShellProvider.ts +4 -1
- package/src/topic/core/__tests__/$subscriber.spec.ts +4 -4
- package/src/topic/core/__tests__/shared.ts +8 -8
- package/src/topic/core/primitives/$subscriber.ts +5 -5
- package/src/topic/core/primitives/$topic.ts +14 -14
- package/src/topic/redis/providers/RedisTopicProvider.ts +3 -3
- package/dist/container/core/index.d.ts +0 -236
- package/dist/container/core/index.d.ts.map +0 -1
- package/dist/container/core/index.js +0 -231
- package/dist/container/core/index.js.map +0 -1
- package/dist/container/core/index.workerd.js +0 -192
- package/dist/container/core/index.workerd.js.map +0 -1
- package/src/cli/core/tasks/BuildSitemapTask.ts +0 -130
- package/src/command/helpers/PrettyAsker.ts +0 -256
- package/src/command/helpers/PrettyPrint.ts +0 -332
- package/src/container/core/__tests__/$container.spec.ts +0 -83
- package/src/container/core/index.ts +0 -50
- package/src/container/core/index.workerd.ts +0 -53
- package/src/container/core/interfaces/ContainerOptions.ts +0 -69
- package/src/container/core/primitives/$container.ts +0 -100
- package/src/container/core/providers/CloudflareContainerProvider.ts +0 -70
- package/src/container/core/providers/ContainerProvider.ts +0 -92
- package/src/container/core/providers/MockContainerProvider.ts +0 -62
- package/src/container/core/providers/NodeContainerProvider.ts +0 -53
- package/src/core/__tests__/jsonSchemaToTypeBox.spec.ts +0 -771
- package/src/core/helpers/jsonSchemaToTypeBox.ts +0 -359
- /package/dist/orm/core/{chunk-B4FMCO8f.js → rolldown-runtime-B4FMCO8f.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/api/notifications/schemas/notificationPayloadSchema.ts","../../../src/api/notifications/services/NotificationSenderService.ts","../../../src/api/notifications/jobs/NotificationJobs.ts","../../../src/api/notifications/controllers/AdminNotificationController.ts","../../../src/api/notifications/primitives/$notification.ts","../../../src/api/notifications/schemas/notificationContactPreferencesSchema.ts","../../../src/api/notifications/schemas/notificationContactSchema.ts","../../../src/api/notifications/schemas/notificationDetailResourceSchema.ts","../../../src/api/notifications/schemas/notificationQuerySchema.ts","../../../src/api/notifications/schemas/notificationResourceSchema.ts","../../../src/api/notifications/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/api/notifications/schemas/notificationPayloadSchema.ts","../../../src/api/notifications/services/NotificationSenderService.ts","../../../src/api/notifications/jobs/NotificationJobs.ts","../../../src/api/notifications/controllers/AdminNotificationController.ts","../../../src/api/notifications/primitives/$notification.ts","../../../src/api/notifications/schemas/notificationContactPreferencesSchema.ts","../../../src/api/notifications/schemas/notificationContactSchema.ts","../../../src/api/notifications/schemas/notificationDetailResourceSchema.ts","../../../src/api/notifications/schemas/notificationQuerySchema.ts","../../../src/api/notifications/schemas/notificationResourceSchema.ts","../../../src/api/notifications/index.ts"],"mappings":";;;;;cAEa,yCAAyB;;;;;;;;;;;;;KAY1B,sBAAsB,cAAc;;;KCP3C;EACH;EACA,iBAAiB;;KAEd;EACH,oBAAoB;;cAGT;qBACQ,QAAM;qBACN,6BAAG;qBACH,eAAa;qBACb,aAAW;EAEjB,KAAK,SAAS,sBAAmB;;;;;;;;;;;;;EAqCvC,UAAU,SAAS;;;;EAoBnB,YAAY,SAAS;;;;;;;;;;;YA2BlB,YACR;IACE,eAAe;MAEX;MAAiB;;KAGvB;IAEI,QAAQ;IAA0B,MAAM;;YASpC,KAAK,SAAS;cAAA;;;;;;;;;;;;;;;;;;;;;;;;cCjGb;qBACQ,6BAAG;qBACH,IAAE;qBACF,2BAAyB;qBAGzB,iCAAU,yBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAGb,0CAAQ,iCAAA;;;WAgBR,4CAAgB,2BAAA;;;;;;;;;;;;;WAgBhB,iDAAqB,8BAAA;;;;cCzD1B;qBACQ;qBACA;qBACA,QAAM;qBACN,kBAAgB;qBAChB,iCAAU,yBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAEf;;;;;;;gBAUA;;YAKJ,WAAW;IAAQ;;WAKb,2CAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BjB,yCAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmBf,4CAAkB;;;;;;;;;;WAsBlB,6CAAmB;;;;;;;;YA4BzB,WAAW,MAAM;IAGvB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;YAIM,iBAAiB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cChHtB;GAAiB,UAAU,SAAO,SACpC,6BAA6B,KAAE,sBAAA;;;UAKzB,6BAA6B,UAAU,iBAC9C,oBAAoB;EAC5B;EACA;EACA;EACA;EACA;EACA;KAEG,eAAe,oBAAoB;;EAEtC,QAAQ;;cAKG,sBAAsB,UAAU,iBAAiB,UAC5D,6BAA6B;qBAEV,kBAAgB;MAExB;;;;;;;YAUD,YAAY;EAYT,KAAK,SAAS,wBAAwB,KAAE;EA+C9C,UAAU,SAAS,QAAQ,6BAA6B;;UAShD,wBAAwB,UAAU;EACjD,WAAW,aAAa;EACxB;;EAEA;;;;;;;EAOA;;UAGe,oBAAoB,UAAU;EAC7C;IACE;IACA,iBAAiB,WAAW,OAAO;;EAErC;IACE,oBAAoB,WAAW,OAAO;;;;;cCnK7B,oDAAoC;;;;KAKrC,iCAAiC,cACpC;;;cCNI,yCAAyB;;;;;;;KAQ1B,sBAAsB,cAAc;;;cCNnC,gDAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAWjC,6BAA6B,cAChC;;;cCbI,uCAAuB;;;;;;;;;;;;;;KAcxB,oBAAoB,cAAc;;;cCfjC,0CAA0B;;;;;;;;;;;;;;KAe3B,uBAAuB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;cC2BpC,yCAAsB,yBAAA"}
|
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import { $inject, $module, Alepha, AlephaError, KIND, Primitive, createPrimitive,
|
|
1
|
+
import { $inject, $module, Alepha, AlephaError, KIND, Primitive, createPrimitive, z } from "alepha";
|
|
2
2
|
import { $job, AlephaApiJobs, jobExecutionEntity } from "alepha/api/jobs";
|
|
3
3
|
import { $parameter, AlephaApiParameters } from "alepha/api/parameters";
|
|
4
4
|
import { $repository, pageQuerySchema } from "alepha/orm";
|
|
5
|
-
import { $secure } from "alepha/security";
|
|
5
|
+
import { $secure, currentTenantAtom } from "alepha/security";
|
|
6
6
|
import { $action, NotFoundError, okSchema } from "alepha/server";
|
|
7
7
|
import { DateTimeProvider } from "alepha/datetime";
|
|
8
8
|
import { $logger, logEntrySchema } from "alepha/logger";
|
|
9
9
|
import { EmailProvider } from "alepha/email";
|
|
10
10
|
import { SmsProvider } from "alepha/sms";
|
|
11
11
|
//#region ../../src/api/notifications/schemas/notificationPayloadSchema.ts
|
|
12
|
-
const notificationPayloadSchema =
|
|
13
|
-
type:
|
|
14
|
-
template:
|
|
15
|
-
contact:
|
|
16
|
-
variables:
|
|
17
|
-
category:
|
|
18
|
-
critical:
|
|
19
|
-
sensitive:
|
|
12
|
+
const notificationPayloadSchema = z.object({
|
|
13
|
+
type: z.enum(["email", "sms"]),
|
|
14
|
+
template: z.text(),
|
|
15
|
+
contact: z.text(),
|
|
16
|
+
variables: z.record(z.text(), z.any()).optional(),
|
|
17
|
+
category: z.text().optional(),
|
|
18
|
+
critical: z.boolean().optional(),
|
|
19
|
+
sensitive: z.boolean().optional(),
|
|
20
|
+
/** Recipient language (e.g. "fr" or "fr-FR") used to pick `translations`. */
|
|
21
|
+
lang: z.text().optional()
|
|
20
22
|
});
|
|
21
23
|
//#endregion
|
|
22
24
|
//#region ../../src/api/notifications/primitives/$notification.ts
|
|
@@ -32,7 +34,7 @@ const notificationPayloadSchema = t.object({
|
|
|
32
34
|
* welcomeEmail = $notification({
|
|
33
35
|
* name: "welcome-email",
|
|
34
36
|
* category: "onboarding",
|
|
35
|
-
* schema:
|
|
37
|
+
* schema: z.object({ username: z.text(), activationLink: z.text() }),
|
|
36
38
|
* email: {
|
|
37
39
|
* subject: "Welcome to our platform!",
|
|
38
40
|
* body: (vars) => `Hello ${vars.username}, click: ${vars.activationLink}`
|
|
@@ -54,8 +56,26 @@ var NotificationPrimitive = class extends Primitive {
|
|
|
54
56
|
get name() {
|
|
55
57
|
return this.options.name ?? `${this.config.propertyKey}`;
|
|
56
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Recipient language for `translations` resolution. Explicit `lang` wins;
|
|
61
|
+
* otherwise the language is captured FROM THE CURRENT REQUEST at push time
|
|
62
|
+
* (the i18n `lang` cookie, then `Accept-Language`) — the send job may run
|
|
63
|
+
* out of request context, so this must be resolved here, not in the sender.
|
|
64
|
+
*/
|
|
65
|
+
resolveLang(explicit) {
|
|
66
|
+
if (explicit) return explicit;
|
|
67
|
+
const request = this.alepha.store.get("alepha.http.request");
|
|
68
|
+
const fromCookie = (request?.headers?.cookie)?.match(/(?:^|;\s*)lang=([a-zA-Z-]+)/)?.[1];
|
|
69
|
+
if (fromCookie) return fromCookie;
|
|
70
|
+
return (request?.headers?.["accept-language"])?.split(",")[0]?.trim().split(";")[0] || void 0;
|
|
71
|
+
}
|
|
57
72
|
async push(options) {
|
|
58
|
-
const
|
|
73
|
+
const lang = this.resolveLang(options.lang);
|
|
74
|
+
const organizationId = options.organizationId ?? this.alepha.store.get(currentTenantAtom)?.id;
|
|
75
|
+
const pushOpts = {
|
|
76
|
+
...this.options.critical ? { priority: "critical" } : {},
|
|
77
|
+
organizationId
|
|
78
|
+
};
|
|
59
79
|
if (this.options.email) await this.notificationJobs.sendNotification.push({
|
|
60
80
|
type: "email",
|
|
61
81
|
template: this.name,
|
|
@@ -63,7 +83,8 @@ var NotificationPrimitive = class extends Primitive {
|
|
|
63
83
|
variables: options.variables,
|
|
64
84
|
category: this.options.category,
|
|
65
85
|
critical: this.options.critical,
|
|
66
|
-
sensitive: this.options.sensitive
|
|
86
|
+
sensitive: this.options.sensitive,
|
|
87
|
+
lang
|
|
67
88
|
}, pushOpts);
|
|
68
89
|
if (this.options.sms) await this.notificationJobs.sendNotification.push({
|
|
69
90
|
type: "sms",
|
|
@@ -72,7 +93,8 @@ var NotificationPrimitive = class extends Primitive {
|
|
|
72
93
|
variables: options.variables,
|
|
73
94
|
category: this.options.category,
|
|
74
95
|
critical: this.options.critical,
|
|
75
|
-
sensitive: this.options.sensitive
|
|
96
|
+
sensitive: this.options.sensitive,
|
|
97
|
+
lang
|
|
76
98
|
}, pushOpts);
|
|
77
99
|
}
|
|
78
100
|
configure(options) {
|
|
@@ -123,7 +145,7 @@ var NotificationSenderService = class {
|
|
|
123
145
|
}
|
|
124
146
|
renderSms(payload) {
|
|
125
147
|
const { variables, contact, template } = this.load(payload);
|
|
126
|
-
const sms = template.options.sms;
|
|
148
|
+
const sms = this.translation(template.options, payload.lang)?.sms ?? template.options.sms;
|
|
127
149
|
if (!sms) throw new AlephaError(`Notification template ${payload.template} has no sms defined`);
|
|
128
150
|
return {
|
|
129
151
|
to: contact,
|
|
@@ -132,7 +154,7 @@ var NotificationSenderService = class {
|
|
|
132
154
|
}
|
|
133
155
|
renderEmail(payload) {
|
|
134
156
|
const { variables, contact, template } = this.load(payload);
|
|
135
|
-
const email = template.options.email;
|
|
157
|
+
const email = this.translation(template.options, payload.lang)?.email ?? template.options.email;
|
|
136
158
|
if (!email) throw new AlephaError(`Notification template ${payload.template} has no email defined`);
|
|
137
159
|
return {
|
|
138
160
|
to: contact,
|
|
@@ -140,6 +162,19 @@ var NotificationSenderService = class {
|
|
|
140
162
|
body: typeof email.body === "function" ? email.body(variables) : email.body
|
|
141
163
|
};
|
|
142
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Pick the template's `translations` entry for the payload language:
|
|
167
|
+
* exact match ("fr-FR") first, then the base language ("fr"). Returns
|
|
168
|
+
* undefined when there is no match — callers fall back to the default
|
|
169
|
+
* (template-level) message.
|
|
170
|
+
*/
|
|
171
|
+
translation(options, lang) {
|
|
172
|
+
if (!lang || !options.translations) return void 0;
|
|
173
|
+
const exact = options.translations[lang];
|
|
174
|
+
if (exact) return exact;
|
|
175
|
+
const base = lang.split("-")[0]?.toLowerCase();
|
|
176
|
+
return base ? options.translations[base] : void 0;
|
|
177
|
+
}
|
|
143
178
|
load(payload) {
|
|
144
179
|
const variables = payload.variables || {};
|
|
145
180
|
const contact = payload.contact;
|
|
@@ -180,10 +215,7 @@ var NotificationJobs = class {
|
|
|
180
215
|
settings = $parameter({
|
|
181
216
|
name: "alepha.api.notifications",
|
|
182
217
|
description: "Notification delivery & retention settings.",
|
|
183
|
-
schema:
|
|
184
|
-
description: "Days to keep notification execution rows before the purge sweep removes them.",
|
|
185
|
-
minimum: 1
|
|
186
|
-
}) }),
|
|
218
|
+
schema: z.object({ retentionDays: z.integer().min(1).describe("Days to keep notification execution rows before the purge sweep removes them.") }),
|
|
187
219
|
default: { retentionDays: 7 }
|
|
188
220
|
});
|
|
189
221
|
sendNotification = $job({
|
|
@@ -236,33 +268,33 @@ var NotificationJobs = class {
|
|
|
236
268
|
};
|
|
237
269
|
//#endregion
|
|
238
270
|
//#region ../../src/api/notifications/schemas/notificationResourceSchema.ts
|
|
239
|
-
const notificationResourceSchema =
|
|
240
|
-
id:
|
|
241
|
-
createdAt:
|
|
242
|
-
status:
|
|
243
|
-
template:
|
|
244
|
-
type:
|
|
245
|
-
contact:
|
|
246
|
-
category:
|
|
247
|
-
critical:
|
|
248
|
-
sensitive:
|
|
249
|
-
startedAt:
|
|
250
|
-
completedAt:
|
|
251
|
-
error:
|
|
271
|
+
const notificationResourceSchema = z.object({
|
|
272
|
+
id: z.uuid(),
|
|
273
|
+
createdAt: z.datetime(),
|
|
274
|
+
status: z.text(),
|
|
275
|
+
template: z.text().optional(),
|
|
276
|
+
type: z.text().optional(),
|
|
277
|
+
contact: z.text().optional(),
|
|
278
|
+
category: z.text().optional(),
|
|
279
|
+
critical: z.boolean().optional(),
|
|
280
|
+
sensitive: z.boolean().optional(),
|
|
281
|
+
startedAt: z.datetime().optional(),
|
|
282
|
+
completedAt: z.datetime().optional(),
|
|
283
|
+
error: z.text().optional()
|
|
252
284
|
});
|
|
253
285
|
//#endregion
|
|
254
286
|
//#region ../../src/api/notifications/schemas/notificationDetailResourceSchema.ts
|
|
255
|
-
const notificationDetailResourceSchema =
|
|
256
|
-
variables:
|
|
257
|
-
rendered:
|
|
258
|
-
logs:
|
|
259
|
-
}
|
|
287
|
+
const notificationDetailResourceSchema = notificationResourceSchema.extend({
|
|
288
|
+
variables: z.record(z.text(), z.any()).optional(),
|
|
289
|
+
rendered: z.record(z.text(), z.any()).optional(),
|
|
290
|
+
logs: z.array(logEntrySchema).optional()
|
|
291
|
+
}).meta({
|
|
260
292
|
title: "NotificationDetailResource",
|
|
261
293
|
description: "A notification resource with rendered content and logs."
|
|
262
294
|
});
|
|
263
295
|
//#endregion
|
|
264
296
|
//#region ../../src/api/notifications/schemas/notificationQuerySchema.ts
|
|
265
|
-
const notificationQuerySchema =
|
|
297
|
+
const notificationQuerySchema = pageQuerySchema.extend({ status: z.enum([
|
|
266
298
|
"pending",
|
|
267
299
|
"scheduled",
|
|
268
300
|
"retrying",
|
|
@@ -270,29 +302,46 @@ const notificationQuerySchema = t.extend(pageQuerySchema, { status: t.optional(t
|
|
|
270
302
|
"completed",
|
|
271
303
|
"dead",
|
|
272
304
|
"cancelled"
|
|
273
|
-
])) });
|
|
305
|
+
]).optional() });
|
|
274
306
|
//#endregion
|
|
275
307
|
//#region ../../src/api/notifications/controllers/AdminNotificationController.ts
|
|
276
308
|
var AdminNotificationController = class {
|
|
277
309
|
url = "/notifications";
|
|
278
310
|
group = "admin:notifications";
|
|
311
|
+
alepha = $inject(Alepha);
|
|
279
312
|
notificationJobs = $inject(NotificationJobs);
|
|
280
313
|
executions = $repository(jobExecutionEntity);
|
|
281
314
|
get jobName() {
|
|
282
315
|
return this.notificationJobs.sendNotification.name;
|
|
283
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* The tenant this request is acting in, when multi-tenant. The notification
|
|
319
|
+
* outbox (`job_executions`) is shared across tenants in a pooled worker, so
|
|
320
|
+
* every read/delete here is scoped to this org to prevent cross-tenant access.
|
|
321
|
+
* Undefined in single-tenant apps → no extra filter (all rows are this app's).
|
|
322
|
+
*/
|
|
323
|
+
get organizationId() {
|
|
324
|
+
return this.alepha.store.get(currentTenantAtom)?.id;
|
|
325
|
+
}
|
|
326
|
+
/** True when `exec` belongs to the acting tenant (or the app is single-tenant). */
|
|
327
|
+
sameTenant(exec) {
|
|
328
|
+
const org = this.organizationId;
|
|
329
|
+
return !org || exec.organizationId === org;
|
|
330
|
+
}
|
|
284
331
|
findNotifications = $action({
|
|
285
332
|
path: this.url,
|
|
286
333
|
group: this.group,
|
|
287
334
|
use: [$secure({ permissions: ["admin:notification:read"] })],
|
|
288
335
|
schema: {
|
|
289
336
|
query: notificationQuerySchema,
|
|
290
|
-
response:
|
|
337
|
+
response: z.page(notificationResourceSchema)
|
|
291
338
|
},
|
|
292
339
|
handler: async ({ query }) => {
|
|
293
340
|
query.sort ??= "-createdAt";
|
|
294
341
|
const where = this.executions.createQueryWhere();
|
|
295
342
|
where.jobName = { eq: this.jobName };
|
|
343
|
+
const org = this.organizationId;
|
|
344
|
+
if (org) where.organizationId = { eq: org };
|
|
296
345
|
const page = await this.executions.paginate(query, { where }, { count: true });
|
|
297
346
|
return {
|
|
298
347
|
...page,
|
|
@@ -305,12 +354,12 @@ var AdminNotificationController = class {
|
|
|
305
354
|
group: this.group,
|
|
306
355
|
use: [$secure({ permissions: ["admin:notification:read"] })],
|
|
307
356
|
schema: {
|
|
308
|
-
params:
|
|
357
|
+
params: z.object({ id: z.uuid() }),
|
|
309
358
|
response: notificationDetailResourceSchema
|
|
310
359
|
},
|
|
311
360
|
handler: async ({ params }) => {
|
|
312
361
|
const exec = await this.executions.findById(params.id);
|
|
313
|
-
if (!exec || exec.jobName !== this.jobName) throw new NotFoundError(`Notification not found: ${params.id}`);
|
|
362
|
+
if (!exec || exec.jobName !== this.jobName || !this.sameTenant(exec)) throw new NotFoundError(`Notification not found: ${params.id}`);
|
|
314
363
|
return this.toDetailResource(exec);
|
|
315
364
|
}
|
|
316
365
|
});
|
|
@@ -321,12 +370,12 @@ var AdminNotificationController = class {
|
|
|
321
370
|
use: [$secure({ permissions: ["admin:notification:delete"] })],
|
|
322
371
|
description: "Delete a notification record",
|
|
323
372
|
schema: {
|
|
324
|
-
params:
|
|
373
|
+
params: z.object({ id: z.uuid() }),
|
|
325
374
|
response: okSchema
|
|
326
375
|
},
|
|
327
376
|
handler: async ({ params }) => {
|
|
328
377
|
const exec = await this.executions.findById(params.id);
|
|
329
|
-
if (!exec || exec.jobName !== this.jobName) throw new NotFoundError(`Notification not found: ${params.id}`);
|
|
378
|
+
if (!exec || exec.jobName !== this.jobName || !this.sameTenant(exec)) throw new NotFoundError(`Notification not found: ${params.id}`);
|
|
330
379
|
await this.executions.deleteById(params.id);
|
|
331
380
|
return {
|
|
332
381
|
ok: true,
|
|
@@ -341,16 +390,15 @@ var AdminNotificationController = class {
|
|
|
341
390
|
use: [$secure({ permissions: ["admin:notification:delete"] })],
|
|
342
391
|
description: "Delete many notification records in one call",
|
|
343
392
|
schema: {
|
|
344
|
-
body:
|
|
345
|
-
|
|
346
|
-
maxItems: 1e3
|
|
347
|
-
}) }),
|
|
348
|
-
response: t.object({ deleted: t.array(t.uuid()) })
|
|
393
|
+
body: z.object({ ids: z.array(z.uuid()).min(1).max(1e3) }),
|
|
394
|
+
response: z.object({ deleted: z.array(z.uuid()) })
|
|
349
395
|
},
|
|
350
396
|
handler: async ({ body }) => {
|
|
397
|
+
const org = this.organizationId;
|
|
351
398
|
return { deleted: (await this.executions.deleteMany({
|
|
352
399
|
id: { inArray: body.ids },
|
|
353
|
-
jobName: { eq: this.jobName }
|
|
400
|
+
jobName: { eq: this.jobName },
|
|
401
|
+
...org ? { organizationId: { eq: org } } : {}
|
|
354
402
|
})).map(String) };
|
|
355
403
|
}
|
|
356
404
|
});
|
|
@@ -382,18 +430,18 @@ var AdminNotificationController = class {
|
|
|
382
430
|
};
|
|
383
431
|
//#endregion
|
|
384
432
|
//#region ../../src/api/notifications/schemas/notificationContactPreferencesSchema.ts
|
|
385
|
-
const notificationContactPreferencesSchema =
|
|
386
|
-
language:
|
|
387
|
-
exclude:
|
|
433
|
+
const notificationContactPreferencesSchema = z.object({
|
|
434
|
+
language: z.text().optional(),
|
|
435
|
+
exclude: z.array(z.text())
|
|
388
436
|
});
|
|
389
437
|
//#endregion
|
|
390
438
|
//#region ../../src/api/notifications/schemas/notificationContactSchema.ts
|
|
391
|
-
const notificationContactSchema =
|
|
392
|
-
email:
|
|
393
|
-
phoneNumber:
|
|
394
|
-
firstName:
|
|
395
|
-
lastName:
|
|
396
|
-
language:
|
|
439
|
+
const notificationContactSchema = z.object({
|
|
440
|
+
email: z.email().optional(),
|
|
441
|
+
phoneNumber: z.e164().optional(),
|
|
442
|
+
firstName: z.shortText().optional(),
|
|
443
|
+
lastName: z.text({ size: "short" }).optional(),
|
|
444
|
+
language: z.bcp47().optional()
|
|
397
445
|
});
|
|
398
446
|
//#endregion
|
|
399
447
|
//#region ../../src/api/notifications/index.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/api/notifications/schemas/notificationPayloadSchema.ts","../../../src/api/notifications/primitives/$notification.ts","../../../src/api/notifications/services/NotificationSenderService.ts","../../../src/api/notifications/jobs/NotificationJobs.ts","../../../src/api/notifications/schemas/notificationResourceSchema.ts","../../../src/api/notifications/schemas/notificationDetailResourceSchema.ts","../../../src/api/notifications/schemas/notificationQuerySchema.ts","../../../src/api/notifications/controllers/AdminNotificationController.ts","../../../src/api/notifications/schemas/notificationContactPreferencesSchema.ts","../../../src/api/notifications/schemas/notificationContactSchema.ts","../../../src/api/notifications/index.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\n\nexport const notificationPayloadSchema = t.object({\n type: t.enum([\"email\", \"sms\"]),\n template: t.text(),\n contact: t.text(),\n variables: t.optional(t.record(t.text(), t.any())),\n category: t.optional(t.text()),\n critical: t.optional(t.boolean()),\n sensitive: t.optional(t.boolean()),\n});\n\nexport type NotificationPayload = Static<typeof notificationPayloadSchema>;\n","import {\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type Static,\n type StaticEncode,\n type TObject,\n} from \"alepha\";\nimport { NotificationJobs } from \"../jobs/NotificationJobs.ts\";\n\n/**\n * Creates a notification primitive for managing email/SMS notification templates.\n *\n * Provides type-safe, reusable notification templates with multi-language support,\n * variable substitution, and categorization for different notification channels.\n *\n * @example\n * ```ts\n * class NotificationTemplates {\n * welcomeEmail = $notification({\n * name: \"welcome-email\",\n * category: \"onboarding\",\n * schema: t.object({ username: t.text(), activationLink: t.text() }),\n * email: {\n * subject: \"Welcome to our platform!\",\n * body: (vars) => `Hello ${vars.username}, click: ${vars.activationLink}`\n * }\n * });\n *\n * async sendWelcome(user: User) {\n * await this.welcomeEmail.push({\n * variables: { username: user.name, activationLink: generateLink() },\n * contact: user.email\n * });\n * }\n * }\n * ```\n */\nexport const $notification = <T extends TObject>(\n options: NotificationPrimitiveOptions<T>,\n) => createPrimitive(NotificationPrimitive<T>, options);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface NotificationPrimitiveOptions<T extends TObject>\n extends NotificationMessage<T> {\n name?: string;\n description?: string;\n category?: string;\n critical?: boolean;\n sensitive?: boolean;\n translations?: {\n // e.g., \"en\", \"fr\", even \"en-US\"\n [lang: string]: NotificationMessage<T>;\n };\n schema: T;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class NotificationPrimitive<T extends TObject> extends Primitive<\n NotificationPrimitiveOptions<T>\n> {\n protected readonly notificationJobs = $inject(NotificationJobs);\n\n public get name() {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n public async push(options: NotificationPushOptions<T>) {\n const pushOpts = this.options.critical\n ? ({ priority: \"critical\" } as const)\n : undefined;\n\n if (this.options.email) {\n await this.notificationJobs.sendNotification.push(\n {\n type: \"email\",\n template: this.name,\n contact: options.contact,\n variables: options.variables as Record<string, unknown>,\n category: this.options.category,\n critical: this.options.critical,\n sensitive: this.options.sensitive,\n },\n pushOpts,\n );\n }\n\n if (this.options.sms) {\n await this.notificationJobs.sendNotification.push(\n {\n type: \"sms\",\n template: this.name,\n contact: options.contact,\n variables: options.variables as Record<string, unknown>,\n category: this.options.category,\n critical: this.options.critical,\n sensitive: this.options.sensitive,\n },\n pushOpts,\n );\n }\n }\n\n public configure(options: Partial<NotificationPrimitiveOptions<T>>) {\n Object.assign(this.options, options);\n }\n}\n\n$notification[KIND] = NotificationPrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface NotificationPushOptions<T extends TObject> {\n variables: StaticEncode<T>;\n contact: string;\n}\n\nexport interface NotificationMessage<T extends TObject> {\n email?: {\n subject: string;\n body: string | ((variables: Static<T>) => string);\n };\n sms?: {\n message: string | ((variables: Static<T>) => string);\n };\n}\n","import { $inject, Alepha, AlephaError } from \"alepha\";\nimport { EmailProvider } from \"alepha/email\";\nimport { $logger } from \"alepha/logger\";\nimport { SmsProvider } from \"alepha/sms\";\nimport { $notification } from \"../primitives/$notification.ts\";\nimport type { NotificationPayload } from \"../schemas/notificationPayloadSchema.ts\";\n\nexport class NotificationSenderService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly emailProvider = $inject(EmailProvider);\n protected readonly smsProvider = $inject(SmsProvider);\n\n public async send(payload: NotificationPayload) {\n this.log.debug(\"Processing notification\", {\n type: payload.type,\n template: payload.template,\n contact: payload.contact,\n });\n\n if (payload.type === \"email\") {\n const rendered = this.renderEmail(payload);\n await this.emailProvider.send(rendered);\n this.log.info(\"Email notification sent\", {\n template: payload.template,\n contact: payload.contact,\n });\n return {\n type: \"email\" as const,\n to: rendered.to,\n subject: rendered.subject,\n body: rendered.body,\n };\n }\n\n if (payload.type === \"sms\") {\n const rendered = this.renderSms(payload);\n await this.smsProvider.send(rendered);\n this.log.info(\"SMS notification sent\", {\n template: payload.template,\n contact: payload.contact,\n });\n return {\n type: \"sms\" as const,\n to: rendered.to,\n message: rendered.message,\n };\n }\n }\n\n public renderSms(payload: NotificationPayload) {\n const { variables, contact, template } = this.load(payload);\n\n const sms = template.options.sms;\n if (!sms) {\n throw new AlephaError(\n `Notification template ${payload.template} has no sms defined`,\n );\n }\n\n const message =\n typeof sms.message === \"function\"\n ? sms.message(variables as any)\n : sms.message;\n\n return { to: contact, message };\n }\n\n public renderEmail(payload: NotificationPayload) {\n const { variables, contact, template } = this.load(payload);\n\n const email = template.options.email;\n if (!email) {\n throw new AlephaError(\n `Notification template ${payload.template} has no email defined`,\n );\n }\n\n const subject = email.subject;\n const body =\n typeof email.body === \"function\"\n ? email.body(variables as any)\n : email.body;\n\n return { to: contact, subject, body };\n }\n\n protected load(payload: NotificationPayload) {\n const variables = payload.variables || {};\n const contact = payload.contact;\n const template = this.alepha\n .primitives($notification)\n .find((it) => it.name === payload.template);\n\n if (!template) {\n throw new AlephaError(\n `No notification template found for ${payload.template}`,\n );\n }\n\n return { template, variables, contact };\n }\n}\n","import { $inject, t } from \"alepha\";\nimport { $job, jobExecutionEntity } from \"alepha/api/jobs\";\nimport { $parameter } from \"alepha/api/parameters\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport { notificationPayloadSchema } from \"../schemas/notificationPayloadSchema.ts\";\nimport { NotificationSenderService } from \"../services/NotificationSenderService.ts\";\n\n/**\n * Notification jobs + runtime-editable retention.\n *\n * - `settings` — a `$parameter` exposing `retentionDays` that admins can\n * update at runtime. Changes propagate across instances via the parameter\n * pub/sub; the next purge run picks up the new value with no restart.\n * - `sendNotification` — queue-mode, audit-oriented. Every execution is kept\n * (`record: \"all\"`, `keep: { ok: 0, error: 0 }` disables the ring-buffer\n * trim) so the audit trail survives even under heavy volume.\n * - `purgeOldNotifications` — cron sweep that deletes notification execution\n * rows whose `completedAt` is older than the current `retentionDays`.\n *\n * Cron expression note: the purge cron is declared statically (`0 3 * * *`)\n * because some runtimes (Cloudflare Workers) freeze cron triggers at deploy\n * time. The *retention window* is fully runtime-editable — that's the knob\n * that actually matters for operators.\n */\nexport class NotificationJobs {\n protected readonly log = $logger();\n protected readonly dt = $inject(DateTimeProvider);\n protected readonly notificationSenderService = $inject(\n NotificationSenderService,\n );\n protected readonly executions = $repository(jobExecutionEntity);\n\n /** Runtime-editable config. Admins can change retentionDays without deploy. */\n public readonly settings = $parameter({\n name: \"alepha.api.notifications\",\n description: \"Notification delivery & retention settings.\",\n schema: t.object({\n retentionDays: t.integer({\n description:\n \"Days to keep notification execution rows before the purge sweep removes them.\",\n minimum: 1,\n }),\n }),\n default: {\n retentionDays: 7,\n },\n });\n\n public readonly sendNotification = $job({\n name: \"api:notifications:sendNotification\",\n description:\n \"Sends a notification (email/SMS) and keeps every execution for audit.\",\n schema: notificationPayloadSchema,\n retry: {\n retries: 3,\n },\n timeout: [30, \"seconds\"],\n record: \"all\",\n keep: { ok: 0, error: 0 },\n handler: async ({ payload }) => {\n await this.notificationSenderService.send(payload);\n },\n });\n\n public readonly purgeOldNotifications = $job({\n name: \"api:notifications:purgeOldNotifications\",\n description:\n \"Hourly sweep that deletes notification execution rows older than the configured retention window.\",\n cron: \"0 * * * *\",\n handler: async ({ now }) => {\n const { retentionDays } = this.settings.cachedCurrentContent;\n const cutoff = now.subtract(retentionDays, \"day\").toISOString();\n const jobName = this.sendNotification.name;\n\n const expired = await this.executions.findMany({\n where: {\n jobName: { eq: jobName },\n status: { inArray: [\"ok\", \"error\", \"cancelled\"] },\n completedAt: { lt: cutoff },\n },\n columns: [\"id\"] as any,\n limit: 5_000,\n });\n\n if (expired.length === 0) {\n this.log.debug(\"Notification purge: nothing to delete\", {\n cutoff,\n retentionDays,\n });\n return;\n }\n\n await this.executions.deleteMany({\n id: { inArray: expired.map((r) => r.id) },\n });\n this.log.info(\n `Notification purge: deleted ${expired.length} row(s) older than ${retentionDays} days`,\n { cutoff },\n );\n },\n });\n}\n","import { type Static, t } from \"alepha\";\n\nexport const notificationResourceSchema = t.object({\n id: t.uuid(),\n createdAt: t.datetime(),\n status: t.text(),\n template: t.optional(t.text()),\n type: t.optional(t.text()),\n contact: t.optional(t.text()),\n category: t.optional(t.text()),\n critical: t.optional(t.boolean()),\n sensitive: t.optional(t.boolean()),\n startedAt: t.optional(t.datetime()),\n completedAt: t.optional(t.datetime()),\n error: t.optional(t.text()),\n});\n\nexport type NotificationResource = Static<typeof notificationResourceSchema>;\n","import { type Static, t } from \"alepha\";\nimport { logEntrySchema } from \"alepha/logger\";\nimport { notificationResourceSchema } from \"./notificationResourceSchema.ts\";\n\nexport const notificationDetailResourceSchema = t.extend(\n notificationResourceSchema,\n {\n variables: t.optional(t.record(t.text(), t.any())),\n rendered: t.optional(t.record(t.text(), t.any())),\n logs: t.optional(t.array(logEntrySchema)),\n },\n {\n title: \"NotificationDetailResource\",\n description: \"A notification resource with rendered content and logs.\",\n },\n);\n\nexport type NotificationDetailResource = Static<\n typeof notificationDetailResourceSchema\n>;\n","import { type Static, t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\n\nexport const notificationQuerySchema = t.extend(pageQuerySchema, {\n status: t.optional(\n t.enum([\n \"pending\",\n \"scheduled\",\n \"retrying\",\n \"running\",\n \"completed\",\n \"dead\",\n \"cancelled\",\n ]),\n ),\n});\n\nexport type NotificationQuery = Static<typeof notificationQuerySchema>;\n","import { $inject, t } from \"alepha\";\nimport { jobExecutionEntity } from \"alepha/api/jobs\";\nimport { $repository } from \"alepha/orm\";\nimport { $secure } from \"alepha/security\";\nimport { $action, NotFoundError, okSchema } from \"alepha/server\";\nimport { NotificationJobs } from \"../jobs/NotificationJobs.ts\";\nimport { notificationDetailResourceSchema } from \"../schemas/notificationDetailResourceSchema.ts\";\nimport { notificationQuerySchema } from \"../schemas/notificationQuerySchema.ts\";\nimport { notificationResourceSchema } from \"../schemas/notificationResourceSchema.ts\";\n\nexport class AdminNotificationController {\n protected readonly url: string = \"/notifications\";\n protected readonly group: string = \"admin:notifications\";\n protected readonly notificationJobs = $inject(NotificationJobs);\n protected readonly executions = $repository(jobExecutionEntity);\n\n protected get jobName(): string {\n return this.notificationJobs.sendNotification.name;\n }\n\n public readonly findNotifications = $action({\n path: this.url,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:read\"] })],\n schema: {\n query: notificationQuerySchema,\n response: t.page(notificationResourceSchema),\n },\n handler: async ({ query }) => {\n query.sort ??= \"-createdAt\";\n const where = this.executions.createQueryWhere();\n where.jobName = { eq: this.jobName };\n const page = await this.executions.paginate(\n query,\n { where },\n { count: true },\n );\n return {\n ...page,\n content: page.content.map((exec) => this.toResource(exec)),\n } as any;\n },\n });\n\n public readonly getNotification = $action({\n path: `${this.url}/:id`,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:read\"] })],\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n response: notificationDetailResourceSchema,\n },\n handler: async ({ params }) => {\n const exec = await this.executions.findById(params.id);\n if (!exec || exec.jobName !== this.jobName) {\n throw new NotFoundError(`Notification not found: ${params.id}`);\n }\n return this.toDetailResource(exec) as any;\n },\n });\n\n public readonly deleteNotification = $action({\n method: \"DELETE\",\n path: `${this.url}/:id`,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:delete\"] })],\n description: \"Delete a notification record\",\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n response: okSchema,\n },\n handler: async ({ params }) => {\n const exec = await this.executions.findById(params.id);\n if (!exec || exec.jobName !== this.jobName) {\n throw new NotFoundError(`Notification not found: ${params.id}`);\n }\n await this.executions.deleteById(params.id);\n return { ok: true, id: params.id };\n },\n });\n\n public readonly deleteNotifications = $action({\n method: \"POST\",\n path: `${this.url}/delete`,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:delete\"] })],\n description: \"Delete many notification records in one call\",\n schema: {\n body: t.object({\n ids: t.array(t.uuid(), { minItems: 1, maxItems: 1000 }),\n }),\n response: t.object({\n deleted: t.array(t.uuid()),\n }),\n },\n handler: async ({ body }) => {\n // Constrain to this job's executions so an admin can't delete arbitrary\n // job rows through this endpoint.\n const deleted = await this.executions.deleteMany({\n id: { inArray: body.ids },\n jobName: { eq: this.jobName },\n });\n return { deleted: deleted.map(String) };\n },\n });\n\n protected toResource(exec: Record<string, unknown>) {\n const payload = (exec.payload ?? {}) as Record<string, unknown>;\n return {\n id: exec.id,\n createdAt: exec.createdAt,\n status: exec.status,\n template: payload.template,\n type: payload.type,\n contact: payload.contact,\n category: payload.category,\n critical: payload.critical,\n sensitive: payload.sensitive,\n startedAt: exec.startedAt,\n completedAt: exec.completedAt,\n error: exec.error,\n };\n }\n\n protected toDetailResource(exec: Record<string, unknown>) {\n const payload = (exec.payload ?? {}) as Record<string, unknown>;\n return {\n ...this.toResource(exec),\n variables: payload.variables,\n logs: exec.logs,\n };\n }\n}\n","import { type Static, t } from \"alepha\";\n\nexport const notificationContactPreferencesSchema = t.object({\n language: t.optional(t.text()),\n exclude: t.array(t.text()),\n});\n\nexport type NotificationContactPreferences = Static<\n typeof notificationContactPreferencesSchema\n>;\n","import { type Static, t } from \"alepha\";\n\nexport const notificationContactSchema = t.object({\n email: t.optional(t.email()),\n phoneNumber: t.optional(t.e164()),\n firstName: t.optional(t.shortText()),\n lastName: t.optional(t.text({ size: \"short\" })),\n language: t.optional(t.bcp47()),\n});\n\nexport type NotificationContact = Static<typeof notificationContactSchema>;\n","import { $module } from \"alepha\";\nimport { AlephaApiJobs } from \"alepha/api/jobs\";\nimport { AlephaApiParameters } from \"alepha/api/parameters\";\nimport { AdminNotificationController } from \"./controllers/AdminNotificationController.ts\";\nimport { NotificationJobs } from \"./jobs/NotificationJobs.ts\";\nimport { $notification } from \"./primitives/$notification.ts\";\nimport { NotificationSenderService } from \"./services/NotificationSenderService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/AdminNotificationController.ts\";\nexport * from \"./jobs/NotificationJobs.ts\";\nexport * from \"./primitives/$notification.ts\";\nexport * from \"./schemas/notificationContactPreferencesSchema.ts\";\nexport * from \"./schemas/notificationContactSchema.ts\";\nexport * from \"./schemas/notificationDetailResourceSchema.ts\";\nexport * from \"./schemas/notificationPayloadSchema.ts\";\nexport * from \"./schemas/notificationQuerySchema.ts\";\nexport * from \"./schemas/notificationResourceSchema.ts\";\nexport * from \"./services/NotificationSenderService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * User notification management.\n *\n * **Features:**\n * - Notification definitions (email/SMS templates)\n * - Delivery via `$job` with retry and audit trail (`record: \"all\"` + no ring buffer trim)\n * - Runtime-editable retention window via `$parameter` — purge cron respects it live\n * - Admin API for inspecting sent notifications\n *\n * **Delivery mode** is decided at runtime by the `$job` system:\n * - If your app loads `AlephaApiJobsQueue` (and thus `AlephaQueue`), notifications\n * go through the queue (best for high-volume systems).\n * - Otherwise, notifications run in **direct** mode: pushed to the outbox table\n * and processed in the same process right after the HTTP response is returned.\n * The reconciliation sweep is the safety net for crashes / retries.\n *\n * Direct mode is the recommended default for small / cheap deployments\n * (Cloudflare Workers, single-instance Node) — no queue infrastructure required.\n *\n * @module alepha.api.notifications\n */\nexport const AlephaApiNotifications = $module({\n name: \"alepha.api.notifications\",\n imports: [AlephaApiJobs, AlephaApiParameters],\n primitives: [$notification],\n services: [\n NotificationSenderService,\n NotificationJobs,\n AdminNotificationController,\n ],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/api/notifications/schemas/notificationPayloadSchema.ts","../../../src/api/notifications/primitives/$notification.ts","../../../src/api/notifications/services/NotificationSenderService.ts","../../../src/api/notifications/jobs/NotificationJobs.ts","../../../src/api/notifications/schemas/notificationResourceSchema.ts","../../../src/api/notifications/schemas/notificationDetailResourceSchema.ts","../../../src/api/notifications/schemas/notificationQuerySchema.ts","../../../src/api/notifications/controllers/AdminNotificationController.ts","../../../src/api/notifications/schemas/notificationContactPreferencesSchema.ts","../../../src/api/notifications/schemas/notificationContactSchema.ts","../../../src/api/notifications/index.ts"],"sourcesContent":["import { type Static, z } from \"alepha\";\n\nexport const notificationPayloadSchema = z.object({\n type: z.enum([\"email\", \"sms\"]),\n template: z.text(),\n contact: z.text(),\n variables: z.record(z.text(), z.any()).optional(),\n category: z.text().optional(),\n critical: z.boolean().optional(),\n sensitive: z.boolean().optional(),\n /** Recipient language (e.g. \"fr\" or \"fr-FR\") used to pick `translations`. */\n lang: z.text().optional(),\n});\n\nexport type NotificationPayload = Static<typeof notificationPayloadSchema>;\n","import {\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type Static,\n type StaticEncode,\n type TObject,\n} from \"alepha\";\nimport { currentTenantAtom } from \"alepha/security\";\nimport { NotificationJobs } from \"../jobs/NotificationJobs.ts\";\n\n/**\n * Creates a notification primitive for managing email/SMS notification templates.\n *\n * Provides type-safe, reusable notification templates with multi-language support,\n * variable substitution, and categorization for different notification channels.\n *\n * @example\n * ```ts\n * class NotificationTemplates {\n * welcomeEmail = $notification({\n * name: \"welcome-email\",\n * category: \"onboarding\",\n * schema: z.object({ username: z.text(), activationLink: z.text() }),\n * email: {\n * subject: \"Welcome to our platform!\",\n * body: (vars) => `Hello ${vars.username}, click: ${vars.activationLink}`\n * }\n * });\n *\n * async sendWelcome(user: User) {\n * await this.welcomeEmail.push({\n * variables: { username: user.name, activationLink: generateLink() },\n * contact: user.email\n * });\n * }\n * }\n * ```\n */\nexport const $notification = <T extends TObject>(\n options: NotificationPrimitiveOptions<T>,\n) => createPrimitive(NotificationPrimitive<T>, options);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface NotificationPrimitiveOptions<T extends TObject>\n extends NotificationMessage<T> {\n name?: string;\n description?: string;\n category?: string;\n critical?: boolean;\n sensitive?: boolean;\n translations?: {\n // e.g., \"en\", \"fr\", even \"en-US\"\n [lang: string]: NotificationMessage<T>;\n };\n schema: T;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class NotificationPrimitive<T extends TObject> extends Primitive<\n NotificationPrimitiveOptions<T>\n> {\n protected readonly notificationJobs = $inject(NotificationJobs);\n\n public get name() {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n /**\n * Recipient language for `translations` resolution. Explicit `lang` wins;\n * otherwise the language is captured FROM THE CURRENT REQUEST at push time\n * (the i18n `lang` cookie, then `Accept-Language`) — the send job may run\n * out of request context, so this must be resolved here, not in the sender.\n */\n protected resolveLang(explicit?: string): string | undefined {\n if (explicit) return explicit;\n const request = this.alepha.store.get(\"alepha.http.request\") as\n | { headers?: Record<string, string | undefined> }\n | undefined;\n const cookie = request?.headers?.cookie;\n const fromCookie = cookie?.match(/(?:^|;\\s*)lang=([a-zA-Z-]+)/)?.[1];\n if (fromCookie) return fromCookie;\n const accept = request?.headers?.[\"accept-language\"];\n return accept?.split(\",\")[0]?.trim().split(\";\")[0] || undefined;\n }\n\n public async push(options: NotificationPushOptions<T>) {\n const lang = this.resolveLang(options.lang);\n // Tag the outbox row with the owning tenant so the notification admin list\n // stays org-scoped (the outbox is shared by every tenant in a pooled\n // worker). Explicit `organizationId` wins (cron sweeps run out of request\n // context and pass the subject's org); otherwise fall back to the tenant\n // resolved for the current request.\n const organizationId =\n options.organizationId ?? this.alepha.store.get(currentTenantAtom)?.id;\n const pushOpts = {\n ...(this.options.critical ? ({ priority: \"critical\" } as const) : {}),\n organizationId,\n };\n\n if (this.options.email) {\n await this.notificationJobs.sendNotification.push(\n {\n type: \"email\",\n template: this.name,\n contact: options.contact,\n variables: options.variables as Record<string, unknown>,\n category: this.options.category,\n critical: this.options.critical,\n sensitive: this.options.sensitive,\n lang,\n },\n pushOpts,\n );\n }\n\n if (this.options.sms) {\n await this.notificationJobs.sendNotification.push(\n {\n type: \"sms\",\n template: this.name,\n contact: options.contact,\n variables: options.variables as Record<string, unknown>,\n category: this.options.category,\n critical: this.options.critical,\n sensitive: this.options.sensitive,\n lang,\n },\n pushOpts,\n );\n }\n }\n\n public configure(options: Partial<NotificationPrimitiveOptions<T>>) {\n Object.assign(this.options, options);\n }\n}\n\n$notification[KIND] = NotificationPrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface NotificationPushOptions<T extends TObject> {\n variables: StaticEncode<T>;\n contact: string;\n /** Recipient language (e.g. \"fr\"); defaults to the current request's. */\n lang?: string;\n /**\n * Owning tenant for this notification. Defaults to the tenant resolved for\n * the current request. Pass it explicitly when sending from a context with no\n * request tenant — e.g. a cron sweep that fans out across clubs (use the\n * subject entity's `organizationId`) — so the row stays correctly org-scoped.\n */\n organizationId?: string;\n}\n\nexport interface NotificationMessage<T extends TObject> {\n email?: {\n subject: string;\n body: string | ((variables: Static<T>) => string);\n };\n sms?: {\n message: string | ((variables: Static<T>) => string);\n };\n}\n","import { $inject, Alepha, AlephaError } from \"alepha\";\nimport { EmailProvider } from \"alepha/email\";\nimport { $logger } from \"alepha/logger\";\nimport { SmsProvider } from \"alepha/sms\";\nimport { $notification } from \"../primitives/$notification.ts\";\nimport type { NotificationPayload } from \"../schemas/notificationPayloadSchema.ts\";\n\ntype NotificationMessageEmail = {\n subject: string;\n body: string | ((variables: any) => string);\n};\ntype NotificationMessageSms = {\n message: string | ((variables: any) => string);\n};\n\nexport class NotificationSenderService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly emailProvider = $inject(EmailProvider);\n protected readonly smsProvider = $inject(SmsProvider);\n\n public async send(payload: NotificationPayload) {\n this.log.debug(\"Processing notification\", {\n type: payload.type,\n template: payload.template,\n contact: payload.contact,\n });\n\n if (payload.type === \"email\") {\n const rendered = this.renderEmail(payload);\n await this.emailProvider.send(rendered);\n this.log.info(\"Email notification sent\", {\n template: payload.template,\n contact: payload.contact,\n });\n return {\n type: \"email\" as const,\n to: rendered.to,\n subject: rendered.subject,\n body: rendered.body,\n };\n }\n\n if (payload.type === \"sms\") {\n const rendered = this.renderSms(payload);\n await this.smsProvider.send(rendered);\n this.log.info(\"SMS notification sent\", {\n template: payload.template,\n contact: payload.contact,\n });\n return {\n type: \"sms\" as const,\n to: rendered.to,\n message: rendered.message,\n };\n }\n }\n\n public renderSms(payload: NotificationPayload) {\n const { variables, contact, template } = this.load(payload);\n\n const sms =\n this.translation(template.options, payload.lang)?.sms ??\n template.options.sms;\n if (!sms) {\n throw new AlephaError(\n `Notification template ${payload.template} has no sms defined`,\n );\n }\n\n const message =\n typeof sms.message === \"function\"\n ? sms.message(variables as any)\n : sms.message;\n\n return { to: contact, message };\n }\n\n public renderEmail(payload: NotificationPayload) {\n const { variables, contact, template } = this.load(payload);\n\n const email =\n this.translation(template.options, payload.lang)?.email ??\n template.options.email;\n if (!email) {\n throw new AlephaError(\n `Notification template ${payload.template} has no email defined`,\n );\n }\n\n const subject = email.subject;\n const body =\n typeof email.body === \"function\"\n ? email.body(variables as any)\n : email.body;\n\n return { to: contact, subject, body };\n }\n\n /**\n * Pick the template's `translations` entry for the payload language:\n * exact match (\"fr-FR\") first, then the base language (\"fr\"). Returns\n * undefined when there is no match — callers fall back to the default\n * (template-level) message.\n */\n protected translation(\n options: {\n translations?: Record<\n string,\n { email?: unknown; sms?: unknown } | undefined\n >;\n },\n lang?: string,\n ):\n | { email?: NotificationMessageEmail; sms?: NotificationMessageSms }\n | undefined {\n if (!lang || !options.translations) return undefined;\n const exact = options.translations[lang];\n if (exact) return exact as any;\n const base = lang.split(\"-\")[0]?.toLowerCase();\n return base ? (options.translations[base] as any) : undefined;\n }\n\n protected load(payload: NotificationPayload) {\n const variables = payload.variables || {};\n const contact = payload.contact;\n const template = this.alepha\n .primitives($notification)\n .find((it) => it.name === payload.template);\n\n if (!template) {\n throw new AlephaError(\n `No notification template found for ${payload.template}`,\n );\n }\n\n return { template, variables, contact };\n }\n}\n","import { $inject, z } from \"alepha\";\nimport { $job, jobExecutionEntity } from \"alepha/api/jobs\";\nimport { $parameter } from \"alepha/api/parameters\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport { notificationPayloadSchema } from \"../schemas/notificationPayloadSchema.ts\";\nimport { NotificationSenderService } from \"../services/NotificationSenderService.ts\";\n\n/**\n * Notification jobs + runtime-editable retention.\n *\n * - `settings` — a `$parameter` exposing `retentionDays` that admins can\n * update at runtime. Changes propagate across instances via the parameter\n * pub/sub; the next purge run picks up the new value with no restart.\n * - `sendNotification` — queue-mode, audit-oriented. Every execution is kept\n * (`record: \"all\"`, `keep: { ok: 0, error: 0 }` disables the ring-buffer\n * trim) so the audit trail survives even under heavy volume.\n * - `purgeOldNotifications` — cron sweep that deletes notification execution\n * rows whose `completedAt` is older than the current `retentionDays`.\n *\n * Cron expression note: the purge cron is declared statically (`0 3 * * *`)\n * because some runtimes (Cloudflare Workers) freeze cron triggers at deploy\n * time. The *retention window* is fully runtime-editable — that's the knob\n * that actually matters for operators.\n */\nexport class NotificationJobs {\n protected readonly log = $logger();\n protected readonly dt = $inject(DateTimeProvider);\n protected readonly notificationSenderService = $inject(\n NotificationSenderService,\n );\n protected readonly executions = $repository(jobExecutionEntity);\n\n /** Runtime-editable config. Admins can change retentionDays without deploy. */\n public readonly settings = $parameter({\n name: \"alepha.api.notifications\",\n description: \"Notification delivery & retention settings.\",\n schema: z.object({\n retentionDays: z\n .integer()\n .min(1)\n .describe(\n \"Days to keep notification execution rows before the purge sweep removes them.\",\n ),\n }),\n default: {\n retentionDays: 7,\n },\n });\n\n public readonly sendNotification = $job({\n name: \"api:notifications:sendNotification\",\n description:\n \"Sends a notification (email/SMS) and keeps every execution for audit.\",\n schema: notificationPayloadSchema,\n retry: {\n retries: 3,\n },\n timeout: [30, \"seconds\"],\n record: \"all\",\n keep: { ok: 0, error: 0 },\n handler: async ({ payload }) => {\n await this.notificationSenderService.send(payload);\n },\n });\n\n public readonly purgeOldNotifications = $job({\n name: \"api:notifications:purgeOldNotifications\",\n description:\n \"Hourly sweep that deletes notification execution rows older than the configured retention window.\",\n cron: \"0 * * * *\",\n handler: async ({ now }) => {\n const { retentionDays } = this.settings.cachedCurrentContent;\n const cutoff = now.subtract(retentionDays, \"day\").toISOString();\n const jobName = this.sendNotification.name;\n\n const expired = await this.executions.findMany({\n where: {\n jobName: { eq: jobName },\n status: { inArray: [\"ok\", \"error\", \"cancelled\"] },\n completedAt: { lt: cutoff },\n },\n columns: [\"id\"] as any,\n limit: 5_000,\n });\n\n if (expired.length === 0) {\n this.log.debug(\"Notification purge: nothing to delete\", {\n cutoff,\n retentionDays,\n });\n return;\n }\n\n await this.executions.deleteMany({\n id: { inArray: expired.map((r) => r.id) },\n });\n this.log.info(\n `Notification purge: deleted ${expired.length} row(s) older than ${retentionDays} days`,\n { cutoff },\n );\n },\n });\n}\n","import { type Static, z } from \"alepha\";\n\nexport const notificationResourceSchema = z.object({\n id: z.uuid(),\n createdAt: z.datetime(),\n status: z.text(),\n template: z.text().optional(),\n type: z.text().optional(),\n contact: z.text().optional(),\n category: z.text().optional(),\n critical: z.boolean().optional(),\n sensitive: z.boolean().optional(),\n startedAt: z.datetime().optional(),\n completedAt: z.datetime().optional(),\n error: z.text().optional(),\n});\n\nexport type NotificationResource = Static<typeof notificationResourceSchema>;\n","import { type Static, z } from \"alepha\";\nimport { logEntrySchema } from \"alepha/logger\";\nimport { notificationResourceSchema } from \"./notificationResourceSchema.ts\";\n\nexport const notificationDetailResourceSchema = notificationResourceSchema\n .extend({\n variables: z.record(z.text(), z.any()).optional(),\n rendered: z.record(z.text(), z.any()).optional(),\n logs: z.array(logEntrySchema).optional(),\n })\n .meta({\n title: \"NotificationDetailResource\",\n description: \"A notification resource with rendered content and logs.\",\n });\n\nexport type NotificationDetailResource = Static<\n typeof notificationDetailResourceSchema\n>;\n","import { type Static, z } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\n\nexport const notificationQuerySchema = pageQuerySchema.extend({\n status: z\n .enum([\n \"pending\",\n \"scheduled\",\n \"retrying\",\n \"running\",\n \"completed\",\n \"dead\",\n \"cancelled\",\n ])\n .optional(),\n});\n\nexport type NotificationQuery = Static<typeof notificationQuerySchema>;\n","import { $inject, Alepha, z } from \"alepha\";\nimport { jobExecutionEntity } from \"alepha/api/jobs\";\nimport { $repository } from \"alepha/orm\";\nimport { $secure, currentTenantAtom } from \"alepha/security\";\nimport { $action, NotFoundError, okSchema } from \"alepha/server\";\nimport { NotificationJobs } from \"../jobs/NotificationJobs.ts\";\nimport { notificationDetailResourceSchema } from \"../schemas/notificationDetailResourceSchema.ts\";\nimport { notificationQuerySchema } from \"../schemas/notificationQuerySchema.ts\";\nimport { notificationResourceSchema } from \"../schemas/notificationResourceSchema.ts\";\n\nexport class AdminNotificationController {\n protected readonly url: string = \"/notifications\";\n protected readonly group: string = \"admin:notifications\";\n protected readonly alepha = $inject(Alepha);\n protected readonly notificationJobs = $inject(NotificationJobs);\n protected readonly executions = $repository(jobExecutionEntity);\n\n protected get jobName(): string {\n return this.notificationJobs.sendNotification.name;\n }\n\n /**\n * The tenant this request is acting in, when multi-tenant. The notification\n * outbox (`job_executions`) is shared across tenants in a pooled worker, so\n * every read/delete here is scoped to this org to prevent cross-tenant access.\n * Undefined in single-tenant apps → no extra filter (all rows are this app's).\n */\n protected get organizationId(): string | undefined {\n return this.alepha.store.get(currentTenantAtom)?.id;\n }\n\n /** True when `exec` belongs to the acting tenant (or the app is single-tenant). */\n protected sameTenant(exec: { organizationId?: string | null }): boolean {\n const org = this.organizationId;\n return !org || exec.organizationId === org;\n }\n\n public readonly findNotifications = $action({\n path: this.url,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:read\"] })],\n schema: {\n query: notificationQuerySchema,\n response: z.page(notificationResourceSchema),\n },\n handler: async ({ query }) => {\n query.sort ??= \"-createdAt\";\n const where = this.executions.createQueryWhere();\n where.jobName = { eq: this.jobName };\n const org = this.organizationId;\n if (org) {\n where.organizationId = { eq: org };\n }\n const page = await this.executions.paginate(\n query,\n { where },\n { count: true },\n );\n return {\n ...page,\n content: page.content.map((exec) => this.toResource(exec)),\n } as any;\n },\n });\n\n public readonly getNotification = $action({\n path: `${this.url}/:id`,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:read\"] })],\n schema: {\n params: z.object({\n id: z.uuid(),\n }),\n response: notificationDetailResourceSchema,\n },\n handler: async ({ params }) => {\n const exec = await this.executions.findById(params.id);\n if (!exec || exec.jobName !== this.jobName || !this.sameTenant(exec)) {\n throw new NotFoundError(`Notification not found: ${params.id}`);\n }\n return this.toDetailResource(exec) as any;\n },\n });\n\n public readonly deleteNotification = $action({\n method: \"DELETE\",\n path: `${this.url}/:id`,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:delete\"] })],\n description: \"Delete a notification record\",\n schema: {\n params: z.object({\n id: z.uuid(),\n }),\n response: okSchema,\n },\n handler: async ({ params }) => {\n const exec = await this.executions.findById(params.id);\n if (!exec || exec.jobName !== this.jobName || !this.sameTenant(exec)) {\n throw new NotFoundError(`Notification not found: ${params.id}`);\n }\n await this.executions.deleteById(params.id);\n return { ok: true, id: params.id };\n },\n });\n\n public readonly deleteNotifications = $action({\n method: \"POST\",\n path: `${this.url}/delete`,\n group: this.group,\n use: [$secure({ permissions: [\"admin:notification:delete\"] })],\n description: \"Delete many notification records in one call\",\n schema: {\n body: z.object({\n ids: z.array(z.uuid()).min(1).max(1000),\n }),\n response: z.object({\n deleted: z.array(z.uuid()),\n }),\n },\n handler: async ({ body }) => {\n // Constrain to this job's executions so an admin can't delete arbitrary\n // job rows through this endpoint — and, when multi-tenant, to this org so\n // one club can't delete another club's notification records.\n const org = this.organizationId;\n const deleted = await this.executions.deleteMany({\n id: { inArray: body.ids },\n jobName: { eq: this.jobName },\n ...(org ? { organizationId: { eq: org } } : {}),\n });\n return { deleted: deleted.map(String) };\n },\n });\n\n protected toResource(exec: Record<string, unknown>) {\n const payload = (exec.payload ?? {}) as Record<string, unknown>;\n return {\n id: exec.id,\n createdAt: exec.createdAt,\n status: exec.status,\n template: payload.template,\n type: payload.type,\n contact: payload.contact,\n category: payload.category,\n critical: payload.critical,\n sensitive: payload.sensitive,\n startedAt: exec.startedAt,\n completedAt: exec.completedAt,\n error: exec.error,\n };\n }\n\n protected toDetailResource(exec: Record<string, unknown>) {\n const payload = (exec.payload ?? {}) as Record<string, unknown>;\n return {\n ...this.toResource(exec),\n variables: payload.variables,\n logs: exec.logs,\n };\n }\n}\n","import { type Static, z } from \"alepha\";\n\nexport const notificationContactPreferencesSchema = z.object({\n language: z.text().optional(),\n exclude: z.array(z.text()),\n});\n\nexport type NotificationContactPreferences = Static<\n typeof notificationContactPreferencesSchema\n>;\n","import { type Static, z } from \"alepha\";\n\nexport const notificationContactSchema = z.object({\n email: z.email().optional(),\n phoneNumber: z.e164().optional(),\n firstName: z.shortText().optional(),\n lastName: z.text({ size: \"short\" }).optional(),\n language: z.bcp47().optional(),\n});\n\nexport type NotificationContact = Static<typeof notificationContactSchema>;\n","import { $module } from \"alepha\";\nimport { AlephaApiJobs } from \"alepha/api/jobs\";\nimport { AlephaApiParameters } from \"alepha/api/parameters\";\nimport { AdminNotificationController } from \"./controllers/AdminNotificationController.ts\";\nimport { NotificationJobs } from \"./jobs/NotificationJobs.ts\";\nimport { $notification } from \"./primitives/$notification.ts\";\nimport { NotificationSenderService } from \"./services/NotificationSenderService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/AdminNotificationController.ts\";\nexport * from \"./jobs/NotificationJobs.ts\";\nexport * from \"./primitives/$notification.ts\";\nexport * from \"./schemas/notificationContactPreferencesSchema.ts\";\nexport * from \"./schemas/notificationContactSchema.ts\";\nexport * from \"./schemas/notificationDetailResourceSchema.ts\";\nexport * from \"./schemas/notificationPayloadSchema.ts\";\nexport * from \"./schemas/notificationQuerySchema.ts\";\nexport * from \"./schemas/notificationResourceSchema.ts\";\nexport * from \"./services/NotificationSenderService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * User notification management.\n *\n * **Features:**\n * - Notification definitions (email/SMS templates)\n * - Delivery via `$job` with retry and audit trail (`record: \"all\"` + no ring buffer trim)\n * - Runtime-editable retention window via `$parameter` — purge cron respects it live\n * - Admin API for inspecting sent notifications\n *\n * **Delivery mode** is decided at runtime by the `$job` system:\n * - If your app loads `AlephaApiJobsQueue` (and thus `AlephaQueue`), notifications\n * go through the queue (best for high-volume systems).\n * - Otherwise, notifications run in **direct** mode: pushed to the outbox table\n * and processed in the same process right after the HTTP response is returned.\n * The reconciliation sweep is the safety net for crashes / retries.\n *\n * Direct mode is the recommended default for small / cheap deployments\n * (Cloudflare Workers, single-instance Node) — no queue infrastructure required.\n *\n * @module alepha.api.notifications\n */\nexport const AlephaApiNotifications = $module({\n name: \"alepha.api.notifications\",\n imports: [AlephaApiJobs, AlephaApiParameters],\n primitives: [$notification],\n services: [\n NotificationSenderService,\n NotificationJobs,\n AdminNotificationController,\n ],\n});\n"],"mappings":"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"}
|