alepha 0.21.2 → 0.22.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/README.md +0 -1
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.d.ts +393 -403
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +25 -56
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.browser.js +31 -1
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +313 -208
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +152 -42
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +2 -2
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +289 -292
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +39 -33
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +211 -216
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +188 -195
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/oauth/index.d.ts +71 -76
- package/dist/api/oauth/index.d.ts.map +1 -1
- package/dist/api/oauth/index.js.map +1 -1
- package/dist/api/organizations/index.browser.js.map +1 -1
- package/dist/api/organizations/index.d.ts +104 -109
- package/dist/api/organizations/index.d.ts.map +1 -1
- package/dist/api/organizations/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +43 -16
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +488 -344
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +175 -35
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.d.ts +396 -402
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/payments/index.js.map +1 -1
- package/dist/api/subscriptions/index.d.ts +644 -652
- package/dist/api/subscriptions/index.d.ts.map +1 -1
- package/dist/api/subscriptions/index.js +1 -1
- package/dist/api/subscriptions/index.js.map +1 -1
- package/dist/api/users/index.browser.js +7 -0
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +1073 -1006
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +283 -61
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.browser.js.map +1 -1
- package/dist/api/verifications/index.d.ts +134 -140
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/background/index.d.ts +95 -0
- package/dist/background/index.d.ts.map +1 -0
- package/dist/background/index.js +121 -0
- package/dist/background/index.js.map +1 -0
- package/dist/background/index.workerd.js +110 -0
- package/dist/background/index.workerd.js.map +1 -0
- package/dist/batch/index.d.ts +5 -7
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js.map +1 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/bucket/index.d.ts +76 -54
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +58 -11
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +200 -5
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cache/core/index.d.ts +7 -10
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/cache/database/index.d.ts +22 -26
- package/dist/cache/database/index.d.ts.map +1 -1
- package/dist/cache/database/index.js.map +1 -1
- package/dist/cache/redis/index.d.ts +4 -7
- package/dist/cache/redis/index.d.ts.map +1 -1
- package/dist/cache/redis/index.js.map +1 -1
- package/dist/captcha/index.d.ts +3 -6
- package/dist/captcha/index.d.ts.map +1 -1
- package/dist/captcha/index.js.map +1 -1
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +417 -214
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +325 -563
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +3 -5
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/i18n/index.d.ts +8 -12
- package/dist/cli/i18n/index.d.ts.map +1 -1
- package/dist/cli/i18n/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +126 -1342
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +136 -2374
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/platform-lib/index.d.ts +1446 -0
- package/dist/cli/platform-lib/index.d.ts.map +1 -0
- package/dist/cli/platform-lib/index.js +2597 -0
- package/dist/cli/platform-lib/index.js.map +1 -0
- package/dist/cli/vendor/index.d.ts +17 -21
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/command/index.d.ts +21 -20
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +39 -10
- package/dist/command/index.js.map +1 -1
- package/dist/{containers → container}/core/index.d.ts +13 -15
- package/dist/container/core/index.d.ts.map +1 -0
- package/dist/{containers → container}/core/index.js +23 -14
- package/dist/container/core/index.js.map +1 -0
- package/dist/{containers → container}/core/index.workerd.js +37 -22
- package/dist/container/core/index.workerd.js.map +1 -0
- package/dist/core/index.browser.js +27 -1
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +48 -24
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +27 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +27 -1
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +27 -1
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/crypto/index.browser.js.map +1 -1
- package/dist/crypto/index.d.ts +5 -8
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js.map +1 -1
- package/dist/datetime/index.d.ts +3 -4
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/brevo/index.d.ts +2 -4
- package/dist/email/brevo/index.d.ts.map +1 -1
- package/dist/email/brevo/index.js.map +1 -1
- package/dist/email/cloudflare/index.d.ts +20 -7
- package/dist/email/cloudflare/index.d.ts.map +1 -1
- package/dist/email/cloudflare/index.js +46 -9
- package/dist/email/cloudflare/index.js.map +1 -1
- package/dist/email/core/index.d.ts +6 -9
- package/dist/email/core/index.d.ts.map +1 -1
- package/dist/email/core/index.js.map +1 -1
- package/dist/email/core/index.workerd.js.map +1 -1
- package/dist/email/smtp/index.d.ts +10 -13
- package/dist/email/smtp/index.d.ts.map +1 -1
- package/dist/email/smtp/index.js +107 -32
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.d.ts +1 -2
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +9 -14
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js.map +1 -1
- package/dist/lock/redis/index.d.ts +2 -4
- 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 +105 -76
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +196 -174
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +16 -20
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +19 -1
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +76 -62
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +20 -2
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +28 -20
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +12 -15
- package/dist/queue/core/index.d.ts.map +1 -1
- package/dist/queue/core/index.js.map +1 -1
- package/dist/queue/core/index.workerd.js.map +1 -1
- package/dist/queue/redis/index.d.ts +3 -5
- package/dist/queue/redis/index.d.ts.map +1 -1
- package/dist/queue/redis/index.js.map +1 -1
- package/dist/react/auth/index.browser.js +9 -2
- package/dist/react/auth/index.browser.js.map +1 -1
- package/dist/react/auth/index.d.ts +14 -9
- package/dist/react/auth/index.d.ts.map +1 -1
- package/dist/react/auth/index.js +9 -2
- package/dist/react/auth/index.js.map +1 -1
- package/dist/react/core/index.d.ts +7 -8
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +6 -3
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +2 -4
- package/dist/react/form/index.d.ts.map +1 -1
- 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 +2 -4
- 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 -11
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +33 -1
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/intro/index.d.ts +1 -2
- package/dist/react/intro/index.d.ts.map +1 -1
- package/dist/react/intro/index.js +2 -2
- package/dist/react/intro/index.js.map +1 -1
- package/dist/react/router/index.browser.js +65 -19
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +327 -222
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +65 -29
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/index.d.ts +1 -2
- package/dist/react/testing/index.d.ts.map +1 -1
- package/dist/react/testing/index.js +16 -17
- package/dist/react/testing/index.js.map +1 -1
- package/dist/react/ui/index.d.ts +20 -25
- package/dist/react/ui/index.d.ts.map +1 -1
- package/dist/react/ui/index.js.map +1 -1
- package/dist/redis/index.bun.js.map +1 -1
- package/dist/redis/index.d.ts +17 -19
- package/dist/redis/index.d.ts.map +1 -1
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +2 -4
- 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 +10 -13
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.browser.js.map +1 -1
- package/dist/security/index.d.ts +45 -48
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.browser.js.map +1 -1
- package/dist/server/auth/index.d.ts +167 -172
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +4 -8
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.browser.js.map +1 -1
- package/dist/server/cookies/index.d.ts +5 -7
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts +88 -73
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +19 -0
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +11 -14
- package/dist/server/cors/index.d.ts.map +1 -1
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/etag/index.d.ts +6 -9
- 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 -21
- package/dist/server/health/index.d.ts.map +1 -1
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/links/index.browser.js +2 -0
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +63 -67
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +2 -0
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +5 -7
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +3 -5
- 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 +10 -13
- package/dist/server/rate-limit/index.d.ts.map +1 -1
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +3 -5
- 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 +5 -8
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +3 -5
- 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 +2 -4
- package/dist/system/index.d.ts.map +1 -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 +4 -6
- package/dist/topic/core/index.d.ts.map +1 -1
- package/dist/topic/core/index.js.map +1 -1
- package/dist/topic/redis/index.d.ts +5 -8
- package/dist/topic/redis/index.d.ts.map +1 -1
- package/dist/topic/redis/index.js.map +1 -1
- package/package.json +45 -22
- package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
- package/src/api/audits/controllers/AdminAuditController.ts +14 -0
- package/src/api/audits/services/AuditService.ts +21 -88
- package/src/api/files/__tests__/FileService.spec.ts +207 -2
- package/src/api/files/index.ts +3 -0
- package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
- package/src/api/files/schemas/fileResourceSchema.ts +10 -1
- package/src/api/files/services/FileService.ts +170 -72
- package/src/api/jobs/__tests__/$job.spec.ts +24 -1
- package/src/api/jobs/index.ts +4 -3
- package/src/api/jobs/primitives/$job.ts +7 -3
- package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
- package/src/api/jobs/providers/JobProvider.ts +53 -24
- package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
- package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
- package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
- package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
- package/src/api/parameters/audits/ParameterAudits.ts +17 -0
- package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
- package/src/api/parameters/index.ts +3 -0
- package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
- package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
- package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
- package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
- package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
- package/src/api/parameters/services/ParameterProvider.ts +69 -6
- package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
- package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
- package/src/api/users/audits/SessionAudits.ts +33 -0
- package/src/api/users/audits/UserAudits.ts +19 -43
- package/src/api/users/controllers/AdminUserController.ts +66 -1
- package/src/api/users/entities/sessions.ts +6 -0
- package/src/api/users/entities/users.ts +2 -0
- package/src/api/users/index.ts +9 -1
- package/src/api/users/primitives/$realm.ts +3 -0
- package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
- package/src/api/users/schemas/updateUserSchema.ts +1 -8
- package/src/api/users/schemas/userQuerySchema.ts +7 -0
- package/src/api/users/services/CredentialService.ts +15 -6
- package/src/api/users/services/IdentityService.ts +2 -1
- package/src/api/users/services/RegistrationService.ts +2 -1
- package/src/api/users/services/SessionCrudService.ts +19 -2
- package/src/api/users/services/SessionService.ts +39 -19
- package/src/api/users/services/UserService.ts +106 -8
- package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
- package/src/background/index.ts +37 -0
- package/src/background/index.workerd.ts +28 -0
- package/src/background/providers/BackgroundTaskProvider.ts +70 -0
- package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
- package/src/bucket/__tests__/$bucket.spec.ts +18 -0
- package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
- package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
- package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
- package/src/bucket/__tests__/shared.ts +30 -0
- package/src/bucket/index.ts +5 -5
- package/src/bucket/index.workerd.ts +11 -4
- package/src/bucket/primitives/$bucket.ts +27 -0
- package/src/bucket/providers/FileStorageProvider.ts +13 -0
- package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
- package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
- package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
- package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
- package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
- package/src/cli/core/__tests__/init.spec.ts +0 -219
- package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
- package/src/cli/core/commands/build.ts +108 -30
- package/src/cli/core/commands/init.ts +0 -12
- package/src/cli/core/commands/pack.ts +133 -0
- package/src/cli/core/index.ts +3 -0
- package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
- package/src/cli/core/services/PackageManagerUtils.ts +0 -16
- package/src/cli/core/services/ProjectScaffolder.ts +29 -291
- package/src/cli/core/tasks/BuildCloudflareTask.ts +353 -47
- package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
- package/src/cli/core/tasks/BuildTask.ts +34 -0
- package/src/cli/core/templates/apiIndexTs.ts +1 -22
- package/src/cli/core/templates/mainCss.ts +0 -1
- package/src/cli/core/templates/webAppRouterTs.ts +0 -99
- package/src/cli/core/templates/webIndexTs.ts +1 -22
- package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
- package/src/cli/platform/commands/SecretsCommand.ts +8 -6
- package/src/cli/platform/commands/platform.ts +192 -46
- package/src/cli/platform/index.ts +12 -52
- package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
- package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
- package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
- package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +402 -165
- package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
- package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
- package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
- package/src/cli/platform-lib/index.ts +67 -0
- package/src/cli/platform-lib/services/NamingService.ts +136 -0
- package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
- package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
- package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
- package/src/command/__tests__/Runner.spec.ts +20 -0
- package/src/command/helpers/EnvUtils.ts +19 -3
- package/src/command/helpers/Runner.ts +12 -2
- package/src/command/providers/CliProvider.ts +34 -1
- package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
- package/src/{containers → container}/core/index.ts +4 -4
- package/src/{containers → container}/core/index.workerd.ts +19 -3
- package/src/{containers → container}/core/primitives/$container.ts +1 -1
- package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
- package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
- package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
- package/src/core/Alepha.ts +49 -1
- package/src/core/__tests__/$env.spec.ts +42 -0
- package/src/core/__tests__/dump.spec.ts +47 -0
- package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
- package/src/email/cloudflare/index.ts +14 -5
- package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
- package/src/logger/__tests__/Logger.spec.ts +55 -0
- package/src/logger/index.ts +13 -0
- package/src/logger/services/Logger.ts +31 -1
- package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
- package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
- package/src/orm/core/interfaces/PgQuery.ts +4 -1
- package/src/orm/core/services/Repository.ts +27 -11
- package/src/react/auth/hooks/useAuth.ts +10 -5
- package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
- package/src/react/core/hooks/useAction.ts +14 -3
- package/src/react/core/hooks/useQuery.ts +24 -4
- package/src/react/i18n/components/Translate.tsx +47 -0
- package/src/react/i18n/index.ts +2 -0
- package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
- package/src/react/router/__tests__/$page.spec.tsx +3 -2
- package/src/react/router/__tests__/page-can.spec.ts +18 -13
- package/src/react/router/hooks/useQueryParams.ts +114 -14
- package/src/react/router/primitives/$page.ts +85 -4
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +3 -7
- package/src/react/router/providers/ReactServerProvider.ts +4 -13
- package/src/react/ui/services/SchemaControl.ts +3 -4
- package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
- package/src/server/links/providers/LinkProvider.ts +10 -0
- package/dist/containers/core/index.d.ts.map +0 -1
- package/dist/containers/core/index.js.map +0 -1
- package/dist/containers/core/index.workerd.js.map +0 -1
- package/src/cli/core/templates/componentsJsonTs.ts +0 -39
- package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
- package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
- package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
- package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
- package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
- package/src/cli/platform/services/NamingService.ts +0 -54
- /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
- /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
- /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
- /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
- /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
- /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
- /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
|
@@ -1,22 +1,105 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
2
|
import { $inject } from "alepha";
|
|
3
3
|
import { KV_DEFAULT_BINDING } from "alepha/cache";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
CloudflareEmailProvider,
|
|
8
|
-
SEND_EMAIL_DEFAULT_BINDING,
|
|
9
|
-
} from "alepha/email/cloudflare";
|
|
4
|
+
import type { ContainerPrimitive } from "alepha/container";
|
|
5
|
+
import { SEND_EMAIL_DEFAULT_BINDING } from "alepha/email/cloudflare";
|
|
10
6
|
import { QUEUE_DEFAULT_BINDING } from "alepha/queue";
|
|
11
7
|
import type { CronProvider, WorkerdCronProvider } from "alepha/scheduler";
|
|
12
8
|
import { FileSystemProvider } from "alepha/system";
|
|
13
9
|
import { ViteUtils } from "../services/ViteUtils.ts";
|
|
14
10
|
import { BuildTask, type BuildTaskContext } from "./BuildTask.ts";
|
|
15
11
|
|
|
12
|
+
// Looked up by class name string (not by class identity) because
|
|
13
|
+
// BuildCloudflareTask runs in the CLI's Alepha context while ctx.alepha
|
|
14
|
+
// is the workspace's separate context. Two module graphs = two distinct
|
|
15
|
+
// `CloudflareEmailProvider` class objects, so the imported reference
|
|
16
|
+
// here wouldn't match the one the workspace registered.
|
|
17
|
+
const CLOUDFLARE_EMAIL_PROVIDER_NAME = "CloudflareEmailProvider";
|
|
18
|
+
|
|
16
19
|
interface WranglerConfig {
|
|
17
20
|
[key: string]: any;
|
|
18
21
|
}
|
|
19
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Build-time snapshot describing what the workspace needs at deploy
|
|
25
|
+
* time. Written to `dist/manifest.json` alongside `wrangler.jsonc`.
|
|
26
|
+
*
|
|
27
|
+
* Lets `alepha platform up --prebuilt` skip the Vite-based
|
|
28
|
+
* introspection step on the deploy side — and lets Alepha Rocket skip
|
|
29
|
+
* the workspace's runtime `npm install` because no app source is
|
|
30
|
+
* booted at deploy time. The manifest captures the bits of primitive
|
|
31
|
+
* data that the deploy steps (provision, secrets, hooks) need to
|
|
32
|
+
* know.
|
|
33
|
+
*/
|
|
34
|
+
export interface BuildManifest {
|
|
35
|
+
version: 1;
|
|
36
|
+
project: string;
|
|
37
|
+
/**
|
|
38
|
+
* Default environment when `--env` is omitted at deploy time.
|
|
39
|
+
* Captured from `platformOptions.default` (defaults to `"production"`).
|
|
40
|
+
*/
|
|
41
|
+
defaultEnv: string;
|
|
42
|
+
/**
|
|
43
|
+
* Multi-tenancy mode (`none` | `optional` | `required`). Captured from
|
|
44
|
+
* `platformOptions.tenancy` so the prebuilt deploy side (Rocket) can
|
|
45
|
+
* validate `--tenant` without re-evaluating `alepha.config.ts`.
|
|
46
|
+
*/
|
|
47
|
+
tenancy?: "none" | "optional" | "required";
|
|
48
|
+
/**
|
|
49
|
+
* Resolved `platform({ environments: ... })` map. Captured at build
|
|
50
|
+
* time from the workspace's `alepha.config.ts` so the deploy side
|
|
51
|
+
* doesn't need to re-evaluate the config. Each value is the same
|
|
52
|
+
* `EnvironmentConfig` shape consumed by the orchestrator (adapter,
|
|
53
|
+
* domain, zone, jurisdiction, accountId).
|
|
54
|
+
*/
|
|
55
|
+
environments: Record<
|
|
56
|
+
string,
|
|
57
|
+
{
|
|
58
|
+
adapter: "cloudflare" | "vercel";
|
|
59
|
+
domain?: string;
|
|
60
|
+
zone?: string;
|
|
61
|
+
jurisdiction?: "eu" | "fedramp";
|
|
62
|
+
accountId?: string;
|
|
63
|
+
}
|
|
64
|
+
>;
|
|
65
|
+
resources: {
|
|
66
|
+
hasDatabase: boolean;
|
|
67
|
+
hasBucket: boolean;
|
|
68
|
+
hasKV: boolean;
|
|
69
|
+
hasQueue: boolean;
|
|
70
|
+
hasCron: boolean;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* All distinct cron expressions registered by `$scheduler`
|
|
74
|
+
* primitives. Empty when `hasCron` is false.
|
|
75
|
+
*/
|
|
76
|
+
crons: string[];
|
|
77
|
+
/**
|
|
78
|
+
* `$container()` descriptors — image, port, lifecycle settings.
|
|
79
|
+
* Used both to populate Cloudflare Containers bindings in
|
|
80
|
+
* wrangler.jsonc and (in future) to know which images Rocket should
|
|
81
|
+
* pull on the deploy side.
|
|
82
|
+
*/
|
|
83
|
+
containers: Array<{
|
|
84
|
+
name: string;
|
|
85
|
+
className: string;
|
|
86
|
+
image: string;
|
|
87
|
+
port: number;
|
|
88
|
+
sleepAfter: string;
|
|
89
|
+
instanceType: string;
|
|
90
|
+
maxInstances: number;
|
|
91
|
+
}>;
|
|
92
|
+
/**
|
|
93
|
+
* Every env var the app declares via `$env`, captured from
|
|
94
|
+
* `alepha.dump().env` at build time. The deploy `secrets` step uses this
|
|
95
|
+
* as the worker-secret allowlist (minus build/binding vars) so CI can
|
|
96
|
+
* deliver secrets straight from `process.env` without a `.env` file —
|
|
97
|
+
* `platform.secrets.keys` overrides it when set. Empty when introspection
|
|
98
|
+
* was unavailable (older artifacts / prebuilt mode).
|
|
99
|
+
*/
|
|
100
|
+
env: string[];
|
|
101
|
+
}
|
|
102
|
+
|
|
20
103
|
/**
|
|
21
104
|
* Generate Cloudflare Workers deployment configuration.
|
|
22
105
|
*
|
|
@@ -52,7 +135,15 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
52
135
|
distDir: string,
|
|
53
136
|
): Promise<void> {
|
|
54
137
|
const root = ctx.root;
|
|
55
|
-
|
|
138
|
+
// Slugify the dir basename — wrangler rejects names that aren't
|
|
139
|
+
// `^[a-z0-9-]+$` (no uppercase, dots, underscores, spaces, etc.).
|
|
140
|
+
// Without this, running `alepha build -t cloudflare` in a dir like
|
|
141
|
+
// `My App` or `club-0.0.2` produces an unusable `wrangler.jsonc`.
|
|
142
|
+
const name = basename(root)
|
|
143
|
+
.toLowerCase()
|
|
144
|
+
.replace(/[^a-z0-9-]+/g, "-")
|
|
145
|
+
.replace(/^-+|-+$/g, "")
|
|
146
|
+
.slice(0, 63);
|
|
56
147
|
const hasAssets = await this.fs.exists(
|
|
57
148
|
this.fs.join(root, distDir, "public"),
|
|
58
149
|
);
|
|
@@ -98,9 +189,128 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
98
189
|
JSON.stringify(wrangler, null, 2),
|
|
99
190
|
);
|
|
100
191
|
|
|
192
|
+
// Only write a fresh manifest when we discovered it from a booted
|
|
193
|
+
// Alepha instance. In manifest mode (ctx.manifest != null) we're
|
|
194
|
+
// re-emitting the same data we just read — skip to avoid a redundant
|
|
195
|
+
// write and to keep the original manifest as the canonical record.
|
|
196
|
+
if (!ctx.manifest) {
|
|
197
|
+
await this.writeManifest(ctx, root, distDir, name, containers);
|
|
198
|
+
}
|
|
101
199
|
await this.writeWorkerEntryPoint(root, distDir, containers);
|
|
102
200
|
}
|
|
103
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Write `dist/manifest.json` — a build-time snapshot of everything
|
|
204
|
+
* downstream tooling needs to know about the app without re-booting
|
|
205
|
+
* it. Used by `alepha platform up --prebuilt` (and Alepha Rocket) so
|
|
206
|
+
* the deploy path can skip the Vite-based introspection step and the
|
|
207
|
+
* workspace's runtime npm install.
|
|
208
|
+
*/
|
|
209
|
+
protected async writeManifest(
|
|
210
|
+
ctx: BuildTaskContext,
|
|
211
|
+
root: string,
|
|
212
|
+
distDir: string,
|
|
213
|
+
name: string,
|
|
214
|
+
containers: ContainerDescriptor[],
|
|
215
|
+
): Promise<void> {
|
|
216
|
+
// Discover the same primitive shapes the enhance* methods read.
|
|
217
|
+
// Errors are silently swallowed — an absent primitive class just
|
|
218
|
+
// means the app doesn't use that resource.
|
|
219
|
+
let hasDatabase = false;
|
|
220
|
+
let hasBucket = false;
|
|
221
|
+
let hasKV = false;
|
|
222
|
+
let hasQueue = false;
|
|
223
|
+
let crons: string[] = [];
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const repo = ctx.alepha.inject("RepositoryProvider") as {
|
|
227
|
+
getRepositories?: () => unknown[];
|
|
228
|
+
};
|
|
229
|
+
hasDatabase = (repo.getRepositories?.() ?? []).length > 0;
|
|
230
|
+
} catch {}
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
hasBucket = ctx.alepha.primitives("$bucket").length > 0;
|
|
234
|
+
} catch {}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
// Only count $cache primitives without an explicit `provider`
|
|
238
|
+
// option — those fall back to KV on workerd. Explicit memory /
|
|
239
|
+
// Redis / Postgres providers opt out of KV provisioning.
|
|
240
|
+
hasKV =
|
|
241
|
+
ctx.alepha
|
|
242
|
+
.primitives("cache")
|
|
243
|
+
.filter(
|
|
244
|
+
(p) =>
|
|
245
|
+
(p as { options?: { provider?: unknown } }).options?.provider ==
|
|
246
|
+
null,
|
|
247
|
+
).length > 0;
|
|
248
|
+
} catch {}
|
|
249
|
+
|
|
250
|
+
try {
|
|
251
|
+
hasQueue = ctx.alepha.primitives("$queue").length > 0;
|
|
252
|
+
} catch {}
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
const cronProvider = ctx.alepha.inject("CronProvider") as {
|
|
256
|
+
getCronJobs?: () => Array<{ expression: string }>;
|
|
257
|
+
};
|
|
258
|
+
crons = [
|
|
259
|
+
...new Set(
|
|
260
|
+
(cronProvider.getCronJobs?.() ?? []).map((c) => c.expression),
|
|
261
|
+
),
|
|
262
|
+
];
|
|
263
|
+
} catch {}
|
|
264
|
+
|
|
265
|
+
// platformOptions come from the CLI's Alepha instance (where
|
|
266
|
+
// alepha.config.ts ran during the configure hook). BuildCommand
|
|
267
|
+
// reads them up there and threads them via ctx — ctx.alepha here
|
|
268
|
+
// is the WORKSPACE's Vite-booted Alepha, which never saw the
|
|
269
|
+
// platform options.
|
|
270
|
+
const defaultEnv = ctx.platformOptions?.default ?? "production";
|
|
271
|
+
const environments = (ctx.platformOptions?.environments ??
|
|
272
|
+
{}) as BuildManifest["environments"];
|
|
273
|
+
|
|
274
|
+
// Every declared `$env` key. dump() force-instantiates the graph (no
|
|
275
|
+
// start/ready hooks), so this is the full env surface — used by the
|
|
276
|
+
// deploy `secrets` step as the worker-secret allowlist.
|
|
277
|
+
let env: string[] = [];
|
|
278
|
+
try {
|
|
279
|
+
env = Object.keys(ctx.alepha.dump().env).sort();
|
|
280
|
+
} catch {}
|
|
281
|
+
|
|
282
|
+
const manifest: BuildManifest = {
|
|
283
|
+
version: 1,
|
|
284
|
+
project: name,
|
|
285
|
+
defaultEnv,
|
|
286
|
+
tenancy: ctx.platformOptions?.tenancy,
|
|
287
|
+
environments,
|
|
288
|
+
resources: {
|
|
289
|
+
hasDatabase,
|
|
290
|
+
hasBucket,
|
|
291
|
+
hasKV,
|
|
292
|
+
hasQueue,
|
|
293
|
+
hasCron: crons.length > 0,
|
|
294
|
+
},
|
|
295
|
+
crons,
|
|
296
|
+
containers: containers.map((c) => ({
|
|
297
|
+
name: c.name,
|
|
298
|
+
className: c.className,
|
|
299
|
+
image: c.image,
|
|
300
|
+
port: c.port,
|
|
301
|
+
sleepAfter: c.sleepAfter,
|
|
302
|
+
instanceType: c.instanceType,
|
|
303
|
+
maxInstances: c.maxInstances,
|
|
304
|
+
})),
|
|
305
|
+
env,
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
await this.fs.writeFile(
|
|
309
|
+
this.fs.join(root, distDir, "manifest.json"),
|
|
310
|
+
JSON.stringify(manifest, null, 2),
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
104
314
|
protected enhanceDomain(wrangler: WranglerConfig): void {
|
|
105
315
|
const domain = process.env.CLOUDFLARE_DOMAIN;
|
|
106
316
|
if (!domain) {
|
|
@@ -132,23 +342,29 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
132
342
|
}
|
|
133
343
|
|
|
134
344
|
protected enhanceCron(ctx: BuildTaskContext, wrangler: WranglerConfig): void {
|
|
135
|
-
|
|
345
|
+
const cronExpressions = ctx.manifest
|
|
346
|
+
? ctx.manifest.crons
|
|
347
|
+
: this.discoverCrons(ctx);
|
|
348
|
+
if (cronExpressions.length === 0) {
|
|
136
349
|
return;
|
|
137
350
|
}
|
|
351
|
+
wrangler.triggers ??= {};
|
|
352
|
+
wrangler.triggers.crons = cronExpressions;
|
|
353
|
+
}
|
|
138
354
|
|
|
355
|
+
protected discoverCrons(ctx: BuildTaskContext): string[] {
|
|
356
|
+
if (ctx.alepha.primitives("scheduler").length === 0) {
|
|
357
|
+
return [];
|
|
358
|
+
}
|
|
139
359
|
let cronProvider: CronProvider | undefined;
|
|
140
360
|
try {
|
|
141
361
|
cronProvider = ctx.alepha.inject("CronProvider") as WorkerdCronProvider;
|
|
142
362
|
} catch {}
|
|
143
|
-
|
|
144
363
|
const crons = cronProvider?.getCronJobs();
|
|
145
364
|
if (!crons || crons.length === 0) {
|
|
146
|
-
return;
|
|
365
|
+
return [];
|
|
147
366
|
}
|
|
148
|
-
|
|
149
|
-
const cronExpressions = [...new Set(crons.map((c) => c.expression))];
|
|
150
|
-
wrangler.triggers ??= {};
|
|
151
|
-
wrangler.triggers.crons = cronExpressions;
|
|
367
|
+
return [...new Set(crons.map((c) => c.expression))];
|
|
152
368
|
}
|
|
153
369
|
|
|
154
370
|
protected enhanceDatabase(wrangler: WranglerConfig): void {
|
|
@@ -256,14 +472,16 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
256
472
|
ctx: BuildTaskContext,
|
|
257
473
|
wrangler: WranglerConfig,
|
|
258
474
|
): void {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
475
|
+
// Manifest mode doesn't capture email provider details yet. Apps
|
|
476
|
+
// using CloudflareEmailProvider would need a manifest field added.
|
|
477
|
+
// For now, skip — non-email apps and apps using non-CF providers
|
|
478
|
+
// are unaffected. TODO: add `emailProvider` to BuildManifest.
|
|
479
|
+
if (ctx.manifest || !ctx.alepha) {
|
|
263
480
|
return;
|
|
264
481
|
}
|
|
265
|
-
|
|
266
|
-
|
|
482
|
+
try {
|
|
483
|
+
ctx.alepha.inject(CLOUDFLARE_EMAIL_PROVIDER_NAME);
|
|
484
|
+
} catch {
|
|
267
485
|
return;
|
|
268
486
|
}
|
|
269
487
|
|
|
@@ -276,11 +494,17 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
276
494
|
return;
|
|
277
495
|
}
|
|
278
496
|
|
|
497
|
+
// NOTE: do NOT set `destination_address` here. On a Cloudflare
|
|
498
|
+
// `send_email` binding, `destination_address` is a *recipient* allow-list
|
|
499
|
+
// lock (the worker may then only send TO that one address) — it is not the
|
|
500
|
+
// sender. Setting it to `EMAIL_FROM` (the sender) broke all outbound mail:
|
|
501
|
+
// a bare address locked delivery to that single recipient ("email to … not
|
|
502
|
+
// allowed"), and a display-name form like `Lore <noreply@…>` is a malformed
|
|
503
|
+
// destination value that Cloudflare rejects with "internal error". The
|
|
504
|
+
// sender goes in the message `from` field (see CloudflareEmailProvider.send);
|
|
505
|
+
// leaving the binding unrestricted lets the worker send to any verified
|
|
506
|
+
// destination.
|
|
279
507
|
const entry: Record<string, unknown> = { name: SEND_EMAIL_DEFAULT_BINDING };
|
|
280
|
-
const destination = process.env.EMAIL_FROM;
|
|
281
|
-
if (destination) {
|
|
282
|
-
entry.destination_address = destination;
|
|
283
|
-
}
|
|
284
508
|
|
|
285
509
|
wrangler.send_email.push(entry);
|
|
286
510
|
}
|
|
@@ -295,18 +519,19 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
295
519
|
* `writeWorkerEntryPoint` can emit `export class <NAME> extends
|
|
296
520
|
* Container` declarations referencing them.
|
|
297
521
|
*/
|
|
298
|
-
protected
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
522
|
+
protected discoverContainers(ctx: BuildTaskContext): ContainerDescriptor[] {
|
|
523
|
+
// String key, not the `$container` factory. The build task runs in
|
|
524
|
+
// the CLI's Node realm, while the workspace's entry module is
|
|
525
|
+
// loaded by Vite — two separate module copies of
|
|
526
|
+
// `alepha/container`. Looking up by `$container[KIND]` (a class
|
|
527
|
+
// reference) would dereference the CLI's ContainerPrimitive class,
|
|
528
|
+
// which never matches the workspace's. The string form iterates
|
|
529
|
+
// the registry by class name and survives the dual-realm — same
|
|
530
|
+
// pattern used for `$bucket`, `$queue`, `scheduler` below.
|
|
302
531
|
const primitives = ctx.alepha.primitives(
|
|
303
|
-
|
|
532
|
+
"container",
|
|
304
533
|
) as ContainerPrimitive[];
|
|
305
|
-
|
|
306
|
-
return [];
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const descriptors: ContainerDescriptor[] = primitives.map((p) => ({
|
|
534
|
+
return primitives.map((p) => ({
|
|
310
535
|
name: p.name.toUpperCase(),
|
|
311
536
|
className: p.name
|
|
312
537
|
.split(/[^a-zA-Z0-9]/)
|
|
@@ -317,10 +542,67 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
317
542
|
port: p.options.port ?? 3000,
|
|
318
543
|
sleepAfter:
|
|
319
544
|
typeof p.options.sleepAfter === "string" ? p.options.sleepAfter : "15m",
|
|
320
|
-
|
|
545
|
+
// `lite` is the post-GA name for what `$container` historically
|
|
546
|
+
// called `dev`. Default to `lite` here and rewrite any
|
|
547
|
+
// explicit `dev` to it on the way out — wrangler warns
|
|
548
|
+
// otherwise.
|
|
549
|
+
instanceType:
|
|
550
|
+
p.options.instanceType === "dev"
|
|
551
|
+
? "lite"
|
|
552
|
+
: (p.options.instanceType ?? "lite"),
|
|
321
553
|
maxInstances: p.options.maxInstances ?? 5,
|
|
322
554
|
envVars: p.options.envVars,
|
|
323
555
|
}));
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Expand a short image ref (e.g. `alepha-rocket:0.1.0`) into the
|
|
560
|
+
* fully-qualified `registry.cloudflare.com/<account>/<image>:<tag>`
|
|
561
|
+
* URL that wrangler validates at deploy time.
|
|
562
|
+
*
|
|
563
|
+
* Cloudflare Containers only pulls from `registry.cloudflare.com`;
|
|
564
|
+
* wrangler accepts either a Dockerfile path or a fully-qualified
|
|
565
|
+
* registry URL in the `image` field — not a bare DockerHub-style
|
|
566
|
+
* name. We let `$container({ image })` callers write the short
|
|
567
|
+
* form (it matches what `wrangler containers push <local>` accepts
|
|
568
|
+
* + matches the local docker tag) and rewrite to the CF registry
|
|
569
|
+
* URL here.
|
|
570
|
+
*
|
|
571
|
+
* Pass-through cases:
|
|
572
|
+
* - already a full URL: starts with `registry.cloudflare.com/`
|
|
573
|
+
* or contains a scheme/`://`
|
|
574
|
+
* - looks like a Dockerfile path: starts with `./` or `/`
|
|
575
|
+
*/
|
|
576
|
+
protected resolveContainerImage(image: string): string {
|
|
577
|
+
if (
|
|
578
|
+
image.startsWith("./") ||
|
|
579
|
+
image.startsWith("/") ||
|
|
580
|
+
image.startsWith("registry.cloudflare.com/") ||
|
|
581
|
+
image.includes("://")
|
|
582
|
+
) {
|
|
583
|
+
return image;
|
|
584
|
+
}
|
|
585
|
+
const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
586
|
+
if (!accountId) {
|
|
587
|
+
// No account id — leave the short form and let wrangler error
|
|
588
|
+
// out with a clearer message. This branch fires only in dry
|
|
589
|
+
// builds where the env isn't wired (e.g. `alepha build` without
|
|
590
|
+
// `alepha platform up` around it).
|
|
591
|
+
return image;
|
|
592
|
+
}
|
|
593
|
+
return `registry.cloudflare.com/${accountId}/${image}`;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
protected enhanceContainers(
|
|
597
|
+
ctx: BuildTaskContext,
|
|
598
|
+
wrangler: WranglerConfig,
|
|
599
|
+
): ContainerDescriptor[] {
|
|
600
|
+
const descriptors: ContainerDescriptor[] = ctx.manifest
|
|
601
|
+
? (ctx.manifest.containers as ContainerDescriptor[])
|
|
602
|
+
: this.discoverContainers(ctx);
|
|
603
|
+
if (descriptors.length === 0) {
|
|
604
|
+
return [];
|
|
605
|
+
}
|
|
324
606
|
|
|
325
607
|
wrangler.containers = wrangler.containers || [];
|
|
326
608
|
wrangler.durable_objects = wrangler.durable_objects || {};
|
|
@@ -331,7 +613,7 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
331
613
|
for (const d of descriptors) {
|
|
332
614
|
wrangler.containers.push({
|
|
333
615
|
class_name: d.className,
|
|
334
|
-
image: d.image,
|
|
616
|
+
image: this.resolveContainerImage(d.image),
|
|
335
617
|
instance_type: d.instanceType,
|
|
336
618
|
max_instances: d.maxInstances,
|
|
337
619
|
});
|
|
@@ -357,20 +639,24 @@ export class BuildCloudflareTask extends BuildTask {
|
|
|
357
639
|
distDir: string,
|
|
358
640
|
containers: ContainerDescriptor[] = [],
|
|
359
641
|
): Promise<void> {
|
|
642
|
+
// Extend `globalThis.__alepha_CloudflareContainer` instead of
|
|
643
|
+
// importing `@cloudflare/containers` directly. The entry is
|
|
644
|
+
// written AFTER Vite, so any bare specifier in here survives to
|
|
645
|
+
// workerd (which has `no_bundle: true`) and 10021's out. The
|
|
646
|
+
// global is set by a side-effect in `alepha/container`'s
|
|
647
|
+
// workerd entry, which Vite has already inlined into
|
|
648
|
+
// `./index.js`. ESM evaluates top-level imports before the
|
|
649
|
+
// module body, so by the time the `extends` expression below is
|
|
650
|
+
// evaluated, the global is set.
|
|
360
651
|
const containerDeclarations = containers
|
|
361
652
|
.map((c) => {
|
|
362
653
|
const envVars = c.envVars
|
|
363
654
|
? ` envVars = ${JSON.stringify(c.envVars)};\n`
|
|
364
655
|
: "";
|
|
365
|
-
return `export class ${c.className} extends
|
|
656
|
+
return `export class ${c.className} extends globalThis.__alepha_CloudflareContainer {\n defaultPort = ${c.port};\n sleepAfter = "${c.sleepAfter}";\n${envVars}}`;
|
|
366
657
|
})
|
|
367
658
|
.join("\n\n");
|
|
368
659
|
|
|
369
|
-
const containerImport =
|
|
370
|
-
containers.length > 0
|
|
371
|
-
? `import { Container } from "@cloudflare/containers";\n\n${containerDeclarations}\n\n`
|
|
372
|
-
: "";
|
|
373
|
-
|
|
374
660
|
const workerCode = `
|
|
375
661
|
import "./index.js";
|
|
376
662
|
|
|
@@ -385,11 +671,19 @@ const setWaitUntil = (executionCtx) => {
|
|
|
385
671
|
}
|
|
386
672
|
};
|
|
387
673
|
|
|
674
|
+
// Bind the per-invocation Worker \`env\`: keep the full binding (D1, R2, KV, …)
|
|
675
|
+
// in the store for providers, and lift its string values (secrets/vars like
|
|
676
|
+
// PUBLIC_URL) into \`alepha.env\` so \`$env\` resolves them at runtime.
|
|
677
|
+
const bindEnv = (env) => {
|
|
678
|
+
__alepha.set("cloudflare.env", env);
|
|
679
|
+
__alepha.loadEnv(env);
|
|
680
|
+
};
|
|
681
|
+
|
|
388
682
|
export default {
|
|
389
683
|
fetch: async (request, env, executionCtx) => {
|
|
390
684
|
const ctx = { req: request, res: undefined };
|
|
391
685
|
|
|
392
|
-
|
|
686
|
+
bindEnv(env);
|
|
393
687
|
setWaitUntil(executionCtx);
|
|
394
688
|
|
|
395
689
|
try {
|
|
@@ -405,7 +699,7 @@ export default {
|
|
|
405
699
|
},
|
|
406
700
|
|
|
407
701
|
scheduled: async (event, env, executionCtx) => {
|
|
408
|
-
|
|
702
|
+
bindEnv(env);
|
|
409
703
|
setWaitUntil(executionCtx);
|
|
410
704
|
|
|
411
705
|
try {
|
|
@@ -422,7 +716,7 @@ export default {
|
|
|
422
716
|
},
|
|
423
717
|
|
|
424
718
|
queue: async (batch, env, executionCtx) => {
|
|
425
|
-
|
|
719
|
+
bindEnv(env);
|
|
426
720
|
setWaitUntil(executionCtx);
|
|
427
721
|
|
|
428
722
|
try {
|
|
@@ -444,9 +738,12 @@ export default {
|
|
|
444
738
|
};
|
|
445
739
|
`.trim();
|
|
446
740
|
|
|
741
|
+
const containerBlock =
|
|
742
|
+
containers.length > 0 ? `${containerDeclarations}\n\n` : "";
|
|
743
|
+
|
|
447
744
|
await this.fs.writeFile(
|
|
448
745
|
this.fs.join(root, distDir, "main.cloudflare.js"),
|
|
449
|
-
`${this.warningComment}\n${
|
|
746
|
+
`${this.warningComment}\n${containerBlock}${workerCode}`.trim(),
|
|
450
747
|
);
|
|
451
748
|
}
|
|
452
749
|
}
|
|
@@ -457,7 +754,16 @@ interface ContainerDescriptor {
|
|
|
457
754
|
image: string;
|
|
458
755
|
port: number;
|
|
459
756
|
sleepAfter: string;
|
|
460
|
-
|
|
757
|
+
/**
|
|
758
|
+
* Cloudflare Containers instance class.
|
|
759
|
+
*
|
|
760
|
+
* `dev` is the wrangler-pre-GA name; the platform accepts it but
|
|
761
|
+
* emits a deprecation warning telling you to use `lite`. We
|
|
762
|
+
* silently translate at write time (see `discoverContainers`
|
|
763
|
+
* default + `enhanceContainers` write) so older
|
|
764
|
+
* `$container({ instanceType: "dev" })` declarations keep working.
|
|
765
|
+
*/
|
|
766
|
+
instanceType: "dev" | "lite" | "basic" | "standard";
|
|
461
767
|
maxInstances: number;
|
|
462
768
|
envVars?: Record<string, string>;
|
|
463
769
|
}
|
|
@@ -73,10 +73,12 @@ export class BuildDockerTask extends BuildTask {
|
|
|
73
73
|
name: "generate deploy config (docker)",
|
|
74
74
|
handler: async () => {
|
|
75
75
|
const migrationsCopied = await this.copyMigrations(ctx.root, distDir);
|
|
76
|
+
const hasDeps = await this.hasRuntimeDeps(ctx.root, distDir);
|
|
76
77
|
await this.writeDockerfile(ctx.root, distDir, {
|
|
77
78
|
compile,
|
|
78
79
|
standard: { image: dockerFrom, command: dockerCommand },
|
|
79
80
|
hasMigrations: migrationsCopied,
|
|
81
|
+
hasDeps,
|
|
80
82
|
install: ctx.options.docker?.install ?? [],
|
|
81
83
|
});
|
|
82
84
|
},
|
|
@@ -211,6 +213,28 @@ export class BuildDockerTask extends BuildTask {
|
|
|
211
213
|
return false;
|
|
212
214
|
}
|
|
213
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Whether the produced `dist/package.json` declares any runtime
|
|
218
|
+
* dependencies. Alepha apps normally bundle everything into the
|
|
219
|
+
* server entry via Vite, leaving `dependencies: {}` — in which case
|
|
220
|
+
* the generated Dockerfile's `RUN npm install` is wasted work
|
|
221
|
+
* (and emits deprecation noise). Skip the line when empty.
|
|
222
|
+
*/
|
|
223
|
+
protected async hasRuntimeDeps(
|
|
224
|
+
root: string,
|
|
225
|
+
distDir: string,
|
|
226
|
+
): Promise<boolean> {
|
|
227
|
+
try {
|
|
228
|
+
const pkg = await this.fs.readJsonFile<{
|
|
229
|
+
dependencies?: Record<string, string>;
|
|
230
|
+
}>(this.fs.join(root, distDir, "package.json"));
|
|
231
|
+
return Object.keys(pkg.dependencies ?? {}).length > 0;
|
|
232
|
+
} catch {
|
|
233
|
+
// No package.json in dist/ → nothing to install.
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
214
238
|
protected async writeDockerfile(
|
|
215
239
|
root: string,
|
|
216
240
|
distDir: string,
|
|
@@ -218,6 +242,7 @@ export class BuildDockerTask extends BuildTask {
|
|
|
218
242
|
compile: ResolvedCompile | null;
|
|
219
243
|
standard: { image: string; command: string };
|
|
220
244
|
hasMigrations: boolean;
|
|
245
|
+
hasDeps: boolean;
|
|
221
246
|
install: string[];
|
|
222
247
|
},
|
|
223
248
|
): Promise<void> {
|
|
@@ -244,12 +269,18 @@ ENTRYPOINT ["/app/app"]
|
|
|
244
269
|
`;
|
|
245
270
|
} else {
|
|
246
271
|
const { image, command } = opts.standard;
|
|
272
|
+
// Skip `RUN <pm> install` when `dist/package.json` declares no
|
|
273
|
+
// runtime deps — Alepha apps normally bundle everything via Vite,
|
|
274
|
+
// making the install a no-op that just emits deprecation noise.
|
|
275
|
+
const baseInstallLine = opts.hasDeps
|
|
276
|
+
? `RUN ${command === "bun" ? "bun" : "npm"} install\n`
|
|
277
|
+
: "";
|
|
247
278
|
// Install requested packages locally (no --global). They land in
|
|
248
279
|
// `/app/node_modules/`, alongside the app's own deps. Use
|
|
249
280
|
// `--no-save` so we don't mutate the bundled package.json. Node
|
|
250
281
|
// module resolution walks up into `/app/node_modules/` when the
|
|
251
282
|
// workspace lives under `/app/workspace/<deploy-id>/`.
|
|
252
|
-
const
|
|
283
|
+
const extraInstallLine = opts.install.length
|
|
253
284
|
? `RUN npm install --no-save --no-fund --no-audit ${opts.install.join(" ")}\n`
|
|
254
285
|
: "";
|
|
255
286
|
dockerfile = `${header}FROM ${image}
|
|
@@ -257,8 +288,7 @@ WORKDIR /app
|
|
|
257
288
|
|
|
258
289
|
COPY . .
|
|
259
290
|
|
|
260
|
-
|
|
261
|
-
${installLine}
|
|
291
|
+
${baseInstallLine}${extraInstallLine}
|
|
262
292
|
ENV SERVER_HOST=0.0.0.0
|
|
263
293
|
|
|
264
294
|
CMD ["${command}", "index.js"]
|
|
@@ -2,6 +2,7 @@ import type { Alepha } from "alepha";
|
|
|
2
2
|
import type { RunnerMethod } from "alepha/command";
|
|
3
3
|
import type { BuildOptions } from "../atoms/buildOptions.ts";
|
|
4
4
|
import type { AppEntry } from "../providers/AppEntryProvider.ts";
|
|
5
|
+
import type { BuildManifest } from "./BuildCloudflareTask.ts";
|
|
5
6
|
|
|
6
7
|
export interface BuildTaskContext {
|
|
7
8
|
/**
|
|
@@ -43,6 +44,39 @@ export interface BuildTaskContext {
|
|
|
43
44
|
* Raw CLI flags passed through from the command.
|
|
44
45
|
* Tasks can read flags relevant to their domain.
|
|
45
46
|
*/
|
|
47
|
+
/**
|
|
48
|
+
* Build-time snapshot of primitive data, read from
|
|
49
|
+
* `dist/manifest.json`. Populated only in `--prebuilt` mode when a
|
|
50
|
+
* previous build's manifest is present — lets BuildCloudflareTask
|
|
51
|
+
* regenerate `wrangler.jsonc` without re-booting the workspace.
|
|
52
|
+
* `null` when introspection (`ctx.alepha`) is the source of truth.
|
|
53
|
+
*/
|
|
54
|
+
manifest: BuildManifest | null;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Resolved `platform({ default, environments, ... })` options from
|
|
58
|
+
* the workspace's `alepha.config.ts`. Populated by `BuildCommand`
|
|
59
|
+
* from the CLI's Alepha instance (where alepha.config.ts ran) —
|
|
60
|
+
* BuildCloudflareTask uses these to write the corresponding fields
|
|
61
|
+
* into `dist/manifest.json` so the deploy side doesn't need to
|
|
62
|
+
* re-load `alepha.config.ts`. `null` when no platform options were
|
|
63
|
+
* declared.
|
|
64
|
+
*/
|
|
65
|
+
platformOptions: {
|
|
66
|
+
default?: string;
|
|
67
|
+
tenancy?: "none" | "optional" | "required";
|
|
68
|
+
environments?: Record<
|
|
69
|
+
string,
|
|
70
|
+
{
|
|
71
|
+
adapter: "cloudflare" | "vercel";
|
|
72
|
+
domain?: string;
|
|
73
|
+
zone?: string;
|
|
74
|
+
jurisdiction?: "eu" | "fedramp";
|
|
75
|
+
accountId?: string;
|
|
76
|
+
}
|
|
77
|
+
>;
|
|
78
|
+
} | null;
|
|
79
|
+
|
|
46
80
|
flags?: {
|
|
47
81
|
image?: boolean | string;
|
|
48
82
|
/**
|