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,4 +1,4 @@
|
|
|
1
|
-
import { $atom, $inject, $module, $state,
|
|
1
|
+
import { $atom, $inject, $module, $state, z } from "alepha";
|
|
2
2
|
import { $action, BadRequestError, NotFoundError } from "alepha/server";
|
|
3
3
|
import { createHash, randomInt } from "node:crypto";
|
|
4
4
|
import { CryptoProvider } from "alepha/crypto";
|
|
@@ -6,37 +6,29 @@ import { DateTimeProvider } from "alepha/datetime";
|
|
|
6
6
|
import { $logger } from "alepha/logger";
|
|
7
7
|
import { $entity, $repository, db } from "alepha/orm";
|
|
8
8
|
import { $scheduler } from "alepha/scheduler";
|
|
9
|
-
//#region ../../src/api/verifications/schemas/requestVerificationCodeResponseSchema.ts
|
|
10
|
-
const requestVerificationCodeResponseSchema = t.object({
|
|
11
|
-
token: t.string({ description: "The verification token (6-digit code for phone, UUID for email). The caller should send this to the user via their preferred notification method." }),
|
|
12
|
-
codeExpiration: t.integer({ description: "Time in seconds before your verification token expires." }),
|
|
13
|
-
verificationCooldown: t.integer({ description: "Cooldown period in seconds before you can request another verification." }),
|
|
14
|
-
maxVerificationAttempts: t.integer({ description: "Maximum number of verification attempts allowed before the token is locked." })
|
|
15
|
-
});
|
|
16
|
-
//#endregion
|
|
17
9
|
//#region ../../src/api/verifications/schemas/validateVerificationCodeResponseSchema.ts
|
|
18
|
-
const validateVerificationCodeResponseSchema =
|
|
19
|
-
ok:
|
|
20
|
-
alreadyVerified:
|
|
10
|
+
const validateVerificationCodeResponseSchema = z.object({
|
|
11
|
+
ok: z.boolean().describe("Indicates whether the verification was successful."),
|
|
12
|
+
alreadyVerified: z.boolean().describe("Indicates whether the target was already verified.").optional()
|
|
21
13
|
});
|
|
22
14
|
//#endregion
|
|
23
15
|
//#region ../../src/api/verifications/schemas/verificationTypeEnumSchema.ts
|
|
24
|
-
const verificationTypeEnumSchema =
|
|
16
|
+
const verificationTypeEnumSchema = z.enum(["code", "link"]);
|
|
25
17
|
//#endregion
|
|
26
18
|
//#region ../../src/api/verifications/entities/verifications.ts
|
|
27
19
|
const verifications = $entity({
|
|
28
20
|
name: "verification",
|
|
29
|
-
schema:
|
|
30
|
-
id: db.primaryKey(
|
|
21
|
+
schema: z.object({
|
|
22
|
+
id: db.primaryKey(z.bigint()),
|
|
31
23
|
createdAt: db.createdAt(),
|
|
32
24
|
updatedAt: db.updatedAt(),
|
|
33
25
|
version: db.version(),
|
|
34
26
|
type: verificationTypeEnumSchema,
|
|
35
|
-
target:
|
|
36
|
-
purpose: db.default(
|
|
37
|
-
code:
|
|
38
|
-
verifiedAt:
|
|
39
|
-
attempts: db.default(
|
|
27
|
+
target: z.text({ description: "Can be a phone (E.164 format) or email address" }),
|
|
28
|
+
purpose: db.default(z.text({ description: "Logical purpose bucket (e.g. 'default', 'password-reset'). Scopes the cooldown and daily-limit checks so unrelated flows that share the same (type, target) — most notably email verification and password reset — don't collide." }), "default"),
|
|
29
|
+
code: z.text({ description: "Hashed verification token (n-digit code or UUID)" }),
|
|
30
|
+
verifiedAt: z.datetime().describe("When it was successfully verified").optional(),
|
|
31
|
+
attempts: db.default(z.integer().describe("Number of failed attempts (to prevent brute-force)"), 0)
|
|
40
32
|
}),
|
|
41
33
|
indexes: ["createdAt", { columns: ["target", "code"] }]
|
|
42
34
|
});
|
|
@@ -49,61 +41,21 @@ const verificationEntityInsertSchema = verifications.insertSchema;
|
|
|
49
41
|
*/
|
|
50
42
|
const verificationOptions = $atom({
|
|
51
43
|
name: "alepha.api.verifications.options",
|
|
52
|
-
schema:
|
|
53
|
-
code:
|
|
54
|
-
maxAttempts:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
maximum: 3600
|
|
68
|
-
}),
|
|
69
|
-
verificationCooldown: t.integer({
|
|
70
|
-
description: "Cooldown period in seconds after a request verification.",
|
|
71
|
-
minimum: 0,
|
|
72
|
-
maximum: 3600
|
|
73
|
-
}),
|
|
74
|
-
limitPerDay: t.integer({
|
|
75
|
-
description: "Maximum number of verification requests per day for one entry.",
|
|
76
|
-
minimum: 1,
|
|
77
|
-
maximum: 100
|
|
78
|
-
})
|
|
79
|
-
}, { description: "Settings specific to code verifications." }),
|
|
80
|
-
link: t.object({
|
|
81
|
-
maxAttempts: t.integer({
|
|
82
|
-
description: "Maximum number of attempts before locking the verification.",
|
|
83
|
-
minimum: 1,
|
|
84
|
-
maximum: 10
|
|
85
|
-
}),
|
|
86
|
-
codeExpiration: t.integer({
|
|
87
|
-
description: "Time in seconds before the verification token expires.",
|
|
88
|
-
minimum: 60,
|
|
89
|
-
maximum: 7200
|
|
90
|
-
}),
|
|
91
|
-
verificationCooldown: t.integer({
|
|
92
|
-
description: "Cooldown period in seconds after a request verification.",
|
|
93
|
-
minimum: 0,
|
|
94
|
-
maximum: 3600
|
|
95
|
-
}),
|
|
96
|
-
limitPerDay: t.integer({
|
|
97
|
-
description: "Maximum number of verification requests per day for one entry.",
|
|
98
|
-
minimum: 1,
|
|
99
|
-
maximum: 100
|
|
100
|
-
})
|
|
101
|
-
}, { description: "Settings specific to link verifications." }),
|
|
102
|
-
purgeDays: t.integer({
|
|
103
|
-
description: "Number of days after which expired verifications are automatically deleted. Set to 0 to disable auto-deletion.",
|
|
104
|
-
minimum: 0,
|
|
105
|
-
maximum: 365
|
|
106
|
-
})
|
|
44
|
+
schema: z.object({
|
|
45
|
+
code: z.object({
|
|
46
|
+
maxAttempts: z.integer().min(1).max(10).describe("Maximum number of attempts before locking the verification."),
|
|
47
|
+
codeLength: z.integer().min(4).max(12).describe("Length of the verification code."),
|
|
48
|
+
codeExpiration: z.integer().min(60).max(3600).describe("Time in seconds before the verification code expires."),
|
|
49
|
+
verificationCooldown: z.integer().min(0).max(3600).describe("Cooldown period in seconds after a request verification."),
|
|
50
|
+
limitPerDay: z.integer().min(1).max(100).describe("Maximum number of verification requests per day for one entry.")
|
|
51
|
+
}).describe("Settings specific to code verifications."),
|
|
52
|
+
link: z.object({
|
|
53
|
+
maxAttempts: z.integer().min(1).max(10).describe("Maximum number of attempts before locking the verification."),
|
|
54
|
+
codeExpiration: z.integer().min(60).max(7200).describe("Time in seconds before the verification token expires."),
|
|
55
|
+
verificationCooldown: z.integer().min(0).max(3600).describe("Cooldown period in seconds after a request verification."),
|
|
56
|
+
limitPerDay: z.integer().min(1).max(100).describe("Maximum number of verification requests per day for one entry.")
|
|
57
|
+
}).describe("Settings specific to link verifications."),
|
|
58
|
+
purgeDays: z.integer().min(0).max(365).describe("Number of days after which expired verifications are automatically deleted. Set to 0 to disable auto-deletion.")
|
|
107
59
|
}),
|
|
108
60
|
default: {
|
|
109
61
|
code: {
|
|
@@ -248,6 +200,14 @@ var VerificationService = class {
|
|
|
248
200
|
const settings = this.verificationParameters.get(entry.type);
|
|
249
201
|
const verification = await this.findByEntry(entry);
|
|
250
202
|
if (verification.verifiedAt) {
|
|
203
|
+
if (verification.code !== this.hashCode(code)) {
|
|
204
|
+
this.log.warn("Invalid code submitted for already-verified entry", {
|
|
205
|
+
id: verification.id,
|
|
206
|
+
type: entry.type,
|
|
207
|
+
target: entry.target
|
|
208
|
+
});
|
|
209
|
+
throw new BadRequestError("Invalid verification code");
|
|
210
|
+
}
|
|
251
211
|
this.log.debug("Verification already verified", {
|
|
252
212
|
id: verification.id,
|
|
253
213
|
type: entry.type,
|
|
@@ -318,31 +278,15 @@ var VerificationController = class {
|
|
|
318
278
|
verificationService = $inject(VerificationService);
|
|
319
279
|
url = "/verifications";
|
|
320
280
|
group = "verifications";
|
|
321
|
-
requestVerificationCode = $action({
|
|
322
|
-
path: `${this.url}/:type`,
|
|
323
|
-
group: this.group,
|
|
324
|
-
method: "POST",
|
|
325
|
-
schema: {
|
|
326
|
-
params: t.object({ type: verificationTypeEnumSchema }),
|
|
327
|
-
body: t.object({ target: t.text() }),
|
|
328
|
-
response: requestVerificationCodeResponseSchema
|
|
329
|
-
},
|
|
330
|
-
handler: async ({ body, params }) => {
|
|
331
|
-
return await this.verificationService.createVerification({
|
|
332
|
-
type: params.type,
|
|
333
|
-
target: body.target
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
281
|
validateVerificationCode = $action({
|
|
338
282
|
path: `${this.url}/:type/validate`,
|
|
339
283
|
group: this.group,
|
|
340
284
|
method: "POST",
|
|
341
285
|
schema: {
|
|
342
|
-
params:
|
|
343
|
-
body:
|
|
344
|
-
target:
|
|
345
|
-
token:
|
|
286
|
+
params: z.object({ type: verificationTypeEnumSchema }),
|
|
287
|
+
body: z.object({
|
|
288
|
+
target: z.text(),
|
|
289
|
+
token: z.text({ description: "The verification token (6-digit code for phone, UUID for email)." })
|
|
346
290
|
}),
|
|
347
291
|
response: validateVerificationCodeResponseSchema
|
|
348
292
|
},
|
|
@@ -373,6 +317,14 @@ var VerificationJobs = class {
|
|
|
373
317
|
});
|
|
374
318
|
};
|
|
375
319
|
//#endregion
|
|
320
|
+
//#region ../../src/api/verifications/schemas/requestVerificationCodeResponseSchema.ts
|
|
321
|
+
const requestVerificationCodeResponseSchema = z.object({
|
|
322
|
+
token: z.string().describe("The verification token (6-digit code for phone, UUID for email). The caller should send this to the user via their preferred notification method."),
|
|
323
|
+
codeExpiration: z.integer().describe("Time in seconds before your verification token expires."),
|
|
324
|
+
verificationCooldown: z.integer().describe("Cooldown period in seconds before you can request another verification."),
|
|
325
|
+
maxVerificationAttempts: z.integer().describe("Maximum number of verification attempts allowed before the token is locked.")
|
|
326
|
+
});
|
|
327
|
+
//#endregion
|
|
376
328
|
//#region ../../src/api/verifications/index.ts
|
|
377
329
|
/**
|
|
378
330
|
* Email and phone verification workflows.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/api/verifications/schemas/requestVerificationCodeResponseSchema.ts","../../../src/api/verifications/schemas/validateVerificationCodeResponseSchema.ts","../../../src/api/verifications/schemas/verificationTypeEnumSchema.ts","../../../src/api/verifications/entities/verifications.ts","../../../src/api/verifications/schemas/verificationSettingsSchema.ts","../../../src/api/verifications/parameters/VerificationParameters.ts","../../../src/api/verifications/services/VerificationService.ts","../../../src/api/verifications/controllers/VerificationController.ts","../../../src/api/verifications/jobs/VerificationJobs.ts","../../../src/api/verifications/index.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const requestVerificationCodeResponseSchema = t.object({\n token: t.string({\n description:\n \"The verification token (6-digit code for phone, UUID for email). The caller should send this to the user via their preferred notification method.\",\n }),\n codeExpiration: t.integer({\n description: \"Time in seconds before your verification token expires.\",\n }),\n verificationCooldown: t.integer({\n description:\n \"Cooldown period in seconds before you can request another verification.\",\n }),\n maxVerificationAttempts: t.integer({\n description:\n \"Maximum number of verification attempts allowed before the token is locked.\",\n }),\n});\n\nexport type RequestVerificationResponse = Static<\n typeof requestVerificationCodeResponseSchema\n>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const validateVerificationCodeResponseSchema = t.object({\n ok: t.boolean({\n description: \"Indicates whether the verification was successful.\",\n }),\n alreadyVerified: t.optional(\n t.boolean({\n description: \"Indicates whether the target was already verified.\",\n }),\n ),\n});\n\nexport type ValidateVerificationCodeResponse = Static<\n typeof validateVerificationCodeResponseSchema\n>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const verificationTypeEnumSchema = t.enum([\"code\", \"link\"]);\nexport type VerificationTypeEnum = Static<typeof verificationTypeEnumSchema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\nimport { verificationTypeEnumSchema } from \"../schemas/verificationTypeEnumSchema.ts\";\n\nexport const verifications = $entity({\n name: \"verification\",\n schema: t.object({\n id: db.primaryKey(t.bigint()),\n\n createdAt: db.createdAt(),\n\n updatedAt: db.updatedAt(),\n\n version: db.version(),\n\n type: verificationTypeEnumSchema,\n\n target: t.text({\n description: \"Can be a phone (E.164 format) or email address\",\n }),\n\n purpose: db.default(\n t.text({\n description:\n \"Logical purpose bucket (e.g. 'default', 'password-reset'). Scopes the cooldown and daily-limit checks so unrelated flows that share the same (type, target) — most notably email verification and password reset — don't collide.\",\n }),\n \"default\",\n ),\n\n code: t.text({\n description: \"Hashed verification token (n-digit code or UUID)\",\n }),\n\n verifiedAt: t.optional(\n t.datetime({\n description: \"When it was successfully verified\",\n }),\n ),\n\n attempts: db.default(\n t.integer({\n description: \"Number of failed attempts (to prevent brute-force)\",\n }),\n 0,\n ),\n }),\n indexes: [\n \"createdAt\",\n {\n columns: [\"target\", \"code\"],\n },\n ],\n});\n\nexport const verificationEntitySchema = verifications.schema;\nexport const verificationEntityInsertSchema = verifications.insertSchema;\nexport type VerificationEntity = Static<typeof verifications.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const verificationSettingsSchema = t.object({\n code: t.object(\n {\n maxAttempts: t.integer({\n description:\n \"Maximum number of attempts before locking the verification.\",\n minimum: 1,\n maximum: 10,\n }),\n codeLength: t.integer({\n description: \"Length of the verification code.\",\n minimum: 4,\n maximum: 12,\n }),\n codeExpiration: t.integer({\n description: \"Time in seconds before the verification code expires.\",\n minimum: 60, // 1 minute\n maximum: 3600, // 1 hour\n }),\n verificationCooldown: t.integer({\n description: \"Cooldown period in seconds after a request verification.\",\n minimum: 0,\n maximum: 3600, // 1 hour\n }),\n limitPerDay: t.integer({\n description:\n \"Maximum number of verification requests per day for one entry.\",\n minimum: 1,\n maximum: 100,\n }),\n },\n {\n description: \"Settings specific to code verifications.\",\n },\n ),\n link: t.object(\n {\n maxAttempts: t.integer({\n description:\n \"Maximum number of attempts before locking the verification.\",\n minimum: 1,\n maximum: 10,\n }),\n codeExpiration: t.integer({\n description: \"Time in seconds before the verification token expires.\",\n minimum: 60, // 1 minute\n maximum: 7200, // 2 hours\n }),\n verificationCooldown: t.integer({\n description: \"Cooldown period in seconds after a request verification.\",\n minimum: 0,\n maximum: 3600, // 1 hour\n }),\n limitPerDay: t.integer({\n description:\n \"Maximum number of verification requests per day for one entry.\",\n minimum: 1,\n maximum: 100,\n }),\n },\n {\n description: \"Settings specific to link verifications.\",\n },\n ),\n purgeDays: t.integer({\n description:\n \"Number of days after which expired verifications are automatically deleted. Set to 0 to disable auto-deletion.\",\n minimum: 0,\n maximum: 365,\n }),\n});\n\nexport type VerificationSettings = Static<typeof verificationSettingsSchema>;\n","import { $atom, $state, type Static } from \"alepha\";\nimport {\n type VerificationSettings,\n verificationSettingsSchema,\n} from \"../schemas/verificationSettingsSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Verification settings configuration atom\n */\nexport const verificationOptions = $atom({\n name: \"alepha.api.verifications.options\",\n schema: verificationSettingsSchema,\n default: {\n code: {\n maxAttempts: 5,\n codeLength: 6,\n codeExpiration: 300, // 5 minutes\n verificationCooldown: 90,\n limitPerDay: 10,\n },\n link: {\n maxAttempts: 3, // Lower since UUIDs are harder to guess\n codeExpiration: 1800, // 30 minutes\n verificationCooldown: 90,\n limitPerDay: 10,\n },\n purgeDays: 1,\n },\n});\n\nexport type VerificationOptions = Static<typeof verificationOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [verificationOptions.key]: VerificationOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class VerificationParameters {\n protected readonly options = $state(verificationOptions);\n\n public get<K extends keyof VerificationSettings>(\n key: K,\n ): VerificationSettings[K] {\n return this.options[key];\n }\n}\n","import { createHash, randomInt } from \"node:crypto\";\nimport { $inject } from \"alepha\";\nimport { CryptoProvider } from \"alepha/crypto\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport { BadRequestError, NotFoundError } from \"alepha/server\";\nimport {\n type VerificationEntity,\n verifications,\n} from \"../entities/verifications.ts\";\nimport { VerificationParameters } from \"../parameters/VerificationParameters.ts\";\nimport type { RequestVerificationResponse } from \"../schemas/requestVerificationCodeResponseSchema.ts\";\nimport type { ValidateVerificationCodeResponse } from \"../schemas/validateVerificationCodeResponseSchema.ts\";\nimport type { VerificationTypeEnum } from \"../schemas/verificationTypeEnumSchema.ts\";\n\nexport class VerificationService {\n protected readonly log = $logger();\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly crypto = $inject(CryptoProvider);\n protected readonly verificationParameters = $inject(VerificationParameters);\n protected readonly verificationRepository = $repository(verifications);\n\n public async findByEntry(\n entry: VerificationEntry,\n ): Promise<VerificationEntity> {\n this.log.trace(\"Finding verification by entry\", {\n type: entry.type,\n target: entry.target,\n });\n\n const results = await this.verificationRepository.findMany({\n limit: 1, // only need the most recent entry\n orderBy: {\n column: \"createdAt\",\n direction: \"desc\",\n },\n where: {\n type: { eq: entry.type },\n target: { eq: entry.target },\n purpose: { eq: entry.purpose ?? \"default\" },\n },\n });\n\n if (results.length === 0) {\n this.log.debug(\"Verification entry not found\", {\n type: entry.type,\n target: entry.target,\n });\n throw new NotFoundError(\"Verification entry not found\");\n }\n\n this.log.debug(\"Verification entry found\", {\n id: results[0].id,\n type: entry.type,\n target: entry.target,\n });\n\n return results[0];\n }\n\n public findRecentsByEntry(entry: VerificationEntry) {\n this.log.trace(\"Finding recent verifications by entry\", {\n type: entry.type,\n target: entry.target,\n });\n\n return this.verificationRepository.findMany({\n orderBy: {\n column: \"createdAt\",\n direction: \"desc\",\n },\n where: {\n type: { eq: entry.type },\n target: { eq: entry.target },\n purpose: { eq: entry.purpose ?? \"default\" },\n createdAt: {\n gte: this.dateTimeProvider.now().startOf(\"day\").toISOString(),\n },\n },\n });\n }\n\n /**\n * Creates a verification entry and returns the token.\n * The caller is responsible for sending notifications with the token.\n * This allows for context-specific notifications (e.g., password reset vs email verification).\n */\n public async createVerification(\n entry: VerificationEntry,\n ): Promise<RequestVerificationResponse> {\n this.log.trace(\"Creating verification\", {\n type: entry.type,\n target: entry.target,\n });\n\n const settings = this.verificationParameters.get(entry.type);\n\n const recents = await this.findRecentsByEntry(entry);\n if (recents.length >= settings.limitPerDay) {\n this.log.warn(\"Daily verification limit reached\", {\n type: entry.type,\n target: entry.target,\n limit: settings.limitPerDay,\n count: recents.length,\n });\n throw new BadRequestError(\n `Maximum number of verification requests per day reached (${settings.limitPerDay})`,\n );\n }\n\n const existingVerification = recents[0];\n if (existingVerification) {\n const nowSec = this.dateTimeProvider.now().unix();\n const createdAtSec = this.dateTimeProvider\n .of(existingVerification.createdAt)\n .unix();\n\n const diffSec = nowSec - createdAtSec;\n if (diffSec < settings.verificationCooldown) {\n const remainingCooldown = Math.floor(\n settings.verificationCooldown - diffSec,\n );\n this.log.debug(\"Verification on cooldown\", {\n type: entry.type,\n target: entry.target,\n remainingSeconds: remainingCooldown,\n });\n throw new BadRequestError(\n `Verification is on cooldown for ${remainingCooldown} seconds`,\n );\n }\n }\n\n const token = this.generateToken(entry.type);\n\n const verification = await this.verificationRepository.create({\n type: entry.type,\n target: entry.target,\n purpose: entry.purpose ?? \"default\",\n code: this.hashCode(token),\n createdAt: this.dateTimeProvider.nowISOString(),\n });\n\n this.log.info(\"Verification created\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n expiresInSeconds: settings.codeExpiration,\n });\n\n return {\n token,\n codeExpiration: settings.codeExpiration,\n verificationCooldown: settings.verificationCooldown,\n maxVerificationAttempts: settings.maxAttempts,\n };\n }\n\n public async verifyCode(\n entry: VerificationEntry,\n code: string,\n ): Promise<ValidateVerificationCodeResponse> {\n this.log.trace(\"Verifying code\", {\n type: entry.type,\n target: entry.target,\n });\n\n const settings = this.verificationParameters.get(entry.type);\n\n const verification = await this.findByEntry(entry);\n if (verification.verifiedAt) {\n this.log.debug(\"Verification already verified\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n verifiedAt: verification.verifiedAt,\n });\n return { ok: true, alreadyVerified: true };\n }\n\n // DO NOT DELETE THE VERIFICATION WHEN IT IS REJECTED,\n // or we won't be able to cooldown the verification\n\n const now = this.dateTimeProvider.now();\n const expirationDate = this.dateTimeProvider\n .of(verification.createdAt)\n .add(settings.codeExpiration, \"seconds\");\n\n if (now > expirationDate) {\n this.log.warn(\"Verification code expired\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n createdAt: verification.createdAt,\n expiredAt: expirationDate.toISOString(),\n });\n throw new BadRequestError(\"Verification code has expired\");\n }\n\n if (verification.attempts >= settings.maxAttempts) {\n this.log.warn(\"Verification locked due to max attempts\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n attempts: verification.attempts,\n maxAttempts: settings.maxAttempts,\n });\n throw new BadRequestError(\n \"Maximum number of attempts reached - verification is locked\",\n );\n }\n\n if (verification.code !== this.hashCode(code)) {\n const newAttempts = verification.attempts + 1;\n this.log.warn(\"Invalid verification code\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n attempts: newAttempts,\n maxAttempts: settings.maxAttempts,\n });\n await this.verificationRepository.updateById(verification.id, {\n attempts: newAttempts,\n });\n throw new BadRequestError(\"Invalid verification code\");\n }\n\n await this.verificationRepository.updateById(verification.id, {\n verifiedAt: this.dateTimeProvider.nowISOString(),\n });\n\n this.log.info(\"Verification code verified\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n });\n\n return { ok: true };\n }\n\n public hashCode(code: string): string {\n return createHash(\"sha256\").update(code).digest(\"hex\");\n }\n\n public generateToken(type: VerificationTypeEnum): string {\n if (type === \"code\") {\n const settings = this.verificationParameters.get(\"code\");\n return randomInt(0, 1_000_000)\n .toString()\n .padStart(settings.codeLength, \"0\");\n } else if (type === \"link\") {\n return this.crypto.randomUUID();\n }\n\n throw new BadRequestError(`Invalid verification type: ${type}`);\n }\n}\n\nexport interface VerificationEntry {\n type: VerificationTypeEnum;\n target: string;\n\n /**\n * Logical purpose bucket. Cooldown and daily-limit checks are scoped to\n * `(type, target, purpose)`, so flows that share a `(type, target)` pair\n * — e.g. email verification and password reset, both `type: \"code\"` on the\n * same email — get independent rate-limit windows instead of colliding.\n *\n * Defaults to `\"default\"` when omitted (back-compatible with callers and\n * rows that predate this field).\n */\n purpose?: string;\n}\n","import { $inject, t } from \"alepha\";\nimport { $action } from \"alepha/server\";\nimport { requestVerificationCodeResponseSchema } from \"../schemas/requestVerificationCodeResponseSchema.ts\";\nimport { validateVerificationCodeResponseSchema } from \"../schemas/validateVerificationCodeResponseSchema.ts\";\nimport { verificationTypeEnumSchema } from \"../schemas/verificationTypeEnumSchema.ts\";\nimport { VerificationService } from \"../services/VerificationService.ts\";\n\nexport class VerificationController {\n protected readonly verificationService = $inject(VerificationService);\n\n public readonly url = \"/verifications\";\n public readonly group = \"verifications\";\n\n public readonly requestVerificationCode = $action({\n path: `${this.url}/:type`,\n group: this.group,\n method: \"POST\",\n schema: {\n params: t.object({\n type: verificationTypeEnumSchema,\n }),\n body: t.object({\n target: t.text(),\n }),\n response: requestVerificationCodeResponseSchema,\n },\n handler: async ({ body, params }) => {\n return await this.verificationService.createVerification({\n type: params.type,\n target: body.target,\n });\n },\n });\n\n public readonly validateVerificationCode = $action({\n path: `${this.url}/:type/validate`,\n group: this.group,\n method: \"POST\",\n schema: {\n params: t.object({\n type: verificationTypeEnumSchema,\n }),\n body: t.object({\n target: t.text(),\n token: t.text({\n description:\n \"The verification token (6-digit code for phone, UUID for email).\",\n }),\n }),\n response: validateVerificationCodeResponseSchema,\n },\n handler: async ({ body, params }) => {\n return this.verificationService.verifyCode(\n {\n type: params.type,\n target: body.target,\n },\n body.token,\n );\n },\n });\n}\n","import { $inject } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $repository } from \"alepha/orm\";\nimport { $scheduler } from \"alepha/scheduler\";\nimport { verifications } from \"../entities/verifications.ts\";\nimport { VerificationParameters } from \"../parameters/VerificationParameters.ts\";\n\nexport class VerificationJobs {\n protected readonly verificationRepository = $repository(verifications);\n protected readonly verificationParameters = $inject(VerificationParameters);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n public readonly cleanExpired = $scheduler({\n name: \"api:verifications:cleanExpired\",\n cron: \"0 * * * *\", // Hourly at minute 0\n description: \"Clean expired verifications\",\n handler: async () => {\n const purgeDays = this.verificationParameters.get(\"purgeDays\");\n if (purgeDays <= 0) {\n return; // Auto deletion is disabled\n }\n\n const dayMs = 24 * 60 * 60 * 1000;\n const purgeThreshold =\n this.dateTimeProvider.nowMillis() - purgeDays * dayMs;\n\n await this.verificationRepository.deleteMany({\n createdAt: {\n lt: this.dateTimeProvider.of(purgeThreshold).toISOString(),\n },\n });\n },\n });\n}\n","import { $module } from \"alepha\";\nimport { VerificationController } from \"./controllers/VerificationController.ts\";\nimport { VerificationJobs } from \"./jobs/VerificationJobs.ts\";\nimport { VerificationParameters } from \"./parameters/VerificationParameters.ts\";\nimport { VerificationService } from \"./services/VerificationService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/VerificationController.ts\";\nexport * from \"./entities/verifications.ts\";\nexport * from \"./jobs/VerificationJobs.ts\";\nexport * from \"./parameters/VerificationParameters.ts\";\nexport * from \"./schemas/requestVerificationCodeResponseSchema.ts\";\nexport * from \"./schemas/validateVerificationCodeResponseSchema.ts\";\nexport * from \"./schemas/verificationTypeEnumSchema.ts\";\nexport * from \"./services/VerificationService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Email and phone verification workflows.\n *\n * **Features:**\n * - Verification token generation\n * - Verification code sending\n * - Verification completion tracking\n * - Resend functionality\n *\n * @module alepha.api.verifications\n */\nexport const AlephaApiVerification = $module({\n name: \"alepha.api.verifications\",\n services: [\n VerificationController,\n VerificationJobs,\n VerificationService,\n VerificationParameters,\n ],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/api/verifications/schemas/validateVerificationCodeResponseSchema.ts","../../../src/api/verifications/schemas/verificationTypeEnumSchema.ts","../../../src/api/verifications/entities/verifications.ts","../../../src/api/verifications/schemas/verificationSettingsSchema.ts","../../../src/api/verifications/parameters/VerificationParameters.ts","../../../src/api/verifications/services/VerificationService.ts","../../../src/api/verifications/controllers/VerificationController.ts","../../../src/api/verifications/jobs/VerificationJobs.ts","../../../src/api/verifications/schemas/requestVerificationCodeResponseSchema.ts","../../../src/api/verifications/index.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { z } from \"alepha\";\n\nexport const validateVerificationCodeResponseSchema = z.object({\n ok: z\n .boolean()\n .describe(\"Indicates whether the verification was successful.\"),\n alreadyVerified: z\n .boolean()\n .describe(\"Indicates whether the target was already verified.\")\n .optional(),\n});\n\nexport type ValidateVerificationCodeResponse = Static<\n typeof validateVerificationCodeResponseSchema\n>;\n","import type { Static } from \"alepha\";\nimport { z } from \"alepha\";\n\nexport const verificationTypeEnumSchema = z.enum([\"code\", \"link\"]);\nexport type VerificationTypeEnum = Static<typeof verificationTypeEnumSchema>;\n","import type { Static } from \"alepha\";\nimport { z } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\nimport { verificationTypeEnumSchema } from \"../schemas/verificationTypeEnumSchema.ts\";\n\nexport const verifications = $entity({\n name: \"verification\",\n schema: z.object({\n id: db.primaryKey(z.bigint()),\n\n createdAt: db.createdAt(),\n\n updatedAt: db.updatedAt(),\n\n version: db.version(),\n\n type: verificationTypeEnumSchema,\n\n target: z.text({\n description: \"Can be a phone (E.164 format) or email address\",\n }),\n\n purpose: db.default(\n z.text({\n description:\n \"Logical purpose bucket (e.g. 'default', 'password-reset'). Scopes the cooldown and daily-limit checks so unrelated flows that share the same (type, target) — most notably email verification and password reset — don't collide.\",\n }),\n \"default\",\n ),\n\n code: z.text({\n description: \"Hashed verification token (n-digit code or UUID)\",\n }),\n\n verifiedAt: z\n .datetime()\n .describe(\"When it was successfully verified\")\n .optional(),\n\n attempts: db.default(\n z\n .integer()\n .describe(\"Number of failed attempts (to prevent brute-force)\"),\n 0,\n ),\n }),\n indexes: [\n \"createdAt\",\n {\n columns: [\"target\", \"code\"],\n },\n ],\n});\n\nexport const verificationEntitySchema = verifications.schema;\nexport const verificationEntityInsertSchema = verifications.insertSchema;\nexport type VerificationEntity = Static<typeof verifications.schema>;\n","import type { Static } from \"alepha\";\nimport { z } from \"alepha\";\n\nexport const verificationSettingsSchema = z.object({\n code: z\n .object({\n maxAttempts: z\n .integer()\n .min(1)\n .max(10)\n .describe(\n \"Maximum number of attempts before locking the verification.\",\n ),\n codeLength: z\n .integer()\n .min(4)\n .max(12)\n .describe(\"Length of the verification code.\"),\n codeExpiration: z\n .integer()\n .min(60)\n .max(3600)\n .describe(\"Time in seconds before the verification code expires.\"),\n verificationCooldown: z\n .integer()\n .min(0)\n .max(3600)\n .describe(\"Cooldown period in seconds after a request verification.\"),\n limitPerDay: z\n .integer()\n .min(1)\n .max(100)\n .describe(\n \"Maximum number of verification requests per day for one entry.\",\n ),\n })\n .describe(\"Settings specific to code verifications.\"),\n link: z\n .object({\n maxAttempts: z\n .integer()\n .min(1)\n .max(10)\n .describe(\n \"Maximum number of attempts before locking the verification.\",\n ),\n codeExpiration: z\n .integer()\n .min(60)\n .max(7200)\n .describe(\"Time in seconds before the verification token expires.\"),\n verificationCooldown: z\n .integer()\n .min(0)\n .max(3600)\n .describe(\"Cooldown period in seconds after a request verification.\"),\n limitPerDay: z\n .integer()\n .min(1)\n .max(100)\n .describe(\n \"Maximum number of verification requests per day for one entry.\",\n ),\n })\n .describe(\"Settings specific to link verifications.\"),\n purgeDays: z\n .integer()\n .min(0)\n .max(365)\n .describe(\n \"Number of days after which expired verifications are automatically deleted. Set to 0 to disable auto-deletion.\",\n ),\n});\n\nexport type VerificationSettings = Static<typeof verificationSettingsSchema>;\n","import { $atom, $state, type Static } from \"alepha\";\nimport {\n type VerificationSettings,\n verificationSettingsSchema,\n} from \"../schemas/verificationSettingsSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Verification settings configuration atom\n */\nexport const verificationOptions = $atom({\n name: \"alepha.api.verifications.options\",\n schema: verificationSettingsSchema,\n default: {\n code: {\n maxAttempts: 5,\n codeLength: 6,\n codeExpiration: 300, // 5 minutes\n verificationCooldown: 90,\n limitPerDay: 10,\n },\n link: {\n maxAttempts: 3, // Lower since UUIDs are harder to guess\n codeExpiration: 1800, // 30 minutes\n verificationCooldown: 90,\n limitPerDay: 10,\n },\n purgeDays: 1,\n },\n});\n\nexport type VerificationOptions = Static<typeof verificationOptions.schema>;\n\ndeclare module \"alepha\" {\n interface State {\n [verificationOptions.key]: VerificationOptions;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class VerificationParameters {\n protected readonly options = $state(verificationOptions);\n\n public get<K extends keyof VerificationSettings>(\n key: K,\n ): VerificationSettings[K] {\n return this.options[key];\n }\n}\n","import { createHash, randomInt } from \"node:crypto\";\nimport { $inject } from \"alepha\";\nimport { CryptoProvider } from \"alepha/crypto\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport { BadRequestError, NotFoundError } from \"alepha/server\";\nimport {\n type VerificationEntity,\n verifications,\n} from \"../entities/verifications.ts\";\nimport { VerificationParameters } from \"../parameters/VerificationParameters.ts\";\nimport type { RequestVerificationResponse } from \"../schemas/requestVerificationCodeResponseSchema.ts\";\nimport type { ValidateVerificationCodeResponse } from \"../schemas/validateVerificationCodeResponseSchema.ts\";\nimport type { VerificationTypeEnum } from \"../schemas/verificationTypeEnumSchema.ts\";\n\nexport class VerificationService {\n protected readonly log = $logger();\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly crypto = $inject(CryptoProvider);\n protected readonly verificationParameters = $inject(VerificationParameters);\n protected readonly verificationRepository = $repository(verifications);\n\n public async findByEntry(\n entry: VerificationEntry,\n ): Promise<VerificationEntity> {\n this.log.trace(\"Finding verification by entry\", {\n type: entry.type,\n target: entry.target,\n });\n\n const results = await this.verificationRepository.findMany({\n limit: 1, // only need the most recent entry\n orderBy: {\n column: \"createdAt\",\n direction: \"desc\",\n },\n where: {\n type: { eq: entry.type },\n target: { eq: entry.target },\n purpose: { eq: entry.purpose ?? \"default\" },\n },\n });\n\n if (results.length === 0) {\n this.log.debug(\"Verification entry not found\", {\n type: entry.type,\n target: entry.target,\n });\n throw new NotFoundError(\"Verification entry not found\");\n }\n\n this.log.debug(\"Verification entry found\", {\n id: results[0].id,\n type: entry.type,\n target: entry.target,\n });\n\n return results[0];\n }\n\n public findRecentsByEntry(entry: VerificationEntry) {\n this.log.trace(\"Finding recent verifications by entry\", {\n type: entry.type,\n target: entry.target,\n });\n\n return this.verificationRepository.findMany({\n orderBy: {\n column: \"createdAt\",\n direction: \"desc\",\n },\n where: {\n type: { eq: entry.type },\n target: { eq: entry.target },\n purpose: { eq: entry.purpose ?? \"default\" },\n createdAt: {\n gte: this.dateTimeProvider.now().startOf(\"day\").toISOString(),\n },\n },\n });\n }\n\n /**\n * Creates a verification entry and returns the token.\n * The caller is responsible for sending notifications with the token.\n * This allows for context-specific notifications (e.g., password reset vs email verification).\n */\n public async createVerification(\n entry: VerificationEntry,\n ): Promise<RequestVerificationResponse> {\n this.log.trace(\"Creating verification\", {\n type: entry.type,\n target: entry.target,\n });\n\n const settings = this.verificationParameters.get(entry.type);\n\n const recents = await this.findRecentsByEntry(entry);\n if (recents.length >= settings.limitPerDay) {\n this.log.warn(\"Daily verification limit reached\", {\n type: entry.type,\n target: entry.target,\n limit: settings.limitPerDay,\n count: recents.length,\n });\n throw new BadRequestError(\n `Maximum number of verification requests per day reached (${settings.limitPerDay})`,\n );\n }\n\n const existingVerification = recents[0];\n if (existingVerification) {\n const nowSec = this.dateTimeProvider.now().unix();\n const createdAtSec = this.dateTimeProvider\n .of(existingVerification.createdAt)\n .unix();\n\n const diffSec = nowSec - createdAtSec;\n if (diffSec < settings.verificationCooldown) {\n const remainingCooldown = Math.floor(\n settings.verificationCooldown - diffSec,\n );\n this.log.debug(\"Verification on cooldown\", {\n type: entry.type,\n target: entry.target,\n remainingSeconds: remainingCooldown,\n });\n throw new BadRequestError(\n `Verification is on cooldown for ${remainingCooldown} seconds`,\n );\n }\n }\n\n const token = this.generateToken(entry.type);\n\n const verification = await this.verificationRepository.create({\n type: entry.type,\n target: entry.target,\n purpose: entry.purpose ?? \"default\",\n code: this.hashCode(token),\n createdAt: this.dateTimeProvider.nowISOString(),\n });\n\n this.log.info(\"Verification created\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n expiresInSeconds: settings.codeExpiration,\n });\n\n return {\n token,\n codeExpiration: settings.codeExpiration,\n verificationCooldown: settings.verificationCooldown,\n maxVerificationAttempts: settings.maxAttempts,\n };\n }\n\n public async verifyCode(\n entry: VerificationEntry,\n code: string,\n ): Promise<ValidateVerificationCodeResponse> {\n this.log.trace(\"Verifying code\", {\n type: entry.type,\n target: entry.target,\n });\n\n const settings = this.verificationParameters.get(entry.type);\n\n const verification = await this.findByEntry(entry);\n if (verification.verifiedAt) {\n // Already verified — but STILL require the submitted code to match the\n // record. Short-circuiting on `verifiedAt` alone means any code (or a\n // blank one) passes once the target has been verified, so any flow\n // re-using verifyCode as an authz gate would accept an attacker's guess.\n if (verification.code !== this.hashCode(code)) {\n this.log.warn(\"Invalid code submitted for already-verified entry\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n });\n throw new BadRequestError(\"Invalid verification code\");\n }\n this.log.debug(\"Verification already verified\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n verifiedAt: verification.verifiedAt,\n });\n return { ok: true, alreadyVerified: true };\n }\n\n // DO NOT DELETE THE VERIFICATION WHEN IT IS REJECTED,\n // or we won't be able to cooldown the verification\n\n const now = this.dateTimeProvider.now();\n const expirationDate = this.dateTimeProvider\n .of(verification.createdAt)\n .add(settings.codeExpiration, \"seconds\");\n\n if (now > expirationDate) {\n this.log.warn(\"Verification code expired\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n createdAt: verification.createdAt,\n expiredAt: expirationDate.toISOString(),\n });\n throw new BadRequestError(\"Verification code has expired\");\n }\n\n if (verification.attempts >= settings.maxAttempts) {\n this.log.warn(\"Verification locked due to max attempts\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n attempts: verification.attempts,\n maxAttempts: settings.maxAttempts,\n });\n throw new BadRequestError(\n \"Maximum number of attempts reached - verification is locked\",\n );\n }\n\n if (verification.code !== this.hashCode(code)) {\n const newAttempts = verification.attempts + 1;\n this.log.warn(\"Invalid verification code\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n attempts: newAttempts,\n maxAttempts: settings.maxAttempts,\n });\n await this.verificationRepository.updateById(verification.id, {\n attempts: newAttempts,\n });\n throw new BadRequestError(\"Invalid verification code\");\n }\n\n await this.verificationRepository.updateById(verification.id, {\n verifiedAt: this.dateTimeProvider.nowISOString(),\n });\n\n this.log.info(\"Verification code verified\", {\n id: verification.id,\n type: entry.type,\n target: entry.target,\n });\n\n return { ok: true };\n }\n\n public hashCode(code: string): string {\n return createHash(\"sha256\").update(code).digest(\"hex\");\n }\n\n public generateToken(type: VerificationTypeEnum): string {\n if (type === \"code\") {\n const settings = this.verificationParameters.get(\"code\");\n return randomInt(0, 1_000_000)\n .toString()\n .padStart(settings.codeLength, \"0\");\n } else if (type === \"link\") {\n return this.crypto.randomUUID();\n }\n\n throw new BadRequestError(`Invalid verification type: ${type}`);\n }\n}\n\nexport interface VerificationEntry {\n type: VerificationTypeEnum;\n target: string;\n\n /**\n * Logical purpose bucket. Cooldown and daily-limit checks are scoped to\n * `(type, target, purpose)`, so flows that share a `(type, target)` pair\n * — e.g. email verification and password reset, both `type: \"code\"` on the\n * same email — get independent rate-limit windows instead of colliding.\n *\n * Defaults to `\"default\"` when omitted (back-compatible with callers and\n * rows that predate this field).\n */\n purpose?: string;\n}\n","import { $inject, z } from \"alepha\";\nimport { $action } from \"alepha/server\";\nimport { validateVerificationCodeResponseSchema } from \"../schemas/validateVerificationCodeResponseSchema.ts\";\nimport { verificationTypeEnumSchema } from \"../schemas/verificationTypeEnumSchema.ts\";\nimport { VerificationService } from \"../services/VerificationService.ts\";\n\nexport class VerificationController {\n protected readonly verificationService = $inject(VerificationService);\n\n public readonly url = \"/verifications\";\n public readonly group = \"verifications\";\n\n // SECURITY: there is deliberately NO public \"request a code\" action here.\n // `VerificationService.createVerification` returns the raw token so that the\n // *caller* can deliver it out-of-band (email/SMS). Exposing that over HTTP —\n // as a previous `requestVerificationCode` action did, with no `$secure` — let\n // anyone request a code for any target and read it straight from the response,\n // defeating verification entirely. Verification requests are driven\n // server-side (RegistrationService / UserService call the service directly and\n // send the code); only code *submission* is public, below.\n public readonly validateVerificationCode = $action({\n path: `${this.url}/:type/validate`,\n group: this.group,\n method: \"POST\",\n schema: {\n params: z.object({\n type: verificationTypeEnumSchema,\n }),\n body: z.object({\n target: z.text(),\n token: z.text({\n description:\n \"The verification token (6-digit code for phone, UUID for email).\",\n }),\n }),\n response: validateVerificationCodeResponseSchema,\n },\n handler: async ({ body, params }) => {\n return this.verificationService.verifyCode(\n {\n type: params.type,\n target: body.target,\n },\n body.token,\n );\n },\n });\n}\n","import { $inject } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $repository } from \"alepha/orm\";\nimport { $scheduler } from \"alepha/scheduler\";\nimport { verifications } from \"../entities/verifications.ts\";\nimport { VerificationParameters } from \"../parameters/VerificationParameters.ts\";\n\nexport class VerificationJobs {\n protected readonly verificationRepository = $repository(verifications);\n protected readonly verificationParameters = $inject(VerificationParameters);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n public readonly cleanExpired = $scheduler({\n name: \"api:verifications:cleanExpired\",\n cron: \"0 * * * *\", // Hourly at minute 0\n description: \"Clean expired verifications\",\n handler: async () => {\n const purgeDays = this.verificationParameters.get(\"purgeDays\");\n if (purgeDays <= 0) {\n return; // Auto deletion is disabled\n }\n\n const dayMs = 24 * 60 * 60 * 1000;\n const purgeThreshold =\n this.dateTimeProvider.nowMillis() - purgeDays * dayMs;\n\n await this.verificationRepository.deleteMany({\n createdAt: {\n lt: this.dateTimeProvider.of(purgeThreshold).toISOString(),\n },\n });\n },\n });\n}\n","import type { Static } from \"alepha\";\nimport { z } from \"alepha\";\n\nexport const requestVerificationCodeResponseSchema = z.object({\n token: z\n .string()\n .describe(\n \"The verification token (6-digit code for phone, UUID for email). The caller should send this to the user via their preferred notification method.\",\n ),\n codeExpiration: z\n .integer()\n .describe(\"Time in seconds before your verification token expires.\"),\n verificationCooldown: z\n .integer()\n .describe(\n \"Cooldown period in seconds before you can request another verification.\",\n ),\n maxVerificationAttempts: z\n .integer()\n .describe(\n \"Maximum number of verification attempts allowed before the token is locked.\",\n ),\n});\n\nexport type RequestVerificationResponse = Static<\n typeof requestVerificationCodeResponseSchema\n>;\n","import { $module } from \"alepha\";\nimport { VerificationController } from \"./controllers/VerificationController.ts\";\nimport { VerificationJobs } from \"./jobs/VerificationJobs.ts\";\nimport { VerificationParameters } from \"./parameters/VerificationParameters.ts\";\nimport { VerificationService } from \"./services/VerificationService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/VerificationController.ts\";\nexport * from \"./entities/verifications.ts\";\nexport * from \"./jobs/VerificationJobs.ts\";\nexport * from \"./parameters/VerificationParameters.ts\";\nexport * from \"./schemas/requestVerificationCodeResponseSchema.ts\";\nexport * from \"./schemas/validateVerificationCodeResponseSchema.ts\";\nexport * from \"./schemas/verificationTypeEnumSchema.ts\";\nexport * from \"./services/VerificationService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Email and phone verification workflows.\n *\n * **Features:**\n * - Verification token generation\n * - Verification code sending\n * - Verification completion tracking\n * - Resend functionality\n *\n * @module alepha.api.verifications\n */\nexport const AlephaApiVerification = $module({\n name: \"alepha.api.verifications\",\n services: [\n VerificationController,\n VerificationJobs,\n VerificationService,\n VerificationParameters,\n ],\n});\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/background/providers/BackgroundTaskProvider.ts","../../src/background/providers/WorkerdBackgroundTaskProvider.ts","../../src/background/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/background/providers/BackgroundTaskProvider.ts","../../src/background/providers/WorkerdBackgroundTaskProvider.ts","../../src/background/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;cAmBa;qBACQ,QAAM;qBACN,6BAAG;;qBAGH,SAAO,IAAA;;;;;;;EAQnB,MAAM,sBAAsB;;;;;;YAuBzB,UAAU,UAAU;;;;;EAMjB,SAAS;qBAIH,yBAAM;;;;;;;;;;;;;;;;;;;;;cC9Cd,sCAAsC;YAC9B,UAAU,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;cCa3B,mCAAgB,yBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/background/providers/BackgroundTaskProvider.ts","../../src/background/providers/WorkerdBackgroundTaskProvider.ts","../../src/background/index.ts"],"sourcesContent":["import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\n\n/**\n * Runs fire-and-forget work that should outlive the request that scheduled it\n * (sending a welcome email, an audit write, a webhook) without blocking the\n * response.\n *\n * On a long-lived runtime (Node, Vercel) the event loop keeps the promise\n * alive, so the only job here is to detach the task from the caller and never\n * leak an unhandled rejection. On serverless/edge runtimes that freeze the\n * isolate once the response is returned (Cloudflare Workers) the\n * {@link WorkerdBackgroundTaskProvider} variant additionally wraps the task in\n * `executionCtx.waitUntil` — call sites stay platform-agnostic and only ever\n * call {@link defer}.\n *\n * In-flight tasks are tracked and awaited on shutdown (`flush`), so graceful\n * stop, `run({ once })`, and unit tests don't silently drop work.\n */\nexport class BackgroundTaskProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n\n /** In-flight deferred tasks, awaited on stop. */\n protected readonly pending = new Set<Promise<void>>();\n\n /**\n * Schedule `task` to run in the background. Returns immediately — the task is\n * detached onto a microtask, so the caller (e.g. an HTTP handler) is never\n * blocked and a synchronous throw inside `task` can't escape into it. Errors\n * are caught and logged.\n */\n public defer(task: () => unknown | Promise<unknown>): void {\n const promise = Promise.resolve()\n .then(task)\n .then(\n () => undefined,\n (error: unknown) => {\n this.log.warn(\"Background task failed\", error as Error);\n },\n );\n\n this.pending.add(promise);\n void promise.finally(() => {\n this.pending.delete(promise);\n });\n\n this.keepAlive(promise);\n }\n\n /**\n * Hook for platform variants to keep the runtime alive until `promise`\n * settles. No-op on long-lived runtimes (the event loop already does). The\n * Cloudflare variant overrides this with `executionCtx.waitUntil`.\n */\n protected keepAlive(_promise: Promise<void>): void {}\n\n /**\n * Await all in-flight tasks (best-effort). Called on `stop` so shutdown and\n * tests don't drop deferred work.\n */\n public async flush(): Promise<void> {\n await Promise.allSettled([...this.pending]);\n }\n\n protected readonly onStop = $hook({\n on: \"stop\",\n handler: () => this.flush(),\n });\n}\n","import { BackgroundTaskProvider } from \"./BackgroundTaskProvider.ts\";\n\n/**\n * Cloudflare Workers variant of {@link BackgroundTaskProvider}.\n *\n * Cloudflare freezes the isolate once the response is returned, so a plain\n * fire-and-forget promise would be killed mid-flight. The platform exposes a\n * per-request `executionCtx.waitUntil(promise)` that keeps the isolate alive\n * until `promise` settles; the request entry point (generated by the Cloudflare\n * build) stashes it in the Alepha store under `cloudflare.waitUntil`.\n *\n * This is the ONE place that reads that key — call sites use\n * {@link BackgroundTaskProvider.defer} and stay platform-agnostic.\n *\n * `waitUntil` is request-scoped, so `defer()` must be called within the\n * request's async context (which is where background work is scheduled). Outside\n * a request (e.g. a cron tick) the key is absent and we fall back to the base\n * fire-and-track behaviour.\n */\nexport class WorkerdBackgroundTaskProvider extends BackgroundTaskProvider {\n protected override keepAlive(promise: Promise<void>): void {\n const waitUntil = this.alepha.store.get(\"cloudflare.waitUntil\") as\n | ((p: Promise<unknown>) => void)\n | undefined;\n\n if (typeof waitUntil !== \"function\") {\n // No request-scoped execution context (cron / outside a request). The\n // base tracking + a long-lived isolate keep the promise alive.\n return;\n }\n\n try {\n waitUntil(promise);\n } catch (error) {\n // The runtime rejects waitUntil if called outside a request scope; the\n // promise still runs, just without the isolate-alive guarantee.\n this.log.debug(\n \"waitUntil rejected — falling back to fire-and-track\",\n error as Error,\n );\n }\n }\n}\n","import { $module } from \"alepha\";\nimport { BackgroundTaskProvider } from \"./providers/BackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BackgroundTaskProvider.ts\";\nexport * from \"./providers/WorkerdBackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Fire-and-forget background work that should outlive the request that\n * scheduled it, without blocking the response.\n *\n * Inject {@link BackgroundTaskProvider} and call `defer(() => …)`:\n *\n * ```ts\n * protected readonly background = $inject(BackgroundTaskProvider);\n *\n * createUser = $action({ handler: async ({ body }) => {\n * const user = await this.users.create(body);\n * this.background.defer(() => this.email.send(welcome(user))); // don't block\n * return user;\n * }});\n * ```\n *\n * On Node/Vercel the event loop keeps the task alive. On Cloudflare Workers the\n * `workerd` build swaps in {@link WorkerdBackgroundTaskProvider}, which wraps\n * the task in `executionCtx.waitUntil` so the isolate isn't frozen at response\n * time — the call site is identical either way.\n *\n * @module alepha.background\n */\nexport const AlephaBackground = $module({\n name: \"alepha.background\",\n services: [BackgroundTaskProvider],\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,IAAa,yBAAb,MAAoC;CAClC,SAA4B,QAAQ,MAAM;CAC1C,MAAyB,QAAQ;;CAGjC,0BAA6B,IAAI,IAAmB;;;;;;;CAQpD,MAAa,MAA8C;EACzD,MAAM,UAAU,QAAQ,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/background/providers/BackgroundTaskProvider.ts","../../src/background/providers/WorkerdBackgroundTaskProvider.ts","../../src/background/index.ts"],"sourcesContent":["import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\n\n/**\n * Runs fire-and-forget work that should outlive the request that scheduled it\n * (sending a welcome email, an audit write, a webhook) without blocking the\n * response.\n *\n * On a long-lived runtime (Node, Vercel) the event loop keeps the promise\n * alive, so the only job here is to detach the task from the caller and never\n * leak an unhandled rejection. On serverless/edge runtimes that freeze the\n * isolate once the response is returned (Cloudflare Workers) the\n * {@link WorkerdBackgroundTaskProvider} variant additionally wraps the task in\n * `executionCtx.waitUntil` — call sites stay platform-agnostic and only ever\n * call {@link defer}.\n *\n * In-flight tasks are tracked and awaited on shutdown (`flush`), so graceful\n * stop, `run({ once })`, and unit tests don't silently drop work.\n */\nexport class BackgroundTaskProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n\n /** In-flight deferred tasks, awaited on stop. */\n protected readonly pending = new Set<Promise<void>>();\n\n /**\n * Schedule `task` to run in the background. Returns immediately — the task is\n * detached onto a microtask, so the caller (e.g. an HTTP handler) is never\n * blocked and a synchronous throw inside `task` can't escape into it. Errors\n * are caught and logged.\n */\n public defer(task: () => unknown | Promise<unknown>): void {\n const promise = Promise.resolve()\n .then(task)\n .then(\n () => undefined,\n (error: unknown) => {\n this.log.warn(\"Background task failed\", error as Error);\n },\n );\n\n this.pending.add(promise);\n void promise.finally(() => {\n this.pending.delete(promise);\n });\n\n this.keepAlive(promise);\n }\n\n /**\n * Hook for platform variants to keep the runtime alive until `promise`\n * settles. No-op on long-lived runtimes (the event loop already does). The\n * Cloudflare variant overrides this with `executionCtx.waitUntil`.\n */\n protected keepAlive(_promise: Promise<void>): void {}\n\n /**\n * Await all in-flight tasks (best-effort). Called on `stop` so shutdown and\n * tests don't drop deferred work.\n */\n public async flush(): Promise<void> {\n await Promise.allSettled([...this.pending]);\n }\n\n protected readonly onStop = $hook({\n on: \"stop\",\n handler: () => this.flush(),\n });\n}\n","import { BackgroundTaskProvider } from \"./BackgroundTaskProvider.ts\";\n\n/**\n * Cloudflare Workers variant of {@link BackgroundTaskProvider}.\n *\n * Cloudflare freezes the isolate once the response is returned, so a plain\n * fire-and-forget promise would be killed mid-flight. The platform exposes a\n * per-request `executionCtx.waitUntil(promise)` that keeps the isolate alive\n * until `promise` settles; the request entry point (generated by the Cloudflare\n * build) stashes it in the Alepha store under `cloudflare.waitUntil`.\n *\n * This is the ONE place that reads that key — call sites use\n * {@link BackgroundTaskProvider.defer} and stay platform-agnostic.\n *\n * `waitUntil` is request-scoped, so `defer()` must be called within the\n * request's async context (which is where background work is scheduled). Outside\n * a request (e.g. a cron tick) the key is absent and we fall back to the base\n * fire-and-track behaviour.\n */\nexport class WorkerdBackgroundTaskProvider extends BackgroundTaskProvider {\n protected override keepAlive(promise: Promise<void>): void {\n const waitUntil = this.alepha.store.get(\"cloudflare.waitUntil\") as\n | ((p: Promise<unknown>) => void)\n | undefined;\n\n if (typeof waitUntil !== \"function\") {\n // No request-scoped execution context (cron / outside a request). The\n // base tracking + a long-lived isolate keep the promise alive.\n return;\n }\n\n try {\n waitUntil(promise);\n } catch (error) {\n // The runtime rejects waitUntil if called outside a request scope; the\n // promise still runs, just without the isolate-alive guarantee.\n this.log.debug(\n \"waitUntil rejected — falling back to fire-and-track\",\n error as Error,\n );\n }\n }\n}\n","import { $module } from \"alepha\";\nimport { BackgroundTaskProvider } from \"./providers/BackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BackgroundTaskProvider.ts\";\nexport * from \"./providers/WorkerdBackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Fire-and-forget background work that should outlive the request that\n * scheduled it, without blocking the response.\n *\n * Inject {@link BackgroundTaskProvider} and call `defer(() => …)`:\n *\n * ```ts\n * protected readonly background = $inject(BackgroundTaskProvider);\n *\n * createUser = $action({ handler: async ({ body }) => {\n * const user = await this.users.create(body);\n * this.background.defer(() => this.email.send(welcome(user))); // don't block\n * return user;\n * }});\n * ```\n *\n * On Node/Vercel the event loop keeps the task alive. On Cloudflare Workers the\n * `workerd` build swaps in {@link WorkerdBackgroundTaskProvider}, which wraps\n * the task in `executionCtx.waitUntil` so the isolate isn't frozen at response\n * time — the call site is identical either way.\n *\n * @module alepha.background\n */\nexport const AlephaBackground = $module({\n name: \"alepha.background\",\n services: [BackgroundTaskProvider],\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,IAAa,yBAAb,MAAoC;CAClC,SAA4B,QAAQ,MAAM;CAC1C,MAAyB,QAAQ;;CAGjC,0BAA6B,IAAI,IAAmB;;;;;;;CAQpD,MAAa,MAA8C;EACzD,MAAM,UAAU,QAAQ,QAAQ,CAAC,CAC9B,KAAK,IAAI,CAAC,CACV,WACO,KAAA,IACL,UAAmB;GAClB,KAAK,IAAI,KAAK,0BAA0B,KAAc;EACxD,CACF;EAEF,KAAK,QAAQ,IAAI,OAAO;EACxB,QAAa,cAAc;GACzB,KAAK,QAAQ,OAAO,OAAO;EAC7B,CAAC;EAED,KAAK,UAAU,OAAO;CACxB;;;;;;CAOA,UAAoB,UAA+B,CAAC;;;;;CAMpD,MAAa,QAAuB;EAClC,MAAM,QAAQ,WAAW,CAAC,GAAG,KAAK,OAAO,CAAC;CAC5C;CAEA,SAA4B,MAAM;EAChC,IAAI;EACJ,eAAe,KAAK,MAAM;CAC5B,CAAC;AACH;;;;;;;;;;;;;;;;;;;;AClDA,IAAa,gCAAb,cAAmD,uBAAuB;CACxE,UAA6B,SAA8B;EACzD,MAAM,YAAY,KAAK,OAAO,MAAM,IAAI,sBAAsB;EAI9D,IAAI,OAAO,cAAc,YAGvB;EAGF,IAAI;GACF,UAAU,OAAO;EACnB,SAAS,OAAO;GAGd,KAAK,IAAI,MACP,uDACA,KACF;EACF;CACF;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;ACTA,MAAa,mBAAmB,QAAQ;CACtC,MAAM;CACN,UAAU,CAAC,sBAAsB;AACnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.workerd.js","names":[],"sources":["../../src/background/providers/BackgroundTaskProvider.ts","../../src/background/providers/WorkerdBackgroundTaskProvider.ts","../../src/background/index.workerd.ts"],"sourcesContent":["import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\n\n/**\n * Runs fire-and-forget work that should outlive the request that scheduled it\n * (sending a welcome email, an audit write, a webhook) without blocking the\n * response.\n *\n * On a long-lived runtime (Node, Vercel) the event loop keeps the promise\n * alive, so the only job here is to detach the task from the caller and never\n * leak an unhandled rejection. On serverless/edge runtimes that freeze the\n * isolate once the response is returned (Cloudflare Workers) the\n * {@link WorkerdBackgroundTaskProvider} variant additionally wraps the task in\n * `executionCtx.waitUntil` — call sites stay platform-agnostic and only ever\n * call {@link defer}.\n *\n * In-flight tasks are tracked and awaited on shutdown (`flush`), so graceful\n * stop, `run({ once })`, and unit tests don't silently drop work.\n */\nexport class BackgroundTaskProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n\n /** In-flight deferred tasks, awaited on stop. */\n protected readonly pending = new Set<Promise<void>>();\n\n /**\n * Schedule `task` to run in the background. Returns immediately — the task is\n * detached onto a microtask, so the caller (e.g. an HTTP handler) is never\n * blocked and a synchronous throw inside `task` can't escape into it. Errors\n * are caught and logged.\n */\n public defer(task: () => unknown | Promise<unknown>): void {\n const promise = Promise.resolve()\n .then(task)\n .then(\n () => undefined,\n (error: unknown) => {\n this.log.warn(\"Background task failed\", error as Error);\n },\n );\n\n this.pending.add(promise);\n void promise.finally(() => {\n this.pending.delete(promise);\n });\n\n this.keepAlive(promise);\n }\n\n /**\n * Hook for platform variants to keep the runtime alive until `promise`\n * settles. No-op on long-lived runtimes (the event loop already does). The\n * Cloudflare variant overrides this with `executionCtx.waitUntil`.\n */\n protected keepAlive(_promise: Promise<void>): void {}\n\n /**\n * Await all in-flight tasks (best-effort). Called on `stop` so shutdown and\n * tests don't drop deferred work.\n */\n public async flush(): Promise<void> {\n await Promise.allSettled([...this.pending]);\n }\n\n protected readonly onStop = $hook({\n on: \"stop\",\n handler: () => this.flush(),\n });\n}\n","import { BackgroundTaskProvider } from \"./BackgroundTaskProvider.ts\";\n\n/**\n * Cloudflare Workers variant of {@link BackgroundTaskProvider}.\n *\n * Cloudflare freezes the isolate once the response is returned, so a plain\n * fire-and-forget promise would be killed mid-flight. The platform exposes a\n * per-request `executionCtx.waitUntil(promise)` that keeps the isolate alive\n * until `promise` settles; the request entry point (generated by the Cloudflare\n * build) stashes it in the Alepha store under `cloudflare.waitUntil`.\n *\n * This is the ONE place that reads that key — call sites use\n * {@link BackgroundTaskProvider.defer} and stay platform-agnostic.\n *\n * `waitUntil` is request-scoped, so `defer()` must be called within the\n * request's async context (which is where background work is scheduled). Outside\n * a request (e.g. a cron tick) the key is absent and we fall back to the base\n * fire-and-track behaviour.\n */\nexport class WorkerdBackgroundTaskProvider extends BackgroundTaskProvider {\n protected override keepAlive(promise: Promise<void>): void {\n const waitUntil = this.alepha.store.get(\"cloudflare.waitUntil\") as\n | ((p: Promise<unknown>) => void)\n | undefined;\n\n if (typeof waitUntil !== \"function\") {\n // No request-scoped execution context (cron / outside a request). The\n // base tracking + a long-lived isolate keep the promise alive.\n return;\n }\n\n try {\n waitUntil(promise);\n } catch (error) {\n // The runtime rejects waitUntil if called outside a request scope; the\n // promise still runs, just without the isolate-alive guarantee.\n this.log.debug(\n \"waitUntil rejected — falling back to fire-and-track\",\n error as Error,\n );\n }\n }\n}\n","import { $module } from \"alepha\";\nimport { BackgroundTaskProvider } from \"./providers/BackgroundTaskProvider.ts\";\nimport { WorkerdBackgroundTaskProvider } from \"./providers/WorkerdBackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BackgroundTaskProvider.ts\";\nexport * from \"./providers/WorkerdBackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Cloudflare Workers build of {@link AlephaBackground}: swaps\n * {@link BackgroundTaskProvider} for {@link WorkerdBackgroundTaskProvider},\n * which keeps the isolate alive past the response via `executionCtx.waitUntil`.\n *\n * @module alepha.background\n */\nexport const AlephaBackground = $module({\n name: \"alepha.background\",\n services: [BackgroundTaskProvider],\n variants: [WorkerdBackgroundTaskProvider],\n register: (alepha) =>\n alepha.with({\n provide: BackgroundTaskProvider,\n use: WorkerdBackgroundTaskProvider,\n }),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,IAAa,yBAAb,MAAoC;CAClC,SAA4B,QAAQ,MAAM;CAC1C,MAAyB,QAAQ;;CAGjC,0BAA6B,IAAI,IAAmB;;;;;;;CAQpD,MAAa,MAA8C;EACzD,MAAM,UAAU,QAAQ,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.workerd.js","names":[],"sources":["../../src/background/providers/BackgroundTaskProvider.ts","../../src/background/providers/WorkerdBackgroundTaskProvider.ts","../../src/background/index.workerd.ts"],"sourcesContent":["import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\n\n/**\n * Runs fire-and-forget work that should outlive the request that scheduled it\n * (sending a welcome email, an audit write, a webhook) without blocking the\n * response.\n *\n * On a long-lived runtime (Node, Vercel) the event loop keeps the promise\n * alive, so the only job here is to detach the task from the caller and never\n * leak an unhandled rejection. On serverless/edge runtimes that freeze the\n * isolate once the response is returned (Cloudflare Workers) the\n * {@link WorkerdBackgroundTaskProvider} variant additionally wraps the task in\n * `executionCtx.waitUntil` — call sites stay platform-agnostic and only ever\n * call {@link defer}.\n *\n * In-flight tasks are tracked and awaited on shutdown (`flush`), so graceful\n * stop, `run({ once })`, and unit tests don't silently drop work.\n */\nexport class BackgroundTaskProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n\n /** In-flight deferred tasks, awaited on stop. */\n protected readonly pending = new Set<Promise<void>>();\n\n /**\n * Schedule `task` to run in the background. Returns immediately — the task is\n * detached onto a microtask, so the caller (e.g. an HTTP handler) is never\n * blocked and a synchronous throw inside `task` can't escape into it. Errors\n * are caught and logged.\n */\n public defer(task: () => unknown | Promise<unknown>): void {\n const promise = Promise.resolve()\n .then(task)\n .then(\n () => undefined,\n (error: unknown) => {\n this.log.warn(\"Background task failed\", error as Error);\n },\n );\n\n this.pending.add(promise);\n void promise.finally(() => {\n this.pending.delete(promise);\n });\n\n this.keepAlive(promise);\n }\n\n /**\n * Hook for platform variants to keep the runtime alive until `promise`\n * settles. No-op on long-lived runtimes (the event loop already does). The\n * Cloudflare variant overrides this with `executionCtx.waitUntil`.\n */\n protected keepAlive(_promise: Promise<void>): void {}\n\n /**\n * Await all in-flight tasks (best-effort). Called on `stop` so shutdown and\n * tests don't drop deferred work.\n */\n public async flush(): Promise<void> {\n await Promise.allSettled([...this.pending]);\n }\n\n protected readonly onStop = $hook({\n on: \"stop\",\n handler: () => this.flush(),\n });\n}\n","import { BackgroundTaskProvider } from \"./BackgroundTaskProvider.ts\";\n\n/**\n * Cloudflare Workers variant of {@link BackgroundTaskProvider}.\n *\n * Cloudflare freezes the isolate once the response is returned, so a plain\n * fire-and-forget promise would be killed mid-flight. The platform exposes a\n * per-request `executionCtx.waitUntil(promise)` that keeps the isolate alive\n * until `promise` settles; the request entry point (generated by the Cloudflare\n * build) stashes it in the Alepha store under `cloudflare.waitUntil`.\n *\n * This is the ONE place that reads that key — call sites use\n * {@link BackgroundTaskProvider.defer} and stay platform-agnostic.\n *\n * `waitUntil` is request-scoped, so `defer()` must be called within the\n * request's async context (which is where background work is scheduled). Outside\n * a request (e.g. a cron tick) the key is absent and we fall back to the base\n * fire-and-track behaviour.\n */\nexport class WorkerdBackgroundTaskProvider extends BackgroundTaskProvider {\n protected override keepAlive(promise: Promise<void>): void {\n const waitUntil = this.alepha.store.get(\"cloudflare.waitUntil\") as\n | ((p: Promise<unknown>) => void)\n | undefined;\n\n if (typeof waitUntil !== \"function\") {\n // No request-scoped execution context (cron / outside a request). The\n // base tracking + a long-lived isolate keep the promise alive.\n return;\n }\n\n try {\n waitUntil(promise);\n } catch (error) {\n // The runtime rejects waitUntil if called outside a request scope; the\n // promise still runs, just without the isolate-alive guarantee.\n this.log.debug(\n \"waitUntil rejected — falling back to fire-and-track\",\n error as Error,\n );\n }\n }\n}\n","import { $module } from \"alepha\";\nimport { BackgroundTaskProvider } from \"./providers/BackgroundTaskProvider.ts\";\nimport { WorkerdBackgroundTaskProvider } from \"./providers/WorkerdBackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BackgroundTaskProvider.ts\";\nexport * from \"./providers/WorkerdBackgroundTaskProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Cloudflare Workers build of {@link AlephaBackground}: swaps\n * {@link BackgroundTaskProvider} for {@link WorkerdBackgroundTaskProvider},\n * which keeps the isolate alive past the response via `executionCtx.waitUntil`.\n *\n * @module alepha.background\n */\nexport const AlephaBackground = $module({\n name: \"alepha.background\",\n services: [BackgroundTaskProvider],\n variants: [WorkerdBackgroundTaskProvider],\n register: (alepha) =>\n alepha.with({\n provide: BackgroundTaskProvider,\n use: WorkerdBackgroundTaskProvider,\n }),\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,IAAa,yBAAb,MAAoC;CAClC,SAA4B,QAAQ,MAAM;CAC1C,MAAyB,QAAQ;;CAGjC,0BAA6B,IAAI,IAAmB;;;;;;;CAQpD,MAAa,MAA8C;EACzD,MAAM,UAAU,QAAQ,QAAQ,CAAC,CAC9B,KAAK,IAAI,CAAC,CACV,WACO,KAAA,IACL,UAAmB;GAClB,KAAK,IAAI,KAAK,0BAA0B,KAAc;EACxD,CACF;EAEF,KAAK,QAAQ,IAAI,OAAO;EACxB,QAAa,cAAc;GACzB,KAAK,QAAQ,OAAO,OAAO;EAC7B,CAAC;EAED,KAAK,UAAU,OAAO;CACxB;;;;;;CAOA,UAAoB,UAA+B,CAAC;;;;;CAMpD,MAAa,QAAuB;EAClC,MAAM,QAAQ,WAAW,CAAC,GAAG,KAAK,OAAO,CAAC;CAC5C;CAEA,SAA4B,MAAM;EAChC,IAAI;EACJ,eAAe,KAAK,MAAM;CAC5B,CAAC;AACH;;;;;;;;;;;;;;;;;;;;AClDA,IAAa,gCAAb,cAAmD,uBAAuB;CACxE,UAA6B,SAA8B;EACzD,MAAM,YAAY,KAAK,OAAO,MAAM,IAAI,sBAAsB;EAI9D,IAAI,OAAO,cAAc,YAGvB;EAGF,IAAI;GACF,UAAU,OAAO;EACnB,SAAS,OAAO;GAGd,KAAK,IAAI,MACP,uDACA,KACF;EACF;CACF;AACF;;;;;;;;;;ACxBA,MAAa,mBAAmB,QAAQ;CACtC,MAAM;CACN,UAAU,CAAC,sBAAsB;CACjC,UAAU,CAAC,6BAA6B;CACxC,WAAW,WACT,OAAO,KAAK;EACV,SAAS;EACT,KAAK;CACP,CAAC;AACL,CAAC"}
|
package/dist/batch/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { Alepha, KIND, Primitive, Static, TSchema } from "alepha";
|
|
|
2
2
|
import { CryptoProvider } from "alepha/crypto";
|
|
3
3
|
import { DateTimeProvider, DurationLike } from "alepha/datetime";
|
|
4
4
|
import { RetryBackoffOptions, RetryPrimitiveOptions, RetryProvider } from "alepha/retry";
|
|
5
|
-
|
|
6
5
|
//#region ../../src/batch/providers/BatchProvider.d.ts
|
|
7
6
|
interface BatchOptions<TItem, TResponse = any> {
|
|
8
7
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/batch/providers/BatchProvider.ts","../../src/batch/primitives/$batch.ts","../../src/batch/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/batch/providers/BatchProvider.ts","../../src/batch/primitives/$batch.ts","../../src/batch/index.ts"],"mappings":";;;;;UAQiB,aAAa,OAAO;;;;EAInC,UAAU,OAAO,YAAY;;;;;;EAO7B;;;;;EAMA;;;;;;EAOA,cAAc;;;;EAKd,eAAe,MAAM;;;;;;EAOrB;;;;EAKA;;;;;;IAME;;;;;;;IAQA,mBAAmB;;;;;;IAOnB,cAAc;;;;;;IAOd,QAAQ,OAAO;;;;;IAMf,WAAW,OAAO,OAAO;;;KAMjB;UAEK,eAAe,OAAO;EACrC;EACA,MAAM;EACN;EACA,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,UAAU,QAAQ;EAClB,WAAW,OAAO;EAClB,UAAU,OAAO;;UAGF;EACf;EACA;IAAY;;EACZ;;;;;UAMe,aAAa,OAAO;EACnC,SAAS,aAAa,OAAO;EAC7B,YAAY,YAAY,eAAe,OAAO;EAC9C,YAAY,YAAY;EACxB,gBAAgB;EAChB;EACA;EACA,QAAQ;;;;;;cASG;qBACQ,6BAAG;qBACH,UAAQ;qBACR,eAAa;qBACb,QAAM;;;;qBAKN,UAAQ,IAAA;;;;EAK3B,cAAc,OAAO,WACnB,QAAQ,QACR,SAAS,aAAa,OAAO,aAC5B,aAAa,OAAO;;;;qBAiBJ,yBAAM;;;;YAoBf,WAAW,OAAO,WAC1B,SAAS,aAAa,OAAO;;;;YAQrB,eAAe,OAAO,WAC9B,SAAS,aAAa,OAAO;;;;YAQrB,eAAe,OAAO,WAC9B,SAAS,aAAa,OAAO,aAC5B;;;;;;;;EAWH,KAAK,OAAO,WACV,SAAS,aAAa,OAAO,YAC7B,MAAM;;;;;;;EAqGF,KAAK,OAAO,WAChB,SAAS,aAAa,OAAO,YAC7B,aACC,QAAQ;;;;;;EA8BX,OAAO,OAAO,WACZ,SAAS,aAAa,OAAO,YAC7B;IAEI;;IACA;IAAqB,QAAQ;;IAC7B;IAAkB,OAAO;;;;;;;;;;EAwB/B,eAAe,OAAO,WACpB,SAAS,aAAa,OAAO,YAC7B;;;;EAoBI,MAAM,OAAO,WACjB,SAAS,aAAa,OAAO,YAC7B,wBACC;;;;YAiBa,eAAe,OAAO,WACpC,SAAS,aAAa,OAAO,YAC7B,sBACA,iBACC;;;;;EAqHG,UAAU,OAAO,WACrB,SAAS,aAAa,OAAO,aAC5B;;;;EAWG,SAAS,OAAO,WACpB,SAAS,aAAa,OAAO,aAC5B;;;;;;YAYa,gBAAgB,OAAO,WACrC,SAAS,aAAa,OAAO,aAC5B;;;;;;;cCtiBQ;GAAU,cAAc,SAAS,WAAS,SAC5C,sBAAsB,OAAO,aACrC,eAAe,OAAO;;;UAKR,sBAAsB,cAAc,SAAS;;;;EAI5D,QAAQ;;;;EAKR,UAAU,OAAO,OAAO,aAAa;;;;EAKrC;;;;;EAMA;;;;EAKA,cAAc;;;;EAKd,eAAe,MAAM,OAAO;;;;EAK5B;;;;EAKA,QAAQ,KAAK,4BAA4B,MAAM,OAAO;;cAS3C,eACX,cAAc,SACd,yBACQ,UAAU,sBAAsB,OAAO;qBAC5B,eAAa;qBACb,SAAS,aAAa,OAAO,QAAQ;EAExD,eACK,MAAM,6BACA,UAAU,sBAAsB,OAAO;;;;;;EAoBrC,KAAK,MAAM,OAAO,SAAS;;;;;;;EAY3B,KAAK,aAAa,QAAQ;;;;;;EAShC,OACL;IAEI;;IACA;IAAqB,QAAQ;;IAC7B;IAAkB,OAAO;;;;;EAQlB,MAAM,wBAAwB;;;;;;;;EAWpC,eAAe;qBAIH,0BAAO;;;;;;;;;;;;;;;cCrIf,8BAAW,yBAAA"}
|