alepha 0.21.2 → 0.23.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 +282 -285
- 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 +217 -222
- 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 +1106 -1005
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +307 -64
- 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 +137 -143
- 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 +458 -249
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +372 -660
- 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 +20 -17
- package/dist/cli/i18n/index.d.ts.map +1 -1
- package/dist/cli/i18n/index.js +45 -11
- 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 +1472 -0
- package/dist/cli/platform-lib/index.d.ts.map +1 -0
- package/dist/cli/platform-lib/index.js +2660 -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 +20 -19
- 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 +25 -20
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +23 -0
- 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 -5
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +16 -15
- 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 +90 -11
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +147 -11
- 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 +193 -24
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +434 -222
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +249 -35
- 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 +92 -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 +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 +272 -173
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +1608 -15
- 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 +20 -7
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js +22 -3
- 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 +106 -73
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +44 -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 +59 -23
- 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/controllers/RealmController.ts +1 -0
- 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 +29 -0
- package/src/api/users/providers/RealmProvider.ts +15 -0
- package/src/api/users/schemas/realmConfigSchema.ts +14 -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/atoms/buildOptions.ts +0 -12
- package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
- package/src/cli/core/commands/build.ts +105 -37
- 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 -3
- 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 +382 -56
- package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
- package/src/cli/core/tasks/BuildPrerenderTask.ts +44 -7
- 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/i18n/__tests__/I18nCheckService.spec.ts +48 -0
- package/src/cli/i18n/services/I18nCheckService.ts +65 -11
- 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 +519 -190
- 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/mcp/__tests__/McpServerProvider.spec.ts +71 -0
- package/src/mcp/providers/McpServerProvider.ts +55 -0
- 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/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/services/FormModel.ts +57 -39
- package/src/react/i18n/__tests__/I18nProvider.spec.ts +89 -0
- package/src/react/i18n/__tests__/locale-routing.spec.ts +107 -0
- package/src/react/i18n/components/Translate.tsx +47 -0
- package/src/react/i18n/index.ts +2 -0
- package/src/react/i18n/providers/I18nProvider.ts +171 -12
- package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
- package/src/react/router/__tests__/$page.spec.tsx +3 -2
- package/src/react/router/__tests__/RouterLocaleProvider.spec.ts +127 -0
- package/src/react/router/__tests__/page-can.spec.ts +18 -13
- package/src/react/router/hooks/useQueryParams.ts +114 -14
- 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 +85 -4
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +18 -8
- package/src/react/router/providers/ReactPageProvider.ts +12 -1
- package/src/react/router/providers/ReactServerProvider.ts +96 -14
- 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/services/SchemaControl.ts +3 -4
- package/src/server/auth/__tests__/appleClientSecret.spec.ts +34 -0
- package/src/server/auth/__tests__/authFederationClient.spec.ts +40 -0
- package/src/server/auth/__tests__/federationAssertion.spec.ts +146 -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/federationAssertion.ts +74 -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 +4 -0
- package/src/server/auth/primitives/$authFederationBroker.ts +273 -0
- package/src/server/auth/primitives/$authFederationClient.ts +89 -0
- package/src/server/auth/providers/ServerAuthProvider.ts +18 -4
- package/src/server/cookies/__tests__/ServerCookiesProvider.spec.ts +70 -0
- package/src/server/cookies/providers/ServerCookiesProvider.ts +23 -3
- package/src/server/core/interfaces/ServerRequest.ts +8 -0
- package/src/server/core/primitives/$route.ts +27 -0
- 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/tasks/BuildSitemapTask.ts +0 -130
- 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
|
@@ -4,11 +4,18 @@ import { FileSystemProvider } from "alepha/system";
|
|
|
4
4
|
import { BuildTask, type BuildTaskContext } from "./BuildTask.ts";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Pre-render static pages defined in the Alepha application.
|
|
7
|
+
* Pre-render static pages and routes defined in the Alepha application.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* routes via `static.entries`
|
|
9
|
+
* Two passes, both writing into `dist/public`:
|
|
10
|
+
* - **pages** — every `$page` with `static: true` is rendered to an HTML file
|
|
11
|
+
* (supports parameterized routes via `static.entries`).
|
|
12
|
+
* - **routes** — every `static` route primitive (a `$route({ static: true })`
|
|
13
|
+
* or a `$sitemap`) is invoked in-process and its body written verbatim to
|
|
14
|
+
* `{path}` (e.g. `sitemap.xml`, `robots.txt`).
|
|
15
|
+
*
|
|
16
|
+
* Both passes read the primitive registry and call a method on the already
|
|
17
|
+
* created primitive instances — no provider is re-injected, so this works in
|
|
18
|
+
* the build's configured-but-not-started container.
|
|
12
19
|
*/
|
|
13
20
|
export class BuildPrerenderTask extends BuildTask {
|
|
14
21
|
protected readonly fs = $inject(FileSystemProvider);
|
|
@@ -22,7 +29,8 @@ export class BuildPrerenderTask extends BuildTask {
|
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
const pages = this.getStaticPages(ctx);
|
|
25
|
-
|
|
32
|
+
const routes = this.getStaticRoutePrimitives(ctx);
|
|
33
|
+
if (pages.length === 0 && routes.length === 0) {
|
|
26
34
|
return;
|
|
27
35
|
}
|
|
28
36
|
|
|
@@ -31,13 +39,18 @@ export class BuildPrerenderTask extends BuildTask {
|
|
|
31
39
|
const dist = this.fs.join(ctx.root, distDir, publicDir);
|
|
32
40
|
|
|
33
41
|
await ctx.run({
|
|
34
|
-
name: "pre-render
|
|
42
|
+
name: "pre-render",
|
|
35
43
|
handler: async () => {
|
|
36
44
|
// TODO: running configure here is a temporary workaround
|
|
37
45
|
if (!ctx.alepha.isConfigured()) {
|
|
38
46
|
await ctx.alepha.events.emit("configure", ctx.alepha);
|
|
39
47
|
}
|
|
40
|
-
|
|
48
|
+
if (pages.length > 0) {
|
|
49
|
+
await this.prerenderFromAlepha(pages, dist);
|
|
50
|
+
}
|
|
51
|
+
if (routes.length > 0) {
|
|
52
|
+
await this.prerenderRoutes(routes, dist);
|
|
53
|
+
}
|
|
41
54
|
},
|
|
42
55
|
});
|
|
43
56
|
}
|
|
@@ -50,6 +63,18 @@ export class BuildPrerenderTask extends BuildTask {
|
|
|
50
63
|
});
|
|
51
64
|
}
|
|
52
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Static route primitives to snapshot: `$route({ static: true })` and every
|
|
68
|
+
* `$sitemap`. Both expose an async `prerender(): { path, body }`.
|
|
69
|
+
*/
|
|
70
|
+
protected getStaticRoutePrimitives(ctx: BuildTaskContext): any[] {
|
|
71
|
+
const routes = (ctx.alepha.primitives("route") as any[]).filter(
|
|
72
|
+
(route) => route.options?.static === true,
|
|
73
|
+
);
|
|
74
|
+
const sitemaps = ctx.alepha.primitives("sitemap") as any[];
|
|
75
|
+
return [...routes, ...sitemaps];
|
|
76
|
+
}
|
|
77
|
+
|
|
53
78
|
protected async prerenderFromAlepha(
|
|
54
79
|
pages: any[],
|
|
55
80
|
dist: string,
|
|
@@ -77,6 +102,18 @@ export class BuildPrerenderTask extends BuildTask {
|
|
|
77
102
|
return count;
|
|
78
103
|
}
|
|
79
104
|
|
|
105
|
+
protected async prerenderRoutes(
|
|
106
|
+
primitives: any[],
|
|
107
|
+
dist: string,
|
|
108
|
+
): Promise<void> {
|
|
109
|
+
for (const primitive of primitives) {
|
|
110
|
+
const { path, body } = await primitive.prerender();
|
|
111
|
+
const filepath = this.fs.join(dist, path);
|
|
112
|
+
await this.fs.mkdir(dirname(filepath));
|
|
113
|
+
await this.fs.writeFile(filepath, body);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
80
117
|
protected async renderFile(
|
|
81
118
|
page: any,
|
|
82
119
|
options: any,
|
|
@@ -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
|
/**
|
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
export interface ApiIndexTsOptions {
|
|
2
2
|
appName?: string;
|
|
3
|
-
/**
|
|
4
|
-
* Include `AlephaApiUsers` (realms, sessions, registration, identities,
|
|
5
|
-
* password reset, email verification, admin endpoints) plus the local
|
|
6
|
-
* `RealmProvider` that declares `$realm({ ... })`.
|
|
7
|
-
*/
|
|
8
|
-
saas?: boolean;
|
|
9
3
|
}
|
|
10
4
|
|
|
11
5
|
export const apiIndexTs = (options: ApiIndexTsOptions = {}) => {
|
|
12
|
-
const { appName = "app"
|
|
13
|
-
|
|
14
|
-
if (saas) {
|
|
15
|
-
return `
|
|
16
|
-
import { $module } from "alepha";
|
|
17
|
-
import { AlephaApiUsers } from "alepha/api/users";
|
|
18
|
-
import { HelloController } from "./controllers/HelloController.ts";
|
|
19
|
-
import { RealmProvider } from "./providers/RealmProvider.ts";
|
|
20
|
-
|
|
21
|
-
export const ApiModule = $module({
|
|
22
|
-
name: "${appName}.api",
|
|
23
|
-
services: [HelloController, RealmProvider],
|
|
24
|
-
imports: [AlephaApiUsers],
|
|
25
|
-
});
|
|
26
|
-
`.trim();
|
|
27
|
-
}
|
|
6
|
+
const { appName = "app" } = options;
|
|
28
7
|
|
|
29
8
|
return `
|
|
30
9
|
import { $module } from "alepha";
|
|
@@ -11,7 +11,6 @@ export const mainCss = (opts: { tailwind?: boolean } = {}) => {
|
|
|
11
11
|
*
|
|
12
12
|
* Options:
|
|
13
13
|
* - Tailwind CSS: Use \`alepha init --tailwind\` to add Tailwind CSS
|
|
14
|
-
* - shadcn/ui: Use \`alepha init --shadcn\` to add shadcn/ui setup
|
|
15
14
|
* - Raw CSS: Write your own styles below
|
|
16
15
|
*/
|
|
17
16
|
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
export interface WebAppRouterOptions {
|
|
2
2
|
api?: boolean;
|
|
3
|
-
saas?: boolean;
|
|
4
3
|
}
|
|
5
4
|
|
|
6
5
|
export const webAppRouterTs = (options: WebAppRouterOptions) => {
|
|
7
|
-
if (options.saas) {
|
|
8
|
-
return saasAppRouterTs();
|
|
9
|
-
}
|
|
10
|
-
return basicAppRouterTs(options);
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const basicAppRouterTs = (options: WebAppRouterOptions) => {
|
|
14
6
|
const imports: string[] = ['import { $page } from "alepha/react/router";'];
|
|
15
7
|
const classMembers: string[] = [];
|
|
16
8
|
|
|
@@ -39,94 +31,3 @@ export class AppRouter {
|
|
|
39
31
|
${classMembers.join("\n\n")}
|
|
40
32
|
}`;
|
|
41
33
|
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* SaaS router wires three trees onto the app:
|
|
45
|
-
* / → Home
|
|
46
|
-
* /auth/* → AuthLayout + login / register / reset / verify
|
|
47
|
-
* /admin/* → AdminLayout + users / sessions / api-keys / parameters / audits
|
|
48
|
-
*
|
|
49
|
-
* Each auth page resolves the realm config from its loader, so the registry
|
|
50
|
-
* components render with everything they need on first paint.
|
|
51
|
-
*/
|
|
52
|
-
const saasAppRouterTs =
|
|
53
|
-
() => `import type { RealmController } from "alepha/api/users";
|
|
54
|
-
import { $page, NotFound } from "alepha/react/router";
|
|
55
|
-
import { $secure } from "alepha/security";
|
|
56
|
-
import { $client } from "alepha/server/links";
|
|
57
|
-
import type { HelloController } from "../api/controllers/HelloController.ts";
|
|
58
|
-
|
|
59
|
-
export class AppRouter {
|
|
60
|
-
protected readonly api = $client<HelloController>();
|
|
61
|
-
protected readonly realmApi = $client<RealmController>();
|
|
62
|
-
|
|
63
|
-
home = $page({
|
|
64
|
-
path: "/",
|
|
65
|
-
lazy: () => import("./components/Home.tsx"),
|
|
66
|
-
loader: () => this.api.hello(),
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// ── /auth — login, register, reset, verify ─────────────────────────────
|
|
70
|
-
authLayout = $page({
|
|
71
|
-
path: "/auth",
|
|
72
|
-
lazy: () => import("./components/auth/AuthLayout.tsx"),
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
login = $page({
|
|
76
|
-
parent: this.authLayout,
|
|
77
|
-
path: "/login",
|
|
78
|
-
name: "login",
|
|
79
|
-
head: { title: "Sign in" },
|
|
80
|
-
lazy: () => import("./components/auth/Login.tsx"),
|
|
81
|
-
loader: async () => ({ realmConfig: await this.realmApi.getRealmConfig() }),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
register = $page({
|
|
85
|
-
parent: this.authLayout,
|
|
86
|
-
path: "/register",
|
|
87
|
-
name: "register",
|
|
88
|
-
head: { title: "Sign up" },
|
|
89
|
-
lazy: () => import("./components/auth/Register.tsx"),
|
|
90
|
-
loader: async () => ({ realmConfig: await this.realmApi.getRealmConfig() }),
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
resetPassword = $page({
|
|
94
|
-
parent: this.authLayout,
|
|
95
|
-
path: "/reset-password",
|
|
96
|
-
head: { title: "Reset password" },
|
|
97
|
-
lazy: () => import("./components/auth/ResetPassword.tsx"),
|
|
98
|
-
loader: async () => ({ realmConfig: await this.realmApi.getRealmConfig() }),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
verifyEmail = $page({
|
|
102
|
-
parent: this.authLayout,
|
|
103
|
-
path: "/verify-email",
|
|
104
|
-
head: { title: "Verify email" },
|
|
105
|
-
lazy: () => import("./components/auth/VerifyEmail.tsx"),
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// ── /admin — gated by 'admin:ui' permission, declared in RealmProvider.
|
|
109
|
-
// Children inherit the gate via the parent chain.
|
|
110
|
-
adminLayout = $page({
|
|
111
|
-
path: "/admin",
|
|
112
|
-
use: [$secure({ permissions: ["admin:ui"] })],
|
|
113
|
-
lazy: () => import("./components/admin/AdminLayout.tsx"),
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
adminUsers = $page({
|
|
117
|
-
parent: this.adminLayout,
|
|
118
|
-
path: "/users",
|
|
119
|
-
head: { title: "Users" },
|
|
120
|
-
lazy: () => import("./components/admin/Users.tsx"),
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
adminSessions = $page({
|
|
124
|
-
parent: this.adminLayout,
|
|
125
|
-
path: "/sessions",
|
|
126
|
-
head: { title: "Sessions" },
|
|
127
|
-
lazy: () => import("./components/admin/Sessions.tsx"),
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
notFound = $page({ path: "/*", component: NotFound });
|
|
131
|
-
}
|
|
132
|
-
`;
|
|
@@ -1,30 +1,9 @@
|
|
|
1
1
|
export interface WebIndexTsOptions {
|
|
2
2
|
appName?: string;
|
|
3
|
-
/**
|
|
4
|
-
* SaaS bundle: auth pages need `useAuth()` (ReactAuth) which lives in the
|
|
5
|
-
* `alepha.react.auth` module. Importing it here registers ReactAuth in the
|
|
6
|
-
* container so the auth-* registry components can inject it.
|
|
7
|
-
*/
|
|
8
|
-
saas?: boolean;
|
|
9
3
|
}
|
|
10
4
|
|
|
11
5
|
export const webIndexTs = (options: WebIndexTsOptions = {}) => {
|
|
12
|
-
const { appName = "app"
|
|
13
|
-
|
|
14
|
-
if (saas) {
|
|
15
|
-
return `
|
|
16
|
-
import { $module } from "alepha";
|
|
17
|
-
import { AlephaReactAuth } from "alepha/react/auth";
|
|
18
|
-
import { AlephaReactI18n } from "alepha/react/i18n";
|
|
19
|
-
import { AppRouter } from "./AppRouter.ts";
|
|
20
|
-
|
|
21
|
-
export const WebModule = $module({
|
|
22
|
-
name: "${appName}.web",
|
|
23
|
-
services: [AppRouter],
|
|
24
|
-
imports: [AlephaReactAuth, AlephaReactI18n],
|
|
25
|
-
});
|
|
26
|
-
`.trim();
|
|
27
|
-
}
|
|
6
|
+
const { appName = "app" } = options;
|
|
28
7
|
|
|
29
8
|
return `
|
|
30
9
|
import { $module } from "alepha";
|
|
@@ -109,6 +109,54 @@ ${body}
|
|
|
109
109
|
expect(result.unused).toEqual(["home.title"]);
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
+
it("extracts keys from lazily-imported per-language files", async () => {
|
|
113
|
+
await env.fs.mkdir(`${ROOT}/src/web/i18n`, { recursive: true });
|
|
114
|
+
// Marker file declares `$dictionary` but the keys live in split,
|
|
115
|
+
// markerless per-language files referenced via `lazy: () => import(...)`.
|
|
116
|
+
// A sibling `$page` lazy import must NOT be mistaken for a key file.
|
|
117
|
+
await env.fs.writeFile(
|
|
118
|
+
`${ROOT}/src/web/Router.ts`,
|
|
119
|
+
`import { $dictionary } from "alepha/react/i18n";
|
|
120
|
+
export class Router {
|
|
121
|
+
fr = $dictionary({ lazy: () => import("./i18n/fr.ts"), lang: "fr" });
|
|
122
|
+
en = $dictionary({ lazy: () => import("./i18n/en.ts"), lang: "en" });
|
|
123
|
+
page = $page({ lazy: () => import("./Home.tsx") });
|
|
124
|
+
}
|
|
125
|
+
`,
|
|
126
|
+
);
|
|
127
|
+
await env.fs.writeFile(
|
|
128
|
+
`${ROOT}/src/web/i18n/fr.ts`,
|
|
129
|
+
`export default { "home.title": "Accueil", "home.unused": "Rien" };`,
|
|
130
|
+
);
|
|
131
|
+
await env.fs.writeFile(
|
|
132
|
+
`${ROOT}/src/web/i18n/en.ts`,
|
|
133
|
+
`export default { "home.title": "Home", "home.unused": "Nothing" };`,
|
|
134
|
+
);
|
|
135
|
+
// The only reference — `home.unused` is dead in both languages. The
|
|
136
|
+
// `"home.title": "…"` lines in the sibling language file must not count
|
|
137
|
+
// as references (key files are excluded from the usage corpus).
|
|
138
|
+
await env.fs.writeFile(
|
|
139
|
+
`${ROOT}/src/web/Home.tsx`,
|
|
140
|
+
`export const Home = () => tr("home.title");`,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const result = await env.service.check({
|
|
144
|
+
root: ROOT,
|
|
145
|
+
scan: ["src"],
|
|
146
|
+
dynamicPrefixes: [],
|
|
147
|
+
exclude: [],
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
expect(result.totalKeys).toBe(2);
|
|
151
|
+
expect(result.unused).toEqual(["home.unused"]);
|
|
152
|
+
// The resolved language file is treated as a dictionary; the sibling
|
|
153
|
+
// `$page` lazy import is not (it contributed no keys and stays in the
|
|
154
|
+
// usage corpus). `en.ts` is also a dictionary file but adds no *new*
|
|
155
|
+
// keys, so only the first contributor is listed.
|
|
156
|
+
expect(result.dictionaryFiles).toContain(`${ROOT}/src/web/i18n/fr.ts`);
|
|
157
|
+
expect(result.dictionaryFiles).not.toContain(`${ROOT}/src/web/Home.tsx`);
|
|
158
|
+
});
|
|
159
|
+
|
|
112
160
|
it("returns totalKeys=0 when no dictionary is found", async () => {
|
|
113
161
|
await env.fs.mkdir(`${ROOT}/src`, { recursive: true });
|
|
114
162
|
await env.fs.writeFile(
|
|
@@ -35,6 +35,22 @@ const KEY_DECLARATION_RE = /"([\w-]+(?:\.[\w-]+)+)"\s*:/g;
|
|
|
35
35
|
*/
|
|
36
36
|
const DICTIONARY_MARKER = "$dictionary";
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Captures the module specifier of a lazily-imported dictionary, i.e. the
|
|
40
|
+
* `"./fr.ts"` in `$dictionary({ lazy: () => import("./fr.ts") })`. Apps
|
|
41
|
+
* commonly split each language into its own file so a session only ships the
|
|
42
|
+
* active locale — those key files carry no `$dictionary` marker, so without
|
|
43
|
+
* this the keys would be invisible to the check.
|
|
44
|
+
*
|
|
45
|
+
* `[^{}]*?` keeps the match inside the `$dictionary` call's own object literal
|
|
46
|
+
* (it stops at the first brace), so unrelated lazy imports in the same file —
|
|
47
|
+
* e.g. a sibling `$page({ lazy: () => import("./Page.tsx") })` or a
|
|
48
|
+
* `$dictionary` whose `lazy` returns an inline `({ default: {…} })` object —
|
|
49
|
+
* are never mistaken for dictionary key files.
|
|
50
|
+
*/
|
|
51
|
+
const DICTIONARY_LAZY_IMPORT_RE =
|
|
52
|
+
/\$dictionary\s*\(\s*\{[^{}]*?import\s*\(\s*["']([^"']+)["']/g;
|
|
53
|
+
|
|
38
54
|
export interface I18nCheckOptions {
|
|
39
55
|
root: string;
|
|
40
56
|
scan: string[];
|
|
@@ -62,11 +78,11 @@ export class I18nCheckService {
|
|
|
62
78
|
* Find unused translation keys.
|
|
63
79
|
*
|
|
64
80
|
* Discovery is fully static: we walk `scan` dirs, identify files
|
|
65
|
-
* that import `$dictionary` (matched via the literal substring)
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* exempted.
|
|
81
|
+
* that import `$dictionary` (matched via the literal substring) plus
|
|
82
|
+
* any per-language files they lazily `import(...)`, extract every
|
|
83
|
+
* `"a.b.c": ...` property key declared across them, then grep the
|
|
84
|
+
* remaining source files for a quoted-literal occurrence of each key.
|
|
85
|
+
* Anything matching a `dynamicPrefixes` entry is exempted.
|
|
70
86
|
*/
|
|
71
87
|
async check(options: I18nCheckOptions): Promise<I18nCheckResult> {
|
|
72
88
|
const { root, scan, dynamicPrefixes, exclude } = options;
|
|
@@ -91,14 +107,31 @@ export class I18nCheckService {
|
|
|
91
107
|
}
|
|
92
108
|
}
|
|
93
109
|
|
|
94
|
-
const dictionaryFiles: string[] = [];
|
|
95
|
-
const allKeys = new Set<string>();
|
|
96
110
|
const fileContents = new Map<string, string>();
|
|
97
|
-
|
|
98
111
|
for (const file of allFiles) {
|
|
99
|
-
|
|
100
|
-
|
|
112
|
+
fileContents.set(file, (await this.fs.readFile(file)).toString("utf8"));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// A file is a dictionary if it declares `$dictionary` OR it is the target
|
|
116
|
+
// of a `$dictionary({ lazy: () => import("…") })` (the split per-language
|
|
117
|
+
// key files, which carry no marker of their own). Resolving the lazy
|
|
118
|
+
// targets first lets their keys be extracted below and keeps them out of
|
|
119
|
+
// the usage corpus (their `"key": "value"` lines aren't references).
|
|
120
|
+
const dictionarySet = new Set<string>();
|
|
121
|
+
for (const [file, text] of fileContents) {
|
|
101
122
|
if (!text.includes(DICTIONARY_MARKER)) continue;
|
|
123
|
+
dictionarySet.add(file);
|
|
124
|
+
for (const m of text.matchAll(DICTIONARY_LAZY_IMPORT_RE)) {
|
|
125
|
+
const target = this.resolveImport(file, m[1], fileContents);
|
|
126
|
+
if (target) dictionarySet.add(target);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const dictionaryFiles: string[] = [];
|
|
131
|
+
const allKeys = new Set<string>();
|
|
132
|
+
for (const file of dictionarySet) {
|
|
133
|
+
const text = fileContents.get(file);
|
|
134
|
+
if (!text) continue;
|
|
102
135
|
const before = allKeys.size;
|
|
103
136
|
for (const m of text.matchAll(KEY_DECLARATION_RE)) {
|
|
104
137
|
allKeys.add(m[1]);
|
|
@@ -108,7 +141,6 @@ export class I18nCheckService {
|
|
|
108
141
|
|
|
109
142
|
// Concatenate every non-dictionary file into one corpus so each
|
|
110
143
|
// key is tested with a single regex run rather than O(files × keys).
|
|
111
|
-
const dictionarySet = new Set(dictionaryFiles);
|
|
112
144
|
const corpusParts: string[] = [];
|
|
113
145
|
let scannedFiles = 0;
|
|
114
146
|
for (const [file, text] of fileContents) {
|
|
@@ -141,4 +173,26 @@ export class I18nCheckService {
|
|
|
141
173
|
unused: unused.sort(),
|
|
142
174
|
};
|
|
143
175
|
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Resolve a relative `import("…")` specifier from `fromFile` to an absolute
|
|
179
|
+
* path that was actually scanned. Returns `undefined` for bare/package
|
|
180
|
+
* specifiers or targets outside the scan set. Extensionless specifiers are
|
|
181
|
+
* probed against each supported source extension.
|
|
182
|
+
*/
|
|
183
|
+
protected resolveImport(
|
|
184
|
+
fromFile: string,
|
|
185
|
+
spec: string,
|
|
186
|
+
files: Map<string, string>,
|
|
187
|
+
): string | undefined {
|
|
188
|
+
if (!spec.startsWith(".")) return undefined;
|
|
189
|
+
// `join(file, "..", spec)` drops the filename then applies the relative
|
|
190
|
+
// specifier — i.e. resolves against `fromFile`'s directory.
|
|
191
|
+
const base = this.fs.join(fromFile, "..", spec);
|
|
192
|
+
if (files.has(base)) return base;
|
|
193
|
+
for (const ext of SCAN_EXTS) {
|
|
194
|
+
if (files.has(base + ext)) return base + ext;
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
144
198
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Alepha } from "alepha";
|
|
2
|
+
import {
|
|
3
|
+
MemorySecretStore,
|
|
4
|
+
platformOptions,
|
|
5
|
+
type SecretStoreProvider,
|
|
6
|
+
} from "alepha/cli/platform-lib";
|
|
2
7
|
import { CliProvider } from "alepha/command";
|
|
3
8
|
import { FileSystemProvider, MemoryFileSystemProvider } from "alepha/system";
|
|
4
9
|
import { describe, test } from "vitest";
|
|
5
|
-
import { platformOptions } from "../atoms/platformOptions.ts";
|
|
6
10
|
import { SecretsCommand } from "../commands/SecretsCommand.ts";
|
|
7
|
-
import { MemorySecretStore } from "../providers/MemorySecretStore.ts";
|
|
8
|
-
import type { SecretStoreProvider } from "../providers/SecretStoreProvider.ts";
|
|
9
11
|
|
|
10
12
|
class TestSecretsCommand extends SecretsCommand {
|
|
11
13
|
public readonly testList = this.list;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { $inject, $state, AlephaError, t } from "alepha";
|
|
2
|
+
import {
|
|
3
|
+
GitHubSecretStore,
|
|
4
|
+
NamingService,
|
|
5
|
+
PlatformInspector,
|
|
6
|
+
platformOptions,
|
|
7
|
+
SecretFilterService,
|
|
8
|
+
type SecretStoreProvider,
|
|
9
|
+
} from "alepha/cli/platform-lib";
|
|
2
10
|
import { $command, EnvUtils } from "alepha/command";
|
|
3
11
|
import { $logger, ConsoleColorProvider } from "alepha/logger";
|
|
4
|
-
import { platformOptions } from "../atoms/platformOptions.ts";
|
|
5
|
-
import { GitHubSecretStore } from "../providers/GitHubSecretStore.ts";
|
|
6
|
-
import type { SecretStoreProvider } from "../providers/SecretStoreProvider.ts";
|
|
7
|
-
import { NamingService } from "../services/NamingService.ts";
|
|
8
|
-
import { PlatformInspector } from "../services/PlatformInspector.ts";
|
|
9
|
-
import { SecretFilterService } from "../services/SecretFilterService.ts";
|
|
10
12
|
|
|
11
13
|
export class SecretsCommand {
|
|
12
14
|
protected readonly log = $logger();
|