alepha 0.20.3 → 0.20.4
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/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/jobs/index.d.ts +14 -14
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/keys/index.d.ts +4 -4
- package/dist/api/organizations/index.d.ts.map +1 -1
- package/dist/api/parameters/index.d.ts +8 -3
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +20 -4
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/payments/index.d.ts.map +1 -1
- package/dist/api/users/index.browser.js +6 -0
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +5037 -139
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +58 -10
- package/dist/api/users/index.js.map +1 -1
- package/dist/bucket/index.d.ts +77 -107
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +148 -4
- package/dist/bucket/index.js.map +1 -1
- package/dist/bucket/index.workerd.js +7 -1
- package/dist/bucket/index.workerd.js.map +1 -1
- package/dist/cache/core/index.d.ts +26 -0
- package/dist/cache/core/index.d.ts.map +1 -1
- package/dist/cache/core/index.js +11 -1
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cache/core/index.workerd.js +11 -1
- package/dist/cache/core/index.workerd.js.map +1 -1
- package/dist/cli/config/index.d.ts +7 -5
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js +2 -3
- package/dist/cli/config/index.js.map +1 -1
- package/dist/cli/core/index.d.ts +420 -13
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +22 -511
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/devtools/index.d.ts +4 -8
- package/dist/cli/devtools/index.d.ts.map +1 -1
- package/dist/cli/devtools/index.js +13 -15
- package/dist/cli/devtools/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +10 -13
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +18 -15
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +10 -13
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js +16 -13
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/core/index.browser.js +27 -3
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +6 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +27 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +27 -3
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +27 -3
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/datetime/index.d.ts +69 -10
- package/dist/datetime/index.d.ts.map +1 -1
- package/dist/datetime/index.js +135 -13
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/smtp/index.js +10636 -2
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/fake/index.d.ts +8085 -4
- package/dist/fake/index.d.ts.map +1 -1
- package/dist/fake/index.js +33554 -3
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +30 -2
- package/dist/lock/core/index.d.ts.map +1 -1
- package/dist/lock/core/index.js +35 -12
- package/dist/lock/core/index.js.map +1 -1
- package/dist/mcp/index.d.ts +238 -31
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +198 -71
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +1 -1
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +4 -3
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +4877 -9
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +4 -3
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.d.ts +608 -1
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/react/core/index.d.ts +102 -1
- package/dist/react/core/index.d.ts.map +1 -1
- package/dist/react/core/index.js +65 -1
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +6 -0
- package/dist/react/form/index.d.ts.map +1 -1
- package/dist/react/form/index.js +7 -7
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +7 -1
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +6 -0
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/router/index.browser.js +20 -2
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +36 -4
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +20 -2
- package/dist/react/router/index.js.map +1 -1
- package/dist/react/testing/chunk-6Ep1yQYe.js +16 -0
- package/dist/react/testing/index.d.ts +411 -1
- package/dist/react/testing/index.d.ts.map +1 -1
- package/dist/react/testing/index.js +12293 -13
- package/dist/react/testing/index.js.map +1 -1
- package/dist/react/ui/index.d.ts +195 -1
- package/dist/react/ui/index.d.ts.map +1 -1
- package/dist/react/ui/index.js +61 -1
- package/dist/react/ui/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +84 -3
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +390 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/index.workerd.js +390 -1
- package/dist/scheduler/index.workerd.js.map +1 -1
- package/dist/security/index.d.ts +325 -2
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1361 -2
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +1054 -1
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +1223 -1
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/core/index.browser.js +10 -3
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +28 -5
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +514 -1
- package/dist/server/metrics/index.d.ts.map +1 -1
- package/dist/server/metrics/index.js +4374 -4
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +3 -4
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/websocket/index.browser.js +11 -5
- package/dist/websocket/index.browser.js.map +1 -1
- package/dist/websocket/index.d.ts +3 -1
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js +21 -6
- package/dist/websocket/index.js.map +1 -1
- package/package.json +671 -263
- package/src/api/parameters/services/ParameterProvider.ts +21 -4
- package/src/api/users/__tests__/SessionService.spec.ts +99 -0
- package/src/api/users/__tests__/UserJobs.spec.ts +67 -0
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +15 -0
- package/src/api/users/entities/sessions.ts +6 -0
- package/src/api/users/jobs/UserJobs.ts +44 -17
- package/src/api/users/providers/RealmProvider.ts +4 -0
- package/src/api/users/services/SessionService.ts +27 -0
- package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +74 -0
- package/src/bucket/index.ts +19 -2
- package/src/bucket/primitives/$bucket.ts +9 -1
- package/src/bucket/providers/CloudflareR2Provider.ts +2 -137
- package/src/bucket/providers/NodeS3BucketProvider.ts +218 -0
- package/src/cache/core/index.ts +29 -0
- package/src/cache/core/primitives/$cache.ts +14 -1
- package/src/cli/config/defineConfig.ts +13 -15
- package/src/cli/core/__tests__/init.spec.ts +6 -7
- package/src/cli/core/services/ProjectScaffolder.ts +18 -14
- package/src/cli/core/tasks/BuildCloudflareTask.ts +5 -0
- package/src/cli/core/templates/agentMd.ts +2 -10
- package/src/cli/core/templates/saasAdminLayoutTsx.ts +3 -3
- package/src/cli/devtools/index.ts +12 -26
- package/src/cli/platform/index.ts +15 -24
- package/src/cli/vendor/atoms/vendorOptions.ts +1 -1
- package/src/cli/vendor/index.ts +14 -23
- package/src/core/Alepha.ts +11 -1
- package/src/core/helpers/ref.ts +18 -0
- package/src/core/index.shared.ts +1 -0
- package/src/core/providers/SchemaValidator.ts +9 -1
- package/src/core/providers/TypeProvider.ts +1 -2
- package/src/datetime/REFACTORING.md +118 -0
- package/src/datetime/providers/DateTimeProvider.ts +203 -24
- package/src/lock/core/index.ts +31 -0
- package/src/lock/core/primitives/$lock.ts +14 -1
- package/src/mcp/__tests__/jsonrpc.spec.ts +1 -1
- package/src/mcp/helpers/jsonrpc.ts +26 -1
- package/src/mcp/index.ts +10 -5
- package/src/mcp/interfaces/McpTypes.ts +83 -6
- package/src/mcp/primitives/$prompt.ts +18 -1
- package/src/mcp/primitives/$resource.ts +18 -1
- package/src/mcp/primitives/$tool.ts +83 -7
- package/src/mcp/providers/McpServerProvider.ts +74 -16
- package/src/mcp/transports/StreamableHttpMcpTransport.ts +226 -0
- package/src/orm/REFACTORING.md +330 -0
- package/src/orm/core/primitives/$transactional.ts +11 -0
- package/src/orm/core/schemas/updateSchema.ts +1 -1
- package/src/orm/core/services/PgRelationManager.ts +4 -2
- package/src/react/core/__tests__/useQuery.browser.spec.tsx +86 -0
- package/src/react/core/hooks/useQuery.ts +153 -0
- package/src/react/core/index.ts +1 -0
- package/src/react/form/services/FormModel.ts +15 -6
- package/src/react/form/services/parseField.ts +8 -0
- package/src/react/i18n/providers/I18nProvider.ts +8 -2
- package/src/react/router/__tests__/$page.spec.tsx +0 -16
- package/src/react/router/__tests__/ssr.spec.tsx +339 -0
- package/src/react/router/primitives/$page.ts +28 -4
- package/src/react/router/providers/ReactPageProvider.ts +27 -9
- package/src/react/ui/atoms/uiThemeListAtom.ts +36 -0
- package/src/react/ui/index.ts +6 -0
- package/src/react/ui/services/SchemaControl.ts +209 -0
- package/src/security/primitives/$issuer.ts +6 -3
- package/src/server/core/__tests__/ServerRouterProvider-serializationError.spec.ts +75 -0
- package/src/server/core/__tests__/ServerRouterProvider-validationError.spec.ts +306 -0
- package/src/server/core/errors/ValidationError.ts +13 -1
- package/src/server/core/primitives/$action.ts +16 -5
- package/src/server/core/providers/ServerRouterProvider.ts +26 -4
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +5 -7
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +10 -4
- package/src/websocket/services/WebSocketClient.ts +11 -5
- package/src/mcp/transports/SseMcpTransport.ts +0 -182
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/cli/platform/providers/PlatformCacheProvider.ts","../../../src/cli/platform/schemas/cloudflare.ts","../../../src/cli/platform/services/WranglerApi.ts","../../../src/cli/platform/services/CloudflareApi.ts","../../../src/cli/platform/adapters/PlatformAdapter.ts","../../../src/cli/platform/adapters/CloudflareAdapter.ts","../../../src/cli/platform/schemas/vercel.ts","../../../src/cli/platform/services/VercelCli.ts","../../../src/cli/platform/services/VercelApi.ts","../../../src/cli/platform/adapters/VercelAdapter.ts","../../../src/cli/platform/atoms/platformOptions.ts","../../../src/cli/platform/services/NamingService.ts","../../../src/cli/platform/services/PlatformInspector.ts","../../../src/cli/platform/hooks/PlatformHook.ts","../../../src/cli/platform/services/PlatformOrchestrator.ts","../../../src/cli/platform/providers/GitHubSecretStore.ts","../../../src/cli/platform/services/SecretFilterService.ts","../../../src/cli/platform/commands/SecretsCommand.ts","../../../src/cli/platform/commands/platform.ts","../../../src/cli/platform/providers/MemorySecretStore.ts","../../../src/cli/platform/providers/SecretStoreProvider.ts","../../../src/cli/platform/schemas/platform.ts","../../../src/cli/platform/index.ts"],"sourcesContent":["import { $inject } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { FileSystemProvider } from \"alepha/system\";\n\ninterface PlatformCache {\n [adapter: string]: {\n lastLoginCheck: number;\n accountId?: string;\n };\n}\n\n/**\n * Caches cloud provider login state to avoid slow auth checks.\n *\n * Stored in node_modules/.alepha/platform.json (gitignored, project-scoped).\n * TTL: 4 hours.\n */\nexport class PlatformCacheProvider {\n protected static readonly TTL_MS = 4 * 60 * 60 * 1000;\n\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly dateTime = $inject(DateTimeProvider);\n\n protected cachePath(root: string): string {\n return this.fs.join(root, \"node_modules\", \".alepha\", \"platform.json\");\n }\n\n public async isLoginFresh(root: string, adapter: string): Promise<boolean> {\n const cache = await this.readCache(root);\n const entry = cache[adapter];\n if (!entry) {\n return false;\n }\n const age = this.dateTime.nowMillis() - entry.lastLoginCheck;\n return age < PlatformCacheProvider.TTL_MS;\n }\n\n public async getAccountId(\n root: string,\n adapter: string,\n ): Promise<string | undefined> {\n const cache = await this.readCache(root);\n return cache[adapter]?.accountId;\n }\n\n public async recordLogin(\n root: string,\n adapter: string,\n accountId?: string,\n ): Promise<void> {\n const cache = await this.readCache(root);\n cache[adapter] = {\n lastLoginCheck: this.dateTime.nowMillis(),\n accountId,\n };\n await this.writeCache(root, cache);\n }\n\n protected async readCache(root: string): Promise<PlatformCache> {\n const path = this.cachePath(root);\n try {\n return await this.fs.readJsonFile<PlatformCache>(path);\n } catch {\n return {};\n }\n }\n\n protected async writeCache(\n root: string,\n cache: PlatformCache,\n ): Promise<void> {\n const path = this.cachePath(root);\n const lastSlash = path.lastIndexOf(\"/\");\n const dir = lastSlash > 0 ? path.slice(0, lastSlash) : path;\n await this.fs.mkdir(dir, { recursive: true }).catch(() => null);\n await this.fs.writeFile(path, JSON.stringify(cache, null, 2));\n }\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\n// ---------------------------------------------------------------------------\n// Account\n// ---------------------------------------------------------------------------\n\nexport const cloudflareAccountSchema = t.object({\n id: t.string(),\n name: t.string(),\n});\n\nexport type CloudflareAccount = Static<typeof cloudflareAccountSchema>;\n\n// ---------------------------------------------------------------------------\n// D1\n// ---------------------------------------------------------------------------\n\nexport const cloudflareD1Schema = t.object({\n uuid: t.string(),\n name: t.string(),\n});\n\nexport type CloudflareD1 = Static<typeof cloudflareD1Schema>;\n\n// ---------------------------------------------------------------------------\n// KV\n// ---------------------------------------------------------------------------\n\nexport const cloudflareKVSchema = t.object({\n id: t.string(),\n title: t.string(),\n});\n\nexport type CloudflareKV = Static<typeof cloudflareKVSchema>;\n\n// ---------------------------------------------------------------------------\n// R2\n// ---------------------------------------------------------------------------\n\nexport const cloudflareR2Schema = t.object({\n name: t.string(),\n creation_date: t.optional(t.string()),\n});\n\nexport type CloudflareR2 = Static<typeof cloudflareR2Schema>;\n\nexport const cloudflareR2ListSchema = t.object({\n buckets: t.array(cloudflareR2Schema),\n});\n\n// ---------------------------------------------------------------------------\n// Queue\n// ---------------------------------------------------------------------------\n\nexport const cloudflareQueueSchema = t.object({\n queue_id: t.string(),\n queue_name: t.string(),\n});\n\nexport type CloudflareQueue = Static<typeof cloudflareQueueSchema>;\n\nexport const cloudflareQueueConsumerSchema = t.object({\n consumer_id: t.string(),\n service: t.string(),\n environment: t.optional(t.string()),\n});\n\nexport type CloudflareQueueConsumer = Static<\n typeof cloudflareQueueConsumerSchema\n>;\n\n// ---------------------------------------------------------------------------\n// Hyperdrive\n// ---------------------------------------------------------------------------\n\nexport const cloudflareHyperdriveOriginSchema = t.object({\n host: t.string(),\n});\n\nexport const cloudflareHyperdriveSchema = t.object({\n id: t.string(),\n name: t.string(),\n origin: cloudflareHyperdriveOriginSchema,\n});\n\nexport type CloudflareHyperdrive = Static<typeof cloudflareHyperdriveSchema>;\n\n// ---------------------------------------------------------------------------\n// Worker\n// ---------------------------------------------------------------------------\n\nexport const cloudflareWorkerSchema = t.object({\n id: t.string(),\n created_on: t.string(),\n modified_on: t.string(),\n});\n\nexport type CloudflareWorker = Static<typeof cloudflareWorkerSchema>;\n\n// ---------------------------------------------------------------------------\n// Deployment\n// ---------------------------------------------------------------------------\n\nexport const cloudflareDeploymentVersionSchema = t.object({\n version_id: t.string(),\n percentage: t.number(),\n});\n\nexport const cloudflareDeploymentSchema = t.object({\n id: t.string(),\n versions: t.array(cloudflareDeploymentVersionSchema),\n created_on: t.string(),\n});\n\nexport type CloudflareDeployment = Static<typeof cloudflareDeploymentSchema>;\n\nexport const cloudflareDeploymentListSchema = t.object({\n deployments: t.array(cloudflareDeploymentSchema),\n});\n\n// ---------------------------------------------------------------------------\n// Version\n// ---------------------------------------------------------------------------\n\nexport const cloudflareVersionSchema = t.object({\n id: t.string(),\n metadata: t.object({\n created_on: t.string(),\n }),\n annotations: t.optional(t.record(t.string(), t.string())),\n});\n\nexport type CloudflareVersion = Static<typeof cloudflareVersionSchema>;\n\nexport const cloudflareVersionListSchema = t.object({\n items: t.array(cloudflareVersionSchema),\n});\n\n// ---------------------------------------------------------------------------\n// Secret\n// ---------------------------------------------------------------------------\n\nexport const cloudflareSecretSchema = t.object({\n name: t.string(),\n type: t.string(),\n});\n\nexport type CloudflareSecret = Static<typeof cloudflareSecretSchema>;\n\n// ---------------------------------------------------------------------------\n// Request bodies\n// ---------------------------------------------------------------------------\n\nexport const createD1BodySchema = t.object({\n name: t.string(),\n primary_location_hint: t.optional(t.string()),\n jurisdiction: t.optional(t.string()),\n});\n\nexport const createKVBodySchema = t.object({\n title: t.string(),\n});\n\nexport const createR2BodySchema = t.object({\n name: t.string(),\n});\n\nexport const createQueueBodySchema = t.object({\n queue_name: t.string(),\n});\n\nexport const createHyperdriveOriginSchema = t.object({\n scheme: t.string(),\n host: t.string(),\n port: t.number(),\n database: t.string(),\n user: t.string(),\n password: t.string(),\n});\n\nexport const createHyperdriveBodySchema = t.object({\n name: t.string(),\n origin: createHyperdriveOriginSchema,\n});\n\nexport const putSecretBodySchema = t.object({\n name: t.string(),\n text: t.string(),\n type: t.string(),\n});\n\n// ---------------------------------------------------------------------------\n// API envelope\n// ---------------------------------------------------------------------------\n\nexport const cloudflareApiErrorSchema = t.object({\n code: t.number(),\n message: t.string(),\n});\n\nexport type CloudflareApiError = Static<typeof cloudflareApiErrorSchema>;\n","import { $inject } from \"alepha\";\nimport { AlephaCliUtils, PackageManagerUtils } from \"alepha/cli\";\nimport { Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { ShellProvider } from \"alepha/system\";\n\n/**\n * Wraps wrangler CLI commands that are kept as shell-outs.\n *\n * Only used for operations where wrangler provides value\n * beyond a raw API call: OAuth login, worker deploy (bundling/upload),\n * D1 migrations, and secret bulk push.\n */\nexport class WranglerApi {\n protected readonly log = $logger();\n protected readonly shell = $inject(ShellProvider);\n protected readonly utils = $inject(AlephaCliUtils);\n protected readonly pm = $inject(PackageManagerUtils);\n protected readonly runner = $inject(Runner);\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Ensure wrangler is installed in the project.\n */\n public async ensureInstalled(root: string, run: RunnerMethod): Promise<void> {\n await this.pm.ensureDependency(root, \"wrangler\", {\n dev: true,\n exec: async (cmd, opts) => {\n run.pause();\n try {\n await this.utils.exec(cmd, opts);\n } finally {\n run.resume();\n }\n },\n });\n }\n\n /**\n * Check if the user is authenticated. Returns the whoami output.\n */\n public async whoami(): Promise<string> {\n return await this.runShell(\"wrangler whoami\", {\n resolve: true,\n capture: true,\n });\n }\n\n /**\n * Open the browser-based OAuth login flow.\n */\n public async login(): Promise<void> {\n await this.runShell(\"wrangler login\", { resolve: true });\n }\n\n /**\n * Get the current auth token from wrangler (auto-refreshes if expired).\n */\n public async getAuthToken(): Promise<string> {\n const output = await this.shell.run(\"wrangler auth token --json\", {\n resolve: true,\n capture: true,\n });\n\n const parsed = JSON.parse(output) as { type: string; token: string };\n return parsed.token;\n }\n\n // -------------------------------------------------------------------------\n // Deploy\n // -------------------------------------------------------------------------\n\n /**\n * Deploy a worker via wrangler (handles bundling and upload).\n *\n * Returns the workers.dev URL if found in the output.\n */\n public async deploy(\n workerName: string,\n configPath: string,\n ): Promise<string | undefined> {\n const output = await this.runShell(\n `wrangler deploy --name=${workerName} --no-bundle --config=${configPath}`,\n { resolve: true, capture: true },\n );\n\n const match = output.match(/https:\\/\\/[^\\s]*\\.workers\\.dev/);\n return match?.[0];\n }\n\n // -------------------------------------------------------------------------\n // D1 Migrations\n // -------------------------------------------------------------------------\n\n /**\n * Apply D1 migrations remotely.\n */\n public async d1MigrationsApply(\n dbName: string,\n configPath: string,\n ): Promise<void> {\n await this.runShell(\n `wrangler d1 migrations apply ${dbName} --remote --config=${configPath}`,\n { resolve: true, env: { CI: \"1\" } },\n );\n }\n}\n","import { $inject, Alepha, AlephaError, type TSchema, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type {\n CloudflareAccount,\n CloudflareApiError,\n CloudflareD1,\n CloudflareDeployment,\n CloudflareHyperdrive,\n CloudflareKV,\n CloudflareQueue,\n CloudflareQueueConsumer,\n CloudflareR2,\n CloudflareSecret,\n CloudflareVersion,\n CloudflareWorker,\n} from \"../schemas/cloudflare.ts\";\nimport {\n cloudflareAccountSchema,\n cloudflareD1Schema,\n cloudflareDeploymentListSchema,\n cloudflareHyperdriveSchema,\n cloudflareKVSchema,\n cloudflareQueueConsumerSchema,\n cloudflareQueueSchema,\n cloudflareR2Schema,\n cloudflareSecretSchema,\n cloudflareVersionSchema,\n cloudflareWorkerSchema,\n createD1BodySchema,\n createHyperdriveBodySchema,\n createKVBodySchema,\n createQueueBodySchema,\n createR2BodySchema,\n putSecretBodySchema,\n} from \"../schemas/cloudflare.ts\";\nimport { WranglerApi } from \"./WranglerApi.ts\";\n\nexport type {\n CloudflareD1,\n CloudflareDeployment,\n CloudflareHyperdrive,\n CloudflareKV,\n CloudflareQueue,\n CloudflareQueueConsumer,\n CloudflareR2,\n CloudflareSecret,\n CloudflareVersion,\n CloudflareWorker,\n};\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\n/**\n * Thin wrapper over the Cloudflare REST API.\n *\n * Uses `wrangler auth token` to obtain credentials,\n * then calls `fetch()` directly for all CRUD operations.\n */\nexport class CloudflareApi {\n protected static readonly BASE = \"https://api.cloudflare.com/client/v4\";\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly wrangler = $inject(WranglerApi);\n\n protected token?: string;\n protected accountId?: string;\n protected jurisdiction?: \"eu\" | \"fedramp\";\n\n /**\n * Set the Cloudflare data jurisdiction for R2 and D1 resources.\n *\n * R2 buckets and D1 databases created under a jurisdiction live in a\n * separate namespace — every R2 API call (list/create/delete) must include\n * the `cf-r2-jurisdiction` header, and D1 create must include the field\n * in the request body. Omit / pass `undefined` for the default (global).\n */\n public setJurisdiction(jurisdiction?: \"eu\" | \"fedramp\"): void {\n this.jurisdiction = jurisdiction;\n }\n\n /**\n * Override the Cloudflare account ID (from platform config).\n *\n * When unset, `resolveAccountId` falls back to `CLOUDFLARE_ACCOUNT_ID` env\n * var or the token's single account.\n */\n public setAccountId(accountId?: string): void {\n this.accountId = accountId;\n }\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Obtain the current auth token from wrangler.\n */\n public async resolveToken(): Promise<string> {\n if (this.token) {\n return this.token;\n }\n\n this.token = await this.wrangler.getAuthToken();\n return this.token;\n }\n\n /**\n * Resolve the Cloudflare account ID.\n *\n * Calls /accounts and picks the first one. Cached after first call.\n */\n public async resolveAccountId(): Promise<string> {\n if (this.accountId) {\n return this.accountId;\n }\n\n const fromEnv = process.env.CLOUDFLARE_ACCOUNT_ID;\n if (fromEnv) {\n this.accountId = fromEnv;\n return this.accountId;\n }\n\n const res = await this.fetch<CloudflareAccount[]>(\"/accounts\", {\n schema: t.array(cloudflareAccountSchema),\n });\n\n if (res.length === 0) {\n throw new AlephaError(\"No Cloudflare accounts found for this token.\");\n }\n\n if (res.length > 1) {\n const list = res.map((a) => ` - ${a.id} ${a.name}`).join(\"\\n\");\n throw new AlephaError(\n `Cloudflare token has access to ${res.length} accounts; set ` +\n `\\`CLOUDFLARE_ACCOUNT_ID\\` or the \\`accountId\\` field in your ` +\n `platform config to pick one:\\n${list}`,\n );\n }\n\n this.accountId = res[0].id;\n return this.accountId;\n }\n\n // -------------------------------------------------------------------------\n // D1\n // -------------------------------------------------------------------------\n\n public async listD1(): Promise<CloudflareD1[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareD1>(\n `/accounts/${accountId}/d1/database`,\n cloudflareD1Schema,\n );\n }\n\n public async createD1(\n name: string,\n location = \"weur\", // TODO: move to config (or auto-resolve based on account info, or ask ?)\n ): Promise<CloudflareD1> {\n const accountId = await this.resolveAccountId();\n // When jurisdiction is set, `primary_location_hint` is silently ignored\n // by the API, so omit it to avoid confusion.\n const body: Record<string, unknown> = { name };\n if (this.jurisdiction) {\n body.jurisdiction = this.jurisdiction;\n } else {\n body.primary_location_hint = location;\n }\n return await this.fetch<CloudflareD1>(\n `/accounts/${accountId}/d1/database`,\n {\n method: \"POST\",\n body,\n bodySchema: createD1BodySchema,\n schema: cloudflareD1Schema,\n },\n );\n }\n\n public async deleteD1(databaseId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/d1/database/${databaseId}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // KV\n // -------------------------------------------------------------------------\n\n public async listKV(): Promise<CloudflareKV[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareKV>(\n `/accounts/${accountId}/storage/kv/namespaces`,\n cloudflareKVSchema,\n 100, // KV list caps at 100 per page\n );\n }\n\n public async createKV(title: string): Promise<CloudflareKV> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareKV>(\n `/accounts/${accountId}/storage/kv/namespaces`,\n {\n method: \"POST\",\n body: { title },\n bodySchema: createKVBodySchema,\n schema: cloudflareKVSchema,\n },\n );\n }\n\n public async deleteKV(namespaceId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(\n `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}`,\n { method: \"DELETE\" },\n );\n }\n\n // -------------------------------------------------------------------------\n // R2\n // -------------------------------------------------------------------------\n\n public async listR2(): Promise<CloudflareR2[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginateCursor<CloudflareR2>(\n `/accounts/${accountId}/r2/buckets`,\n \"buckets\",\n cloudflareR2Schema,\n );\n }\n\n public async createR2(name: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/r2/buckets`, {\n method: \"POST\",\n body: { name },\n bodySchema: createR2BodySchema,\n });\n }\n\n public async deleteR2(name: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/r2/buckets/${name}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // Queues\n // -------------------------------------------------------------------------\n\n public async listQueues(): Promise<CloudflareQueue[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareQueue>(\n `/accounts/${accountId}/queues`,\n cloudflareQueueSchema,\n );\n }\n\n public async createQueue(name: string): Promise<CloudflareQueue> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareQueue>(`/accounts/${accountId}/queues`, {\n method: \"POST\",\n body: { queue_name: name },\n bodySchema: createQueueBodySchema,\n schema: cloudflareQueueSchema,\n });\n }\n\n public async deleteQueue(queueId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/queues/${queueId}`, {\n method: \"DELETE\",\n });\n }\n\n public async listQueueConsumers(\n queueId: string,\n ): Promise<CloudflareQueueConsumer[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareQueueConsumer>(\n `/accounts/${accountId}/queues/${queueId}/consumers`,\n cloudflareQueueConsumerSchema,\n );\n }\n\n public async deleteQueueConsumer(\n queueId: string,\n consumerService: string,\n ): Promise<void> {\n const accountId = await this.resolveAccountId();\n const consumers = await this.listQueueConsumers(queueId);\n const consumer = consumers.find((c) => c.service === consumerService);\n if (!consumer) {\n return;\n }\n await this.fetch(\n `/accounts/${accountId}/queues/${queueId}/consumers/${consumer.consumer_id}`,\n { method: \"DELETE\" },\n );\n }\n\n // -------------------------------------------------------------------------\n // Hyperdrive\n // -------------------------------------------------------------------------\n\n public async listHyperdrive(): Promise<CloudflareHyperdrive[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareHyperdrive>(\n `/accounts/${accountId}/hyperdrive/configs`,\n cloudflareHyperdriveSchema,\n );\n }\n\n public async createHyperdrive(\n name: string,\n connectionString: string,\n ): Promise<CloudflareHyperdrive> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareHyperdrive>(\n `/accounts/${accountId}/hyperdrive/configs`,\n {\n method: \"POST\",\n body: {\n name,\n origin: this.parseConnectionString(connectionString),\n },\n bodySchema: createHyperdriveBodySchema,\n schema: cloudflareHyperdriveSchema,\n },\n );\n }\n\n public async deleteHyperdrive(configId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/hyperdrive/configs/${configId}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // Workers\n // -------------------------------------------------------------------------\n\n public async getWorker(\n scriptName: string,\n ): Promise<CloudflareWorker | undefined> {\n const accountId = await this.resolveAccountId();\n try {\n return await this.fetch<CloudflareWorker>(\n `/accounts/${accountId}/workers/scripts/${scriptName}`,\n { schema: cloudflareWorkerSchema },\n );\n } catch {\n return undefined;\n }\n }\n\n public async deleteWorker(scriptName: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/workers/scripts/${scriptName}`, {\n method: \"DELETE\",\n query: { force: \"true\" },\n });\n }\n\n public async listDeployments(\n scriptName: string,\n ): Promise<CloudflareDeployment[]> {\n const accountId = await this.resolveAccountId();\n // Deployments list is wrapped in `{ deployments }` and returns newest\n // first; for picking the active deployment we only need the top page.\n const res = await this.fetch<{ deployments: CloudflareDeployment[] }>(\n `/accounts/${accountId}/workers/scripts/${scriptName}/deployments`,\n { schema: cloudflareDeploymentListSchema, query: { per_page: \"100\" } },\n );\n return res.deployments;\n }\n\n public async listVersions(scriptName: string): Promise<CloudflareVersion[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginateCursor<CloudflareVersion>(\n `/accounts/${accountId}/workers/scripts/${scriptName}/versions`,\n \"items\",\n cloudflareVersionSchema,\n );\n }\n\n // -------------------------------------------------------------------------\n // Secrets\n // -------------------------------------------------------------------------\n\n public async listSecrets(scriptName: string): Promise<CloudflareSecret[]> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareSecret[]>(\n `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`,\n { schema: t.array(cloudflareSecretSchema) },\n );\n }\n\n public async putSecret(\n scriptName: string,\n name: string,\n value: string,\n ): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(\n `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`,\n {\n method: \"PUT\",\n body: { name, text: value, type: \"secret_text\" },\n bodySchema: putSecretBodySchema,\n },\n );\n }\n\n // -------------------------------------------------------------------------\n // Core fetch\n // -------------------------------------------------------------------------\n\n protected async fetch<T = unknown>(\n path: string,\n options: {\n method?: string;\n body?: unknown;\n bodySchema?: TSchema;\n schema?: TSchema;\n query?: Record<string, string>;\n } = {},\n ): Promise<T> {\n const token = await this.resolveToken();\n const { method = \"GET\", body, query } = options;\n\n let url = `${CloudflareApi.BASE}${path}`;\n if (query) {\n const params = new URLSearchParams(query);\n url += `?${params.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n\n if (this.jurisdiction && /\\/r2\\//.test(path)) {\n headers[\"cf-r2-jurisdiction\"] = this.jurisdiction;\n }\n\n const init: RequestInit = { method, headers };\n\n if (body) {\n headers[\"Content-Type\"] = \"application/json\";\n const validated = options.bodySchema\n ? this.alepha.codec.validate(options.bodySchema, body)\n : body;\n init.body = JSON.stringify(validated);\n }\n\n const response = await globalThis.fetch(url, init);\n const json = (await response.json()) as {\n success: boolean;\n result: T;\n errors: CloudflareApiError[];\n result_info?: {\n page: number;\n per_page: number;\n total_pages?: number;\n count?: number;\n total_count?: number;\n };\n };\n\n if (!json.success) {\n const messages = json.errors.map((e) => e.message).join(\", \");\n throw new AlephaError(\n `Cloudflare API error (${method} ${path}): ${messages}`,\n );\n }\n\n if (options.schema) {\n return this.alepha.codec.validate(options.schema, json.result) as T;\n }\n\n return json.result;\n }\n\n /**\n * Paginate a page-based list endpoint (`result_info.total_pages`).\n *\n * Cloudflare defaults to `per_page=20`; we push it to 1000 (max on most\n * list endpoints) and loop if more pages exist. Each page is validated\n * against the item schema.\n */\n protected async paginate<T>(\n path: string,\n itemSchema: TSchema,\n perPage = 1000,\n ): Promise<T[]> {\n const results: T[] = [];\n let page = 1;\n\n while (true) {\n const token = await this.resolveToken();\n const url = `${CloudflareApi.BASE}${path}?per_page=${perPage}&page=${page}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n if (this.jurisdiction && /\\/r2\\//.test(path)) {\n headers[\"cf-r2-jurisdiction\"] = this.jurisdiction;\n }\n\n const response = await globalThis.fetch(url, { method: \"GET\", headers });\n const json = (await response.json()) as {\n success: boolean;\n result: T[];\n errors: CloudflareApiError[];\n result_info?: { page: number; total_pages?: number };\n };\n\n if (!json.success) {\n const messages = json.errors.map((e) => e.message).join(\", \");\n throw new AlephaError(\n `Cloudflare API error (GET ${path}): ${messages}`,\n );\n }\n\n const validated = this.alepha.codec.validate(\n t.array(itemSchema),\n json.result,\n ) as T[];\n results.push(...validated);\n\n const totalPages = json.result_info?.total_pages;\n if (!totalPages || page >= totalPages || validated.length === 0) {\n break;\n }\n page++;\n }\n\n return results;\n }\n\n /**\n * Paginate a cursor-based list endpoint where `result` is an object\n * containing both the items array and a `cursor` field (R2 buckets,\n * Workers versions). Returns the flattened item array.\n */\n protected async paginateCursor<T>(\n path: string,\n itemsKey: string,\n itemSchema: TSchema,\n perPage = 1000,\n ): Promise<T[]> {\n const results: T[] = [];\n let cursor: string | undefined;\n\n while (true) {\n const query: Record<string, string> = { per_page: String(perPage) };\n if (cursor) {\n query.cursor = cursor;\n }\n\n const res = await this.fetch<Record<string, unknown>>(path, { query });\n const items = (res[itemsKey] as unknown[]) ?? [];\n const validated = this.alepha.codec.validate(\n t.array(itemSchema),\n items,\n ) as T[];\n results.push(...validated);\n\n const nextCursor = res.cursor as string | undefined;\n if (!nextCursor || validated.length === 0) {\n break;\n }\n cursor = nextCursor;\n }\n\n return results;\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n /**\n * Parse a postgres:// connection string into Hyperdrive origin fields.\n */\n protected parseConnectionString(connectionString: string): {\n scheme: string;\n host: string;\n port: number;\n database: string;\n user: string;\n password: string;\n } {\n const url = new URL(connectionString);\n return {\n scheme: \"postgres\",\n host: url.hostname,\n port: Number(url.port) || 5432,\n database: url.pathname.slice(1),\n user: decodeURIComponent(url.username),\n password: decodeURIComponent(url.password),\n };\n }\n}\n","import type { AppEntry } from \"alepha/cli\";\nimport type { RunnerMethod } from \"alepha/command\";\nimport type { EnvironmentConfig } from \"../atoms/platformOptions.ts\";\nimport type { NamingContext } from \"../services/NamingService.ts\";\n\n// ---------------------------------------------------------------------------\n// Context types\n// ---------------------------------------------------------------------------\n\nexport interface DetectedResources {\n hasDatabase: boolean;\n hasBucket: boolean;\n hasKV: boolean;\n hasQueue: boolean;\n hasCron: boolean;\n}\n\nexport interface AppDefinition {\n /**\n * Slugified app name (from package.json).\n */\n name: string;\n\n /**\n * Relative path from root (e.g., \"apps/api\").\n * Empty string for standalone apps.\n */\n path: string;\n\n /**\n * Resolved entry points for this app.\n */\n entry: AppEntry;\n\n /**\n * Cloud resources detected by introspecting the app.\n */\n resources: DetectedResources;\n}\n\nexport interface PlatformContext {\n /**\n * Slugified project name (from root package.json or config).\n */\n project: string;\n\n /**\n * Environment key (e.g., \"production\", \"staging\", \"tmp-bug001\").\n */\n env: string;\n\n /**\n * Environment configuration from alepha.config.ts.\n */\n envConfig: EnvironmentConfig;\n\n /**\n * All apps in the project.\n */\n apps: AppDefinition[];\n\n /**\n * Monorepo/project root path.\n */\n root: string;\n\n /**\n * Resource name generator bound to this project+env.\n */\n naming: NamingContext;\n}\n\nexport interface AppContext extends PlatformContext {\n /**\n * The specific app being operated on.\n */\n app: AppDefinition;\n}\n\n// ---------------------------------------------------------------------------\n// State types (returned by inspect)\n// ---------------------------------------------------------------------------\n\nexport interface ResourceState {\n name: string;\n exists: boolean;\n id?: string;\n detail?: string;\n}\n\nexport interface WorkerState extends ResourceState {\n version?: string;\n tag?: string;\n createdAt?: string;\n}\n\nexport interface SecretState {\n name: string;\n deployed: boolean;\n}\n\nexport interface PlatformState {\n workers: WorkerState[];\n databases: ResourceState[];\n buckets: ResourceState[];\n kvNamespaces: ResourceState[];\n queues: ResourceState[];\n secrets: SecretState[];\n}\n\n// ---------------------------------------------------------------------------\n// Adapter contract\n// ---------------------------------------------------------------------------\n\n/**\n * Abstract platform adapter.\n *\n * Each cloud provider (Cloudflare, AKS, docker-compose) implements this.\n * The PlatformOrchestrator calls these methods in the correct order.\n */\nexport abstract class PlatformAdapter {\n /**\n * Ensure the user is authenticated with the cloud provider.\n * May use cached credentials to avoid slow checks.\n */\n abstract authenticate(ctx: PlatformContext, run: RunnerMethod): Promise<void>;\n\n /**\n * Build artifacts for a single app.\n */\n abstract build(ctx: AppContext, run: RunnerMethod): Promise<void>;\n\n /**\n * Deploy a single app (upload + activate atomically, e.g., wrangler deploy).\n * Returns the live URL if the platform provides one.\n */\n abstract deploy(\n ctx: AppContext,\n run: RunnerMethod,\n ): Promise<string | undefined>;\n\n /**\n * Create/ensure cloud resources exist (DB, buckets, queues).\n * Not all adapters provision -- AKS defers to Helm.\n */\n async provision(_ctx: PlatformContext, _run: RunnerMethod): Promise<void> {}\n\n /**\n * Run database migrations.\n */\n async migrate(_ctx: PlatformContext, _run: RunnerMethod): Promise<void> {}\n\n /**\n * Push runtime secrets to the deployed worker(s).\n *\n * Reads secrets from `.env.{env}` files (parsed, not from process.env),\n * filters out vars already handled by bindings (DATABASE_URL, R2, etc.),\n * and pushes the rest via the platform's secret management.\n */\n async secrets(_ctx: PlatformContext, _run: RunnerMethod): Promise<void> {}\n\n /**\n * Detect existing resources and their state.\n * Used by `plan` and `status` commands.\n */\n abstract inspect(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<PlatformState>;\n\n /**\n * Tear down all resources for an environment.\n */\n abstract teardown(ctx: PlatformContext, run: RunnerMethod): Promise<void>;\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { EnvUtils, Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\nimport { PlatformCacheProvider } from \"../providers/PlatformCacheProvider.ts\";\nimport { CloudflareApi } from \"../services/CloudflareApi.ts\";\nimport { WranglerApi } from \"../services/WranglerApi.ts\";\nimport {\n type AppContext,\n PlatformAdapter,\n type PlatformContext,\n type PlatformState,\n} from \"./PlatformAdapter.ts\";\n\n/**\n * Cloudflare Workers adapter.\n *\n * Uses the Cloudflare REST API (via CloudflareApi) for resource provisioning\n * and teardown, and wrangler CLI (via WranglerApi) for login, deploy,\n * D1 migrations, and secret bulk push.\n */\nexport class CloudflareAdapter extends PlatformAdapter {\n protected readonly log = $logger();\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly shell = $inject(ShellProvider);\n protected readonly cache = $inject(PlatformCacheProvider);\n protected readonly alepha = $inject(Alepha);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly api = $inject(CloudflareApi);\n protected readonly wrangler = $inject(WranglerApi);\n protected readonly runner = $inject(Runner);\n\n protected provisionedD1Id?: string;\n protected provisionedHyperdriveId?: string;\n protected provisionedKVIds = new Map<string, string>();\n\n /**\n * Check if the user's DATABASE_URL points to an external Postgres database.\n * If so, we use Hyperdrive instead of D1.\n *\n * Reads from `.env.{env}` first, falls back to `process.env`.\n */\n protected async isPostgres(ctx: PlatformContext): Promise<boolean> {\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL;\n return !!dbUrl?.startsWith(\"postgres:\");\n }\n\n /**\n * Propagate the environment's data-jurisdiction setting to the API client.\n *\n * Must be invoked at the top of every entry point (authenticate, build,\n * deploy, secrets, provision, migrate, inspect, teardown) because\n * CloudflareApi is a singleton reused across env invocations.\n */\n protected configureApi(ctx: PlatformContext): void {\n this.api.setJurisdiction(ctx.envConfig.jurisdiction);\n this.api.setAccountId(ctx.envConfig.accountId);\n }\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // authenticate\n // -------------------------------------------------------------------------\n\n async authenticate(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n this.configureApi(ctx);\n await run({\n name: \"authenticate\",\n handler: async () => {\n await this.wrangler.ensureInstalled(ctx.root, run);\n\n // Always validate the token — refresh tokens can expire between runs\n // even when the cache TTL hasn't elapsed.\n let needsLogin = false;\n\n try {\n await this.wrangler.getAuthToken();\n } catch {\n needsLogin = true;\n }\n\n if (needsLogin) {\n run.pause();\n await this.wrangler.login();\n run.resume();\n }\n\n // Skip account resolution if cache is fresh\n if (await this.cache.isLoginFresh(ctx.root, \"cloudflare\")) {\n return;\n }\n\n // Resolve account ID via REST API (typed, no regex)\n try {\n const accountId = await this.api.resolveAccountId();\n await this.cache.recordLogin(ctx.root, \"cloudflare\", accountId);\n } catch {\n await this.cache.recordLogin(ctx.root, \"cloudflare\");\n }\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // build\n // -------------------------------------------------------------------------\n\n async build(ctx: AppContext, run: RunnerMethod): Promise<void> {\n this.configureApi(ctx);\n const appDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path)\n : ctx.root;\n\n const env: Record<string, string> = {};\n\n if (ctx.app.resources.hasDatabase) {\n if (this.provisionedHyperdriveId) {\n env.HYPERDRIVE_ID = this.provisionedHyperdriveId;\n const envVars = await this.envUtils.parseEnv(ctx.root, [\n `.env.${ctx.env}`,\n ]);\n const pgSchema = envVars.POSTGRES_SCHEMA ?? process.env.POSTGRES_SCHEMA;\n if (pgSchema) {\n env.POSTGRES_SCHEMA = pgSchema;\n }\n } else if (this.provisionedD1Id) {\n const dbName = ctx.naming.d1();\n env.DATABASE_URL = `d1://${dbName}:${this.provisionedD1Id}`;\n }\n }\n\n if (ctx.app.resources.hasBucket) {\n env.R2_BUCKET_NAME = ctx.naming.r2();\n }\n\n if (ctx.app.resources.hasKV) {\n const kvName = ctx.naming.kv(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n env.CLOUDFLARE_KV_NAME = kvName;\n const kvId = this.provisionedKVIds.get(kvName);\n if (kvId) {\n env.CLOUDFLARE_KV_ID = kvId;\n }\n }\n\n if (ctx.app.resources.hasQueue) {\n env.CLOUDFLARE_QUEUE_NAME = ctx.naming.queue(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n }\n\n if (ctx.envConfig.domain) {\n env.CLOUDFLARE_DOMAIN = ctx.envConfig.domain;\n }\n\n if (ctx.envConfig.jurisdiction) {\n env.CLOUDFLARE_JURISDICTION = ctx.envConfig.jurisdiction;\n }\n\n await run({\n name: \"alepha build -t cloudflare\",\n handler: async () => {\n await this.runShell(\"alepha build -t cloudflare\", {\n root: appDir,\n env,\n });\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // deploy (wrangler — handles bundling/upload)\n // -------------------------------------------------------------------------\n\n async deploy(\n ctx: AppContext,\n run: RunnerMethod,\n ): Promise<string | undefined> {\n this.configureApi(ctx);\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n const distDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path, \"dist\")\n : this.fs.join(ctx.root, \"dist\");\n\n let url: string | undefined;\n\n await run({\n name: `deploy worker ${ctx.app.name}`,\n handler: async () => {\n url = await this.wrangler.deploy(\n workerName,\n `${distDir}/wrangler.jsonc`,\n );\n },\n });\n\n return url;\n }\n\n // -------------------------------------------------------------------------\n // secrets (wrangler — bulk push)\n // -------------------------------------------------------------------------\n\n /**\n * Vars that are handled by wrangler bindings or build config.\n * These should not be pushed as secrets.\n */\n static readonly EXCLUDED_SECRET_KEYS = new Set([\n \"DATABASE_URL\",\n \"R2_BUCKET_NAME\",\n \"CLOUDFLARE_DOMAIN\",\n \"CLOUDFLARE_JURISDICTION\",\n \"HYPERDRIVE_ID\",\n \"POSTGRES_SCHEMA\",\n \"NODE_ENV\",\n ]);\n\n override async secrets(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n this.configureApi(ctx);\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n\n // Filter out binding/build vars, VITE_* vars, and empty values\n const secrets: Record<string, string> = {};\n for (const [key, value] of Object.entries(envVars)) {\n if (!value) continue;\n if (CloudflareAdapter.EXCLUDED_SECRET_KEYS.has(key)) continue;\n if (key.startsWith(\"VITE_\")) continue;\n secrets[key] = value;\n }\n\n if (Object.keys(secrets).length === 0) {\n return;\n }\n\n // Push secrets to each worker via the REST API (one PUT per secret).\n // Historically we shelled out to `wrangler secret bulk`, but it has an\n // open hang issue (workers-sdk#10555) and is redundant given putSecret.\n for (const app of ctx.apps) {\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n await run({\n name: `push secrets to ${workerName}`,\n handler: async () => {\n for (const [name, value] of Object.entries(secrets)) {\n await this.api.putSecret(workerName, name, value);\n }\n },\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // provision (REST API)\n // -------------------------------------------------------------------------\n\n override async provision(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n this.configureApi(ctx);\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n const needsBucket = ctx.apps.some((a) => a.resources.hasBucket);\n const postgres = needsDB && (await this.isPostgres(ctx));\n\n const tasks: Array<{ name: string; handler: () => Promise<void> }> = [];\n\n if (needsDB) {\n if (postgres) {\n const hdName = ctx.naming.hyperdrive();\n const envVars = await this.envUtils.parseEnv(ctx.root, [\n `.env.${ctx.env}`,\n ]);\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL!;\n tasks.push({\n name: `provision hyperdrive (${hdName})`,\n handler: async () => {\n this.provisionedHyperdriveId = await this.ensureHyperdrive(\n hdName,\n dbUrl,\n );\n },\n });\n } else {\n const dbName = ctx.naming.d1();\n tasks.push({\n name: `provision d1 (${dbName})`,\n handler: async () => {\n this.provisionedD1Id = await this.ensureD1(dbName);\n },\n });\n }\n }\n\n if (needsBucket) {\n const bucketName = ctx.naming.r2();\n tasks.push({\n name: `provision r2 (${bucketName})`,\n handler: async () => {\n await this.ensureR2(bucketName);\n },\n });\n }\n\n for (const app of ctx.apps) {\n if (app.resources.hasKV) {\n const kvName = ctx.naming.kv(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `provision kv (${kvName})`,\n handler: async () => {\n this.provisionedKVIds.set(kvName, await this.ensureKV(kvName));\n },\n });\n }\n\n if (app.resources.hasQueue) {\n const queueName = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `provision queue (${queueName})`,\n handler: async () => {\n await this.ensureQueue(queueName);\n },\n });\n }\n }\n\n await run(tasks);\n }\n\n // -------------------------------------------------------------------------\n // migrate (wrangler — D1 migration runner)\n // -------------------------------------------------------------------------\n\n override async migrate(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n this.configureApi(ctx);\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n if (!needsDB) {\n return;\n }\n\n if (await this.isPostgres(ctx)) {\n await this.migratePostgres(ctx, run);\n } else {\n await this.migrateD1(ctx, run);\n }\n }\n\n protected async migrateD1(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n const dbName = ctx.naming.d1();\n\n await run({\n name: \"migrate d1\",\n handler: async () => {\n const migrationsDir = this.fs.join(ctx.root, \"migrations\", \"sqlite\");\n const dbUrl = this.provisionedD1Id\n ? `d1://${dbName}:${this.provisionedD1Id}`\n : `d1://${dbName}`;\n const env = { DATABASE_URL: dbUrl };\n\n if (await this.fs.exists(migrationsDir)) {\n await this.runShell(`alepha db migrations check --mode ${ctx.env}`, {\n resolve: true,\n env,\n });\n } else {\n await this.runShell(`alepha db migrations create --mode ${ctx.env}`, {\n resolve: true,\n env,\n });\n }\n\n // Copy migrations to dist for wrangler, apply, then clean up\n const distMigrations = this.fs.join(ctx.root, \"dist\", \"migrations\");\n await this.fs.cp(migrationsDir, distMigrations);\n\n await this.wrangler.d1MigrationsApply(dbName, \"dist/wrangler.jsonc\");\n\n await this.fs.rm(distMigrations, { recursive: true });\n },\n });\n }\n\n protected async migratePostgres(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n await run({\n name: \"migrate postgres\",\n handler: async () => {\n const envVars = await this.envUtils.parseEnv(ctx.root, [\n `.env.${ctx.env}`,\n ]);\n\n const env: Record<string, string> = {\n DATABASE_URL: envVars.DATABASE_URL ?? process.env.DATABASE_URL!,\n };\n\n if (envVars.POSTGRES_SCHEMA ?? process.env.POSTGRES_SCHEMA) {\n env.POSTGRES_SCHEMA = (envVars.POSTGRES_SCHEMA ??\n process.env.POSTGRES_SCHEMA)!;\n }\n\n await this.runShell(`alepha db migrations apply --mode ${ctx.env}`, {\n resolve: true,\n env,\n });\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // inspect (REST API)\n // -------------------------------------------------------------------------\n\n async inspect(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<PlatformState> {\n this.configureApi(ctx);\n const state: PlatformState = {\n workers: [],\n databases: [],\n buckets: [],\n kvNamespaces: [],\n queues: [],\n secrets: [],\n };\n\n const tasks: Array<{ name: string; handler: () => Promise<void> }> = [];\n\n // Workers\n for (const app of ctx.apps) {\n const name = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n tasks.push({\n name: `inspect worker (${name})`,\n handler: async () => {\n try {\n const deployment = await this.getActiveDeployment(name);\n if (deployment) {\n state.workers.push({\n name,\n exists: true,\n version: deployment.versionId,\n tag: deployment.tag,\n createdAt: deployment.createdAt,\n });\n } else {\n state.workers.push({ name, exists: false });\n }\n } catch {\n state.workers.push({ name, exists: false });\n }\n },\n });\n }\n\n // Database\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n if (needsDB) {\n if (await this.isPostgres(ctx)) {\n const hdName = ctx.naming.hyperdrive();\n tasks.push({\n name: `inspect hyperdrive (${hdName})`,\n handler: async () => {\n const configs = await this.api.listHyperdrive();\n const existing = configs.find((c) => c.name === hdName);\n state.databases.push({\n name: hdName,\n exists: !!existing,\n id: existing?.id,\n detail: existing?.origin.host,\n });\n },\n });\n } else {\n const dbName = ctx.naming.d1();\n tasks.push({\n name: `inspect d1 (${dbName})`,\n handler: async () => {\n const databases = await this.api.listD1();\n const existing = databases.find((db) => db.name === dbName);\n state.databases.push({\n name: dbName,\n exists: !!existing,\n id: existing?.uuid,\n });\n },\n });\n }\n }\n\n // R2\n const needsBucket = ctx.apps.some((a) => a.resources.hasBucket);\n if (needsBucket) {\n const bucketName = ctx.naming.r2();\n tasks.push({\n name: `inspect r2 (${bucketName})`,\n handler: async () => {\n const buckets = await this.api.listR2();\n const existing = buckets.find((b) => b.name === bucketName);\n state.buckets.push({\n name: bucketName,\n exists: !!existing,\n id: existing?.creation_date,\n });\n },\n });\n }\n\n // KV\n for (const app of ctx.apps) {\n if (app.resources.hasKV) {\n const kvName = ctx.naming.kv(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `inspect kv (${kvName})`,\n handler: async () => {\n const namespaces = await this.api.listKV();\n const existing = namespaces.find((ns) => ns.title === kvName);\n state.kvNamespaces.push({\n name: kvName,\n exists: !!existing,\n id: existing?.id,\n });\n },\n });\n }\n }\n\n // Queues\n for (const app of ctx.apps) {\n if (app.resources.hasQueue) {\n const queueName = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `inspect queue (${queueName})`,\n handler: async () => {\n const queues = await this.api.listQueues();\n const existing = queues.find((q) => q.queue_name === queueName);\n state.queues.push({\n name: queueName,\n exists: !!existing,\n id: existing?.queue_id,\n });\n },\n });\n }\n }\n\n // Secrets\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n const expectedSecrets = Object.keys(envVars).filter(\n (key) =>\n envVars[key] &&\n !CloudflareAdapter.EXCLUDED_SECRET_KEYS.has(key) &&\n !key.startsWith(\"VITE_\"),\n );\n\n if (expectedSecrets.length > 0) {\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.apps[0].name : undefined,\n );\n tasks.push({\n name: \"inspect secrets\",\n handler: async () => {\n try {\n const deployed = await this.api.listSecrets(workerName);\n const deployedNames = new Set(deployed.map((s) => s.name));\n for (const key of expectedSecrets) {\n state.secrets.push({\n name: key,\n deployed: deployedNames.has(key),\n });\n }\n } catch {\n for (const key of expectedSecrets) {\n state.secrets.push({ name: key, deployed: false });\n }\n }\n },\n });\n }\n\n await run(tasks);\n\n return state;\n }\n\n // -------------------------------------------------------------------------\n // teardown (REST API)\n // -------------------------------------------------------------------------\n\n async teardown(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n this.configureApi(ctx);\n // 1. Remove queue consumers (must happen before worker or queue deletion)\n for (const app of ctx.apps) {\n if (app.resources.hasQueue) {\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n const queueName = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n await run({\n name: `unbind queue consumer ${queueName}`,\n handler: async () => {\n try {\n const queues = await this.api.listQueues();\n const queue = queues.find((q) => q.queue_name === queueName);\n if (queue) {\n await this.api.deleteQueueConsumer(queue.queue_id, workerName);\n }\n } catch (error: any) {\n this.log.warn(\n `Failed to unbind queue consumer: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n\n // 2. Delete workers\n for (const app of ctx.apps) {\n const name = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n await run({\n name: `delete worker ${name}`,\n handler: async () => {\n try {\n await this.api.deleteWorker(name);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete worker ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n\n // 3. Delete queues (after worker is gone)\n for (const app of ctx.apps) {\n if (app.resources.hasQueue) {\n const name = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n await run({\n name: `delete queue ${name}`,\n handler: async () => {\n try {\n const queues = await this.api.listQueues();\n const queue = queues.find((q) => q.queue_name === name);\n if (!queue) {\n this.log.debug(`Queue ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteQueue(queue.queue_id);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete queue ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n\n // 4. Delete KV namespaces\n for (const app of ctx.apps) {\n if (app.resources.hasKV) {\n const name = ctx.naming.kv(ctx.apps.length > 1 ? app.name : undefined);\n await run({\n name: `delete kv ${name}`,\n handler: async () => {\n try {\n const namespaces = await this.api.listKV();\n const existing = namespaces.find((ns) => ns.title === name);\n if (!existing) {\n this.log.debug(`KV namespace ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteKV(existing.id);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete kv ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n\n // 5. Delete R2 bucket\n // TODO: empty bucket via S3-compatible API before deletion (needs native S3 client)\n // const needsBucket = ctx.apps.some((a) => a.resources.hasBucket);\n // if (needsBucket) {\n // const name = ctx.naming.r2();\n // await run({\n // name: `delete r2 ${name}`,\n // handler: async () => {\n // try {\n // await this.api.deleteR2(name);\n // } catch (error: any) {\n // const msg = String(error.message || \"\");\n // if (\n // msg.includes(\"does not exist\") ||\n // msg.includes(\"NoSuchBucket\")\n // ) {\n // // Already gone, nothing to do\n // } else if (\n // msg.includes(\"not empty\") ||\n // msg.includes(\"BucketNotEmpty\")\n // ) {\n // this.log.warn(\n // `Bucket ${name} is not empty -- skipped. Empty it manually.`,\n // );\n // } else {\n // this.log.warn(`Failed to delete r2 ${name}: ${msg}`);\n // }\n // }\n // },\n // });\n // }\n\n // 6. Delete D1 or Hyperdrive\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n if (needsDB) {\n if (await this.isPostgres(ctx)) {\n const name = ctx.naming.hyperdrive();\n await run({\n name: `delete hyperdrive ${name}`,\n handler: async () => {\n try {\n const configs = await this.api.listHyperdrive();\n const existing = configs.find((c) => c.name === name);\n if (!existing) {\n this.log.debug(`Hyperdrive ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteHyperdrive(existing.id);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete hyperdrive ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n } else {\n const name = ctx.naming.d1();\n await run({\n name: `delete d1 ${name}`,\n handler: async () => {\n try {\n const databases = await this.api.listD1();\n const existing = databases.find((db) => db.name === name);\n if (!existing) {\n this.log.debug(`D1 database ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteD1(existing.uuid);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete d1 ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Resource helpers (REST API)\n // -------------------------------------------------------------------------\n\n protected async ensureD1(name: string): Promise<string> {\n const databases = await this.api.listD1();\n const existing = databases.find((db) => db.name === name);\n if (existing) {\n return existing.uuid;\n }\n\n const created = await this.api.createD1(name);\n return created.uuid;\n }\n\n protected async ensureHyperdrive(\n name: string,\n connectionString: string,\n ): Promise<string> {\n const configs = await this.api.listHyperdrive();\n const existing = configs.find((c) => c.name === name);\n if (existing) {\n return existing.id;\n }\n\n const created = await this.api.createHyperdrive(name, connectionString);\n return created.id;\n }\n\n protected async ensureR2(name: string): Promise<void> {\n const buckets = await this.api.listR2();\n const existing = buckets.find((b) => b.name === name);\n if (existing) {\n return;\n }\n\n await this.api.createR2(name);\n }\n\n protected async ensureKV(name: string): Promise<string> {\n const namespaces = await this.api.listKV();\n const existing = namespaces.find((ns) => ns.title === name);\n if (existing) {\n return existing.id;\n }\n\n const created = await this.api.createKV(name);\n return created.id;\n }\n\n protected async ensureQueue(name: string): Promise<void> {\n const queues = await this.api.listQueues();\n const existing = queues.find((q) => q.queue_name === name);\n if (existing) {\n return;\n }\n\n await this.api.createQueue(name);\n }\n\n /**\n * Get the currently active deployment for a worker.\n */\n protected async getActiveDeployment(\n workerName: string,\n ): Promise<\n { versionId: string; tag?: string; createdAt?: string } | undefined\n > {\n const deployments = await this.api.listDeployments(workerName);\n\n // API ordering is not guaranteed across releases — sort explicitly.\n const sorted = [...deployments].sort((a, b) =>\n b.created_on.localeCompare(a.created_on),\n );\n const latest = sorted[0];\n if (!latest?.versions?.[0]) {\n return undefined;\n }\n\n const activeVersionId = latest.versions[0].version_id;\n\n const versions = await this.api.listVersions(workerName);\n const version = versions.find((v) => v.id === activeVersionId);\n\n return {\n versionId: activeVersionId,\n tag: version?.annotations?.[\"workers/tag\"],\n createdAt: version?.metadata.created_on,\n };\n }\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\n// ---------------------------------------------------------------------------\n// Project\n// ---------------------------------------------------------------------------\n\nexport const vercelProjectSchema = t.object({\n id: t.string(),\n name: t.string(),\n accountId: t.string(),\n});\n\nexport type VercelProject = Static<typeof vercelProjectSchema>;\n\nexport const createProjectBodySchema = t.object({\n name: t.string(),\n framework: t.optional(t.null()),\n});\n\n// ---------------------------------------------------------------------------\n// Deployment\n// ---------------------------------------------------------------------------\n\nexport const vercelDeploymentSchema = t.object({\n uid: t.string(),\n name: t.string(),\n url: t.string(),\n state: t.optional(t.string()),\n readyState: t.optional(t.string()),\n created: t.optional(t.number()),\n target: t.optional(t.string()),\n alias: t.optional(t.array(t.string())),\n});\n\nexport type VercelDeployment = Static<typeof vercelDeploymentSchema>;\n\n// ---------------------------------------------------------------------------\n// Environment Variable\n// ---------------------------------------------------------------------------\n\nexport const vercelEnvVarSchema = t.object({\n id: t.string(),\n key: t.string(),\n value: t.optional(t.string()),\n type: t.string(),\n target: t.array(t.string()),\n});\n\nexport type VercelEnvVar = Static<typeof vercelEnvVarSchema>;\n\nexport const createEnvVarBodySchema = t.object({\n key: t.string(),\n value: t.string(),\n type: t.string(),\n target: t.array(t.string()),\n});\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { $inject, AlephaError } from \"alepha\";\nimport { AlephaCliUtils, PackageManagerUtils } from \"alepha/cli\";\nimport { Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\n\n/**\n * Wraps Vercel CLI commands and token management.\n *\n * Used for operations where the Vercel CLI provides value:\n * OAuth login, prebuilt deploy, and auth token extraction.\n */\nexport class VercelCli {\n protected readonly log = $logger();\n protected readonly shell = $inject(ShellProvider);\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly utils = $inject(AlephaCliUtils);\n protected readonly pm = $inject(PackageManagerUtils);\n protected readonly runner = $inject(Runner);\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // Install\n // -------------------------------------------------------------------------\n\n /**\n * Ensure vercel CLI is installed in the project.\n */\n public async ensureInstalled(root: string, run: RunnerMethod): Promise<void> {\n await this.pm.ensureDependency(root, \"vercel\", {\n dev: true,\n exec: async (cmd, opts) => {\n run.pause();\n try {\n await this.utils.exec(cmd, opts);\n } finally {\n run.resume();\n }\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Get the Vercel auth token.\n *\n * Priority:\n * 1. VERCEL_TOKEN environment variable (CI/CD)\n * 2. Vercel CLI auth.json file (local dev)\n */\n public async getAuthToken(): Promise<string> {\n const envToken = process.env.VERCEL_TOKEN;\n if (envToken) {\n return envToken;\n }\n\n const authPath = this.getAuthFilePath();\n if (!(await this.fs.exists(authPath))) {\n throw new AlephaError(\n \"Vercel auth token not found. Run `vercel login` or set VERCEL_TOKEN.\",\n );\n }\n\n const content = await this.fs.readFile(authPath);\n const parsed = JSON.parse(content.toString()) as { token?: string };\n\n if (!parsed.token) {\n throw new AlephaError(\n \"Vercel auth.json exists but contains no token. Run `vercel login`.\",\n );\n }\n\n return parsed.token;\n }\n\n /**\n * Validate the current auth token.\n */\n public async whoami(): Promise<string> {\n return await this.runShell(\"vercel whoami\", {\n resolve: true,\n capture: true,\n });\n }\n\n /**\n * Open the browser-based login flow.\n */\n public async login(): Promise<void> {\n await this.runShell(\"vercel login\", { resolve: true });\n }\n\n // -------------------------------------------------------------------------\n // Deploy\n // -------------------------------------------------------------------------\n\n /**\n * Deploy a prebuilt .vercel/output/ directory.\n *\n * Returns the deployment URL.\n */\n public async deploy(\n distDir: string,\n options: { prod?: boolean; token?: string },\n ): Promise<string | undefined> {\n const args = [\"vercel\", \"deploy\", \"--prebuilt\"];\n\n if (options.prod) {\n args.push(\"--prod\");\n }\n\n if (options.token) {\n args.push(`--token=${options.token}`);\n }\n\n const output = await this.runShell(args.join(\" \"), {\n resolve: true,\n capture: true,\n root: distDir,\n });\n\n // Vercel CLI outputs the deployment URL on the last non-empty line\n const lines = output.trim().split(\"\\n\");\n const url = lines\n .reverse()\n .find((line) => line.trim().startsWith(\"https://\"));\n return url?.trim();\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n /**\n * Resolve the path to Vercel CLI auth.json.\n */\n protected getAuthFilePath(): string {\n const os = platform();\n\n if (os === \"darwin\") {\n return join(\n homedir(),\n \"Library\",\n \"Application Support\",\n \"com.vercel.cli\",\n \"auth.json\",\n );\n }\n\n if (os === \"win32\") {\n return join(\n homedir(),\n \"AppData\",\n \"Roaming\",\n \"xdg.data\",\n \"com.vercel.cli\",\n \"auth.json\",\n );\n }\n\n // Linux / other\n return join(homedir(), \".local\", \"share\", \"com.vercel.cli\", \"auth.json\");\n }\n}\n","import { $inject, Alepha, AlephaError, type TSchema, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type {\n VercelDeployment,\n VercelEnvVar,\n VercelProject,\n} from \"../schemas/vercel.ts\";\nimport {\n createEnvVarBodySchema,\n createProjectBodySchema,\n vercelDeploymentSchema,\n vercelEnvVarSchema,\n vercelProjectSchema,\n} from \"../schemas/vercel.ts\";\nimport { VercelCli } from \"./VercelCli.ts\";\n\n/**\n * Thin wrapper over the Vercel REST API.\n *\n * Uses the auth token from VercelCli for all requests.\n */\nexport class VercelApi {\n protected static readonly BASE = \"https://api.vercel.com\";\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly vercelCli = $inject(VercelCli);\n\n protected token?: string;\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Obtain the current auth token from the Vercel CLI.\n */\n public async resolveToken(): Promise<string> {\n if (this.token) {\n return this.token;\n }\n\n this.token = await this.vercelCli.getAuthToken();\n return this.token;\n }\n\n // -------------------------------------------------------------------------\n // Projects\n // -------------------------------------------------------------------------\n\n public async listProjects(): Promise<VercelProject[]> {\n const res = await this.fetch<{ projects: VercelProject[] }>(\n \"/v10/projects\",\n { schema: t.object({ projects: t.array(vercelProjectSchema) }) },\n );\n return res.projects;\n }\n\n public async getProject(\n nameOrId: string,\n ): Promise<VercelProject | undefined> {\n try {\n return await this.fetch<VercelProject>(\n `/v9/projects/${encodeURIComponent(nameOrId)}`,\n { schema: vercelProjectSchema },\n );\n } catch {\n return undefined;\n }\n }\n\n public async createProject(name: string): Promise<VercelProject> {\n return await this.fetch<VercelProject>(\"/v11/projects\", {\n method: \"POST\",\n body: { name, framework: null },\n bodySchema: createProjectBodySchema,\n schema: vercelProjectSchema,\n });\n }\n\n public async updateProject(\n nameOrId: string,\n settings: { framework?: null },\n ): Promise<void> {\n await this.fetch(`/v9/projects/${encodeURIComponent(nameOrId)}`, {\n method: \"PATCH\",\n body: settings,\n });\n }\n\n public async deleteProject(nameOrId: string): Promise<void> {\n await this.fetch(`/v9/projects/${encodeURIComponent(nameOrId)}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // Deployments\n // -------------------------------------------------------------------------\n\n public async listDeployments(\n projectId: string,\n options?: { limit?: number; target?: string },\n ): Promise<VercelDeployment[]> {\n const query: Record<string, string> = { projectId };\n if (options?.limit) {\n query.limit = String(options.limit);\n }\n if (options?.target) {\n query.target = options.target;\n }\n\n const res = await this.fetch<{ deployments: VercelDeployment[] }>(\n \"/v6/deployments\",\n {\n query,\n schema: t.object({ deployments: t.array(vercelDeploymentSchema) }),\n },\n );\n return res.deployments;\n }\n\n // -------------------------------------------------------------------------\n // Environment Variables\n // -------------------------------------------------------------------------\n\n public async listEnvVars(projectId: string): Promise<VercelEnvVar[]> {\n const res = await this.fetch<{ envs: VercelEnvVar[] }>(\n `/v10/projects/${encodeURIComponent(projectId)}/env`,\n {\n query: { decrypt: \"true\" },\n schema: t.object({ envs: t.array(vercelEnvVarSchema) }),\n },\n );\n return res.envs;\n }\n\n public async upsertEnvVars(\n projectId: string,\n vars: Array<{\n key: string;\n value: string;\n target: string[];\n }>,\n ): Promise<void> {\n for (const v of vars) {\n await this.fetch(`/v10/projects/${encodeURIComponent(projectId)}/env`, {\n method: \"POST\",\n query: { upsert: \"true\" },\n body: {\n key: v.key,\n value: v.value,\n type: \"encrypted\",\n target: v.target,\n },\n bodySchema: createEnvVarBodySchema,\n });\n }\n }\n\n public async deleteEnvVar(\n projectId: string,\n envVarId: string,\n ): Promise<void> {\n await this.fetch(\n `/v9/projects/${encodeURIComponent(projectId)}/env/${envVarId}`,\n { method: \"DELETE\" },\n );\n }\n\n // -------------------------------------------------------------------------\n // Core fetch\n // -------------------------------------------------------------------------\n\n protected async fetch<T = unknown>(\n path: string,\n options: {\n method?: string;\n body?: unknown;\n bodySchema?: TSchema;\n schema?: TSchema;\n query?: Record<string, string>;\n } = {},\n ): Promise<T> {\n const token = await this.resolveToken();\n const { method = \"GET\", body, query } = options;\n\n let url = `${VercelApi.BASE}${path}`;\n if (query) {\n const params = new URLSearchParams(query);\n url += `?${params.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n\n const init: RequestInit = { method, headers };\n\n if (body) {\n headers[\"Content-Type\"] = \"application/json\";\n const validated = options.bodySchema\n ? this.alepha.codec.validate(options.bodySchema, body)\n : body;\n init.body = JSON.stringify(validated);\n }\n\n const response = await globalThis.fetch(url, init);\n\n // DELETE returns 204 with no body\n if (response.status === 204) {\n return undefined as T;\n }\n\n const json = await response.json();\n\n // Vercel error format: { error: { message, code } }\n if (json.error) {\n throw new AlephaError(\n `Vercel API error (${method} ${path}): ${json.error.message ?? JSON.stringify(json.error)}`,\n );\n }\n\n if (!response.ok) {\n throw new AlephaError(\n `Vercel API error (${method} ${path}): HTTP ${response.status}`,\n );\n }\n\n if (options.schema) {\n return this.alepha.codec.validate(options.schema, json) as T;\n }\n\n return json as T;\n }\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { AlephaCliUtils } from \"alepha/cli\";\nimport { EnvUtils, Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\nimport { PlatformCacheProvider } from \"../providers/PlatformCacheProvider.ts\";\nimport { VercelApi } from \"../services/VercelApi.ts\";\nimport { VercelCli } from \"../services/VercelCli.ts\";\nimport {\n type AppContext,\n PlatformAdapter,\n type PlatformContext,\n type PlatformState,\n} from \"./PlatformAdapter.ts\";\n\n/**\n * Vercel platform adapter.\n *\n * Uses the Vercel CLI for login and deploy (--prebuilt),\n * and the Vercel REST API for project management, env vars, and inspection.\n *\n * v1 scope: deploy pipeline only. No DB/storage/KV provisioning.\n */\nexport class VercelAdapter extends PlatformAdapter {\n protected readonly log = $logger();\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly shell = $inject(ShellProvider);\n protected readonly utils = $inject(AlephaCliUtils);\n protected readonly cache = $inject(PlatformCacheProvider);\n protected readonly alepha = $inject(Alepha);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly api = $inject(VercelApi);\n protected readonly vercelCli = $inject(VercelCli);\n protected readonly runner = $inject(Runner);\n\n /**\n * Vars that should not be pushed as env vars.\n * These are either handled by the build or are internal.\n */\n static readonly EXCLUDED_SECRET_KEYS = new Set([\"NODE_ENV\"]);\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // authenticate\n // -------------------------------------------------------------------------\n\n async authenticate(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n await run({\n name: \"authenticate\",\n handler: async () => {\n await this.vercelCli.ensureInstalled(ctx.root, run);\n\n let needsLogin = false;\n\n try {\n await this.vercelCli.getAuthToken();\n await this.vercelCli.whoami();\n } catch {\n needsLogin = true;\n }\n\n if (needsLogin) {\n run.pause();\n await this.vercelCli.login();\n run.resume();\n }\n\n if (await this.cache.isLoginFresh(ctx.root, \"vercel\")) {\n return;\n }\n\n await this.cache.recordLogin(ctx.root, \"vercel\");\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // build\n // -------------------------------------------------------------------------\n\n async build(ctx: AppContext, run: RunnerMethod): Promise<void> {\n const appDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path)\n : ctx.root;\n\n await run({\n name: \"alepha build -t vercel\",\n handler: async () => {\n await this.runShell(\"alepha build -t vercel\", {\n root: appDir,\n });\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // deploy\n // -------------------------------------------------------------------------\n\n async deploy(\n ctx: AppContext,\n run: RunnerMethod,\n ): Promise<string | undefined> {\n const distDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path, \"dist\")\n : this.fs.join(ctx.root, \"dist\");\n\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n\n let url: string | undefined;\n\n await run({\n name: `deploy ${ctx.app.name}`,\n handler: async () => {\n // Ensure project exists and has framework: null for prebuilt deploys\n let project = await this.api.getProject(projectName);\n if (!project) {\n project = await this.api.createProject(projectName);\n }\n await this.api.updateProject(projectName, { framework: null });\n\n // Write project.json so vercel CLI knows which project to deploy to\n const vercelDir = this.fs.join(distDir, \".vercel\");\n await this.fs.mkdir(vercelDir);\n await this.fs.writeFile(\n this.fs.join(vercelDir, \"project.json\"),\n JSON.stringify(\n {\n projectId: project.id,\n orgId: project.accountId,\n },\n null,\n 2,\n ),\n );\n\n // Use env token for deploy if available (CI)\n const token = process.env.VERCEL_TOKEN;\n\n await this.vercelCli.deploy(distDir, {\n prod: true,\n token,\n });\n\n // Resolve production URL from latest deployment alias\n const deployments = await this.api.listDeployments(project.id, {\n limit: 1,\n target: \"production\",\n });\n const latest = deployments[0];\n url = latest?.alias?.[0]\n ? `https://${latest.alias[0]}`\n : `https://${projectName}.vercel.app`;\n },\n });\n\n return url;\n }\n\n // -------------------------------------------------------------------------\n // secrets\n // -------------------------------------------------------------------------\n\n override async secrets(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n\n const vars: Array<{ key: string; value: string; target: string[] }> = [];\n for (const [key, value] of Object.entries(envVars)) {\n if (!value) continue;\n if (VercelAdapter.EXCLUDED_SECRET_KEYS.has(key)) continue;\n if (key.startsWith(\"VITE_\")) continue;\n vars.push({\n key,\n value,\n target: [\"production\", \"preview\"],\n });\n }\n\n if (vars.length === 0) {\n return;\n }\n\n for (const app of ctx.apps) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n await run({\n name: `push env vars to ${projectName}`,\n handler: async () => {\n await this.api.upsertEnvVars(projectName, vars);\n },\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // inspect\n // -------------------------------------------------------------------------\n\n async inspect(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<PlatformState> {\n const state: PlatformState = {\n workers: [],\n databases: [],\n buckets: [],\n kvNamespaces: [],\n queues: [],\n secrets: [],\n };\n\n const tasks: Array<{ name: string; handler: () => Promise<void> }> = [];\n\n // Projects/deployments (mapped to \"workers\" in PlatformState)\n for (const app of ctx.apps) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n tasks.push({\n name: `inspect project (${projectName})`,\n handler: async () => {\n const project = await this.api.getProject(projectName);\n if (!project) {\n state.workers.push({ name: projectName, exists: false });\n return;\n }\n\n const deployments = await this.api.listDeployments(project.id, {\n limit: 1,\n });\n const latest = deployments[0];\n\n state.workers.push({\n name: projectName,\n exists: true,\n version: latest?.uid,\n createdAt: latest?.created\n ? new Date(latest.created).toISOString()\n : undefined,\n });\n },\n });\n }\n\n // Env vars (mapped to \"secrets\")\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n const expectedVars = Object.keys(envVars).filter(\n (key) =>\n envVars[key] &&\n !VercelAdapter.EXCLUDED_SECRET_KEYS.has(key) &&\n !key.startsWith(\"VITE_\"),\n );\n\n if (expectedVars.length > 0) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.apps[0].name : undefined,\n );\n\n tasks.push({\n name: \"inspect env vars\",\n handler: async () => {\n try {\n const deployed = await this.api.listEnvVars(projectName);\n const deployedKeys = new Set(deployed.map((v) => v.key));\n for (const key of expectedVars) {\n state.secrets.push({\n name: key,\n deployed: deployedKeys.has(key),\n });\n }\n } catch {\n for (const key of expectedVars) {\n state.secrets.push({ name: key, deployed: false });\n }\n }\n },\n });\n }\n\n await run(tasks);\n\n return state;\n }\n\n // -------------------------------------------------------------------------\n // teardown\n // -------------------------------------------------------------------------\n\n async teardown(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n for (const app of ctx.apps) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n await run({\n name: `delete project ${projectName}`,\n handler: async () => {\n try {\n await this.api.deleteProject(projectName);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete project ${projectName}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n}\n","import { $atom, type Static, t } from \"alepha\";\n\n/**\n * Platform deployment configuration atom.\n *\n * Filled from the `platform` section of `alepha.config.ts`.\n * Read by `PlatformCommand` to resolve environments and adapters.\n */\nexport const platformOptions = $atom({\n name: \"alepha.cli.platform.options\",\n description: \"Platform deployment configuration\",\n schema: t.optional(\n t.object({\n /**\n * Project name override. Defaults to root package.json \"name\".\n */\n name: t.optional(t.text()),\n\n /**\n * Monorepo app paths relative to root. Omit for standalone apps.\n */\n apps: t.optional(t.array(t.text())),\n\n /**\n * Default environment when --env is omitted.\n *\n * @default \"production\"\n */\n default: t.optional(t.text()),\n\n /**\n * Secret store configuration for syncing .env secrets\n * to external providers (e.g. GitHub Actions environments).\n */\n secrets: t.optional(\n t.object({\n /**\n * Secret store backend.\n */\n store: t.enum([\"github\"]),\n\n /**\n * Pattern for resolving environment names in the store.\n * Placeholders: {project}, {env}.\n *\n * @default \"{project}-{env}\"\n */\n environmentPattern: t.optional(t.text()),\n }),\n ),\n\n /**\n * Named environments with their adapter and configuration.\n */\n environments: t.record(\n t.text({\n description:\n \"Environment name (e.g. 'production', 'staging', 'preview'). Used in resource naming and selected via --env.\",\n }),\n t.object({\n adapter: t.enum([\"cloudflare\", \"vercel\"]),\n /**\n * Custom domain for the deployed worker (e.g. \"api.example.com\").\n *\n * On Cloudflare this is attached as a custom-domain route.\n * Omit to use the adapter's default `*.workers.dev` / preview URL.\n */\n domain: t.optional(t.text()),\n /**\n * Cloudflare data jurisdiction for R2 buckets and D1 databases.\n * - \"eu\": data stays within the EU\n * - \"fedramp\": FedRAMP-authorized regions\n *\n * Omit for the default (global) jurisdiction.\n */\n jurisdiction: t.optional(t.enum([\"eu\", \"fedramp\"])),\n /**\n * Cloudflare account ID to deploy into.\n *\n * Falls back to `CLOUDFLARE_ACCOUNT_ID` env var, then to the\n * token's account when the token is scoped to exactly one.\n * Required when the token has access to multiple accounts.\n */\n accountId: t.optional(t.text()),\n }),\n ),\n }),\n ),\n});\n\n/**\n * Type for platform options.\n */\nexport type PlatformOptions = Static<typeof platformOptions.schema>;\n\n/**\n * Configuration for a single named environment.\n */\nexport interface EnvironmentConfig {\n adapter: \"cloudflare\" | \"vercel\";\n domain?: string;\n vars?: Record<string, string>;\n jurisdiction?: \"eu\" | \"fedramp\";\n accountId?: string;\n}\n","/**\n * Generates deterministic resource names for cloud deployments.\n *\n * Pattern: <project>-<env>[-<app>]\n *\n * All segments are slugified (lowercase, alphanumeric + dashes, max 63 chars).\n */\nexport class NamingService {\n public forContext(project: string, env: string): NamingContext {\n const prefix = `${this.slugify(project)}-${this.slugify(env)}`;\n return new NamingContext(prefix, this);\n }\n\n public slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 63);\n }\n}\n\nexport class NamingContext {\n protected readonly prefix: string;\n protected readonly naming: NamingService;\n\n constructor(prefix: string, naming: NamingService) {\n this.prefix = prefix;\n this.naming = naming;\n }\n\n public worker(app?: string): string {\n return app ? `${this.prefix}-${this.naming.slugify(app)}` : this.prefix;\n }\n\n public d1(): string {\n return this.prefix;\n }\n\n public hyperdrive(): string {\n return this.prefix;\n }\n\n public r2(): string {\n return this.prefix;\n }\n\n public kv(app?: string): string {\n return app ? `${this.prefix}-${this.naming.slugify(app)}` : this.prefix;\n }\n\n public queue(app?: string): string {\n return app ? `${this.prefix}-${this.naming.slugify(app)}` : this.prefix;\n }\n}\n","import { $inject, $state, Alepha, AlephaError } from \"alepha\";\nimport { Asker } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider } from \"alepha/system\";\nimport {\n type EnvironmentConfig,\n platformOptions,\n} from \"../atoms/platformOptions.ts\";\nimport { NamingService } from \"./NamingService.ts\";\n\nexport interface ResolvedPlatformConfig {\n project: string;\n defaultEnv: string;\n environments: Record<string, EnvironmentConfig>;\n isMonorepo: boolean;\n appPaths: string[];\n appNames: Map<string, string>;\n}\n\n/**\n * Reads platform config and resolves project topology.\n *\n * Validates project names, app paths, and environment configuration.\n * Does NOT introspect app code for resources — that happens at deploy time\n * via ViteBuildProvider.\n */\nexport class PlatformInspector {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly asker = $inject(Asker);\n protected readonly options = $state(platformOptions);\n protected readonly naming = $inject(NamingService);\n\n /**\n * Resolve and validate the full platform configuration.\n */\n public async resolveConfig(root: string): Promise<ResolvedPlatformConfig> {\n if (!this.options) {\n this.log.warn(` alepha.config.ts not found or missing platform config.\n\nPlease add a \"platform\" section to alepha.config.ts:\n\nexport default defineConfig({\n platform: {\n environments: {\n production: { adapter: \"cloudflare\" },\n },\n },\n});\n `);\n throw new AlephaError(\"Missing platform configuration.\");\n }\n\n // Re-read after potential wizard\n const opts = this.options;\n const platform = opts;\n\n // Resolve project name\n const project = await this.resolveProjectName(root, opts.name);\n\n // Resolve apps\n const appPaths = opts.apps ?? [];\n const isMonorepo = appPaths.length > 0;\n const appNames = new Map<string, string>();\n\n for (const appPath of appPaths) {\n const name = await this.resolveAppName(root, appPath);\n appNames.set(appPath, name);\n }\n\n return {\n project: this.naming.slugify(project),\n defaultEnv: platform.default ?? \"production\",\n environments: platform.environments as Record<string, EnvironmentConfig>,\n isMonorepo,\n appPaths,\n appNames,\n };\n }\n\n /**\n * Resolve a specific environment, validating it exists.\n */\n public async resolveEnvironment(\n root: string,\n envName: string,\n ): Promise<EnvironmentConfig> {\n const config = await this.resolveConfig(root);\n const envConfig = config.environments[envName];\n\n if (!envConfig) {\n const available = Object.keys(config.environments).join(\", \");\n throw new AlephaError(\n `Unknown environment \"${envName}\". Available: ${available}`,\n );\n }\n\n return envConfig;\n }\n\n protected async resolveProjectName(\n root: string,\n configName?: string,\n ): Promise<string> {\n if (configName) {\n return configName;\n }\n\n try {\n const pkgPath = this.fs.join(root, \"package.json\");\n const pkg = await this.fs.readJsonFile<{ name?: string }>(pkgPath);\n if (pkg.name) {\n return pkg.name;\n }\n } catch {}\n\n throw new AlephaError(\n 'Missing project name. Set \"name\" in alepha.config.ts or add a \"name\" field to package.json.',\n );\n }\n\n protected async resolveAppName(\n root: string,\n appPath: string,\n ): Promise<string> {\n const pkgPath = this.fs.join(root, appPath, \"package.json\");\n\n try {\n const pkg = await this.fs.readJsonFile<{ name?: string }>(pkgPath);\n if (pkg.name) {\n return this.naming.slugify(pkg.name);\n }\n } catch {}\n\n throw new AlephaError(\n `Missing \"name\" field in package.json for app at ${appPath}.`,\n );\n }\n}\n","import type { RunnerMethod } from \"alepha/command\";\nimport type { PlatformContext } from \"../adapters/PlatformAdapter.ts\";\n\n/**\n * Context passed to platform hooks.\n *\n * Extends PlatformContext with the fully-qualified base URL of the\n * deployed app (derived from `envConfig.domain` or the adapter's deploy\n * URL) and the active RunnerMethod.\n */\nexport interface PlatformHookContext extends PlatformContext {\n /**\n * Fully-qualified base URL of the deployed app, e.g. \"https://foo.com\".\n */\n baseUrl: string;\n run: RunnerMethod;\n}\n\n/**\n * Third-party provisioning hook for `alepha platform up` / `down`.\n *\n * Plugins can extend this to register resources in external services\n * (Stripe webhooks, Sentry projects, Resend domains, etc.) tied to a\n * deployment. Hooks are discovered via `alepha.services(PlatformHook)`,\n * so adding a plugin to `services: [...]` in `alepha.config.ts` is all\n * it takes to wire one in.\n *\n * Lifecycle:\n * - `register` runs after `deploy` and before `adapter.secrets()` so\n * any secret a hook writes to `.env.<env>` is picked up in the same\n * `up` cycle.\n * - `unregister` runs on `down` before `adapter.teardown()`.\n *\n * Implementations MUST be idempotent: `register` is called on every `up`.\n */\nexport abstract class PlatformHook {\n /**\n * Stable identifier. Used for log output.\n */\n abstract readonly name: string;\n\n /**\n * Create or update external resources. Must tolerate pre-existing state.\n */\n abstract register(ctx: PlatformHookContext): Promise<void>;\n\n /**\n * Remove external resources. Must tolerate missing state.\n */\n abstract unregister(ctx: PlatformHookContext): Promise<void>;\n}\n","import { $inject, Alepha, AlephaError } from \"alepha\";\nimport type { RunnerMethod } from \"alepha/command\";\nimport { $logger, ConsoleColorProvider } from \"alepha/logger\";\nimport { CloudflareAdapter } from \"../adapters/CloudflareAdapter.ts\";\nimport type {\n AppDefinition,\n PlatformAdapter,\n PlatformContext,\n PlatformState,\n} from \"../adapters/PlatformAdapter.ts\";\nimport { VercelAdapter } from \"../adapters/VercelAdapter.ts\";\nimport {\n PlatformHook,\n type PlatformHookContext,\n} from \"../hooks/PlatformHook.ts\";\nimport { type NamingContext, NamingService } from \"./NamingService.ts\";\nimport {\n PlatformInspector,\n type ResolvedPlatformConfig,\n} from \"./PlatformInspector.ts\";\n\n/**\n * Orchestrates platform lifecycle operations.\n *\n * Coordinates adapter calls in the correct order for\n * up (build -> migrate -> deploy), down, plan, and status.\n */\nexport class PlatformOrchestrator {\n protected readonly log = $logger();\n protected readonly color = $inject(ConsoleColorProvider);\n protected readonly inspector = $inject(PlatformInspector);\n protected readonly naming = $inject(NamingService);\n protected readonly cloudflareAdapter = $inject(CloudflareAdapter);\n protected readonly vercelAdapter = $inject(VercelAdapter);\n protected readonly alepha = $inject(Alepha);\n\n // -------------------------------------------------------------------------\n // Adapter resolution\n // -------------------------------------------------------------------------\n\n public resolveAdapter(adapterName: string): PlatformAdapter {\n switch (adapterName) {\n case \"cloudflare\":\n return this.cloudflareAdapter;\n case \"vercel\":\n return this.vercelAdapter;\n default:\n throw new AlephaError(`Unknown adapter: \"${adapterName}\"`);\n }\n }\n\n // -------------------------------------------------------------------------\n // up\n // -------------------------------------------------------------------------\n\n public async up(options: {\n root: string;\n env: string;\n app?: string;\n apps: AppDefinition[];\n run: RunnerMethod;\n }): Promise<void> {\n const { root, env, app: appFilter, apps, run } = options;\n const envConfig = await this.inspector.resolveEnvironment(root, env);\n const config = await this.inspector.resolveConfig(root);\n const adapter = this.resolveAdapter(envConfig.adapter);\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx: PlatformContext = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n // 1. Auth\n await adapter.authenticate(ctx, run);\n\n // 2. Filter apps\n const targetApps = appFilter\n ? apps.filter((a) => a.name === appFilter)\n : apps;\n\n if (targetApps.length === 0 && appFilter) {\n throw new AlephaError(\n `App \"${appFilter}\" not found. Available: ${apps.map((a) => a.name).join(\", \")}`,\n );\n }\n\n // 3. Provision (before build so resource IDs are available for wrangler config)\n await adapter.provision(ctx, run);\n\n // 4. Build\n for (const a of targetApps) {\n await adapter.build({ ...ctx, app: a }, run);\n }\n\n // 5. Migrate\n await adapter.migrate(ctx, run);\n\n // 6. Deploy\n const urls: string[] = [];\n for (const a of targetApps) {\n const url = await adapter.deploy({ ...ctx, app: a }, run);\n if (url) {\n urls.push(url);\n }\n }\n\n // 7. Platform hooks (register external resources: Stripe webhooks, etc.)\n // Run before secrets() so any secret a hook writes to .env.<env>\n // gets pushed to the deployed worker in the same up cycle.\n await this.runHooks(\"register\", ctx, urls, run);\n\n // 8. Secrets (push .env.{env} secrets to deployed workers)\n await adapter.secrets(ctx, run);\n\n run.end();\n\n const c = this.color;\n\n if (envConfig.domain) {\n this.log.info(\"\");\n this.log.info(\n ` ${c.set(\"GREEN\", \"\\u2192\")} ${c.set(\"CYAN\", `https://${envConfig.domain}`)}`,\n );\n this.log.info(\"\");\n } else {\n for (const url of urls) {\n this.log.info(\"\");\n this.log.info(` ${c.set(\"GREEN\", \"\\u2192\")} ${c.set(\"CYAN\", url)}`);\n this.log.info(\"\");\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // down\n // -------------------------------------------------------------------------\n\n public async down(options: {\n root: string;\n env: string;\n app?: string;\n apps: AppDefinition[];\n run: RunnerMethod;\n confirm: (prompt: string) => Promise<string>;\n }): Promise<boolean> {\n const { root, env, app: appFilter, apps, run, confirm } = options;\n const envConfig = await this.inspector.resolveEnvironment(root, env);\n const config = await this.inspector.resolveConfig(root);\n const adapter = this.resolveAdapter(envConfig.adapter);\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx: PlatformContext = {\n project: config.project,\n env,\n envConfig,\n apps: appFilter ? apps.filter((a) => a.name === appFilter) : apps,\n root,\n naming: namingCtx,\n };\n\n // Confirm (skip for tmp envs)\n if (!this.isTmpEnv(env)) {\n const answer = await confirm(`Type \"${env}\" to confirm teardown:`);\n\n if (answer !== env) {\n this.log.info(\"Aborted.\");\n return false;\n }\n }\n\n // Auth\n await adapter.authenticate(ctx, run);\n\n // Platform hooks (tear down external resources first, while creds still valid)\n await this.runHooks(\"unregister\", ctx, [], run);\n\n // Teardown\n await adapter.teardown(ctx, run);\n run.end();\n\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Platform hooks\n // -------------------------------------------------------------------------\n\n /**\n * Run all registered PlatformHook instances.\n *\n * Discovered dynamically via `alepha.services(PlatformHook)`: any plugin\n * that registers a PlatformHook subclass in its `$module.services`\n * participates automatically, without the core knowing about it.\n */\n protected async runHooks(\n phase: \"register\" | \"unregister\",\n ctx: PlatformContext,\n deployUrls: string[],\n run: RunnerMethod,\n ): Promise<void> {\n const hooks = this.alepha.services(PlatformHook);\n if (hooks.length === 0) return;\n\n const baseUrl = ctx.envConfig.domain\n ? `https://${ctx.envConfig.domain}`\n : deployUrls[0];\n\n if (!baseUrl) {\n this.log.debug(\"Skipping platform hooks: no base URL available\");\n return;\n }\n\n const hookCtx: PlatformHookContext = { ...ctx, baseUrl, run };\n\n for (const hook of hooks) {\n this.log.debug(`Platform hook: ${hook.name} (${phase})`);\n try {\n if (phase === \"register\") {\n await hook.register(hookCtx);\n } else {\n await hook.unregister(hookCtx);\n }\n } catch (err) {\n // unregister must never block teardown\n if (phase === \"unregister\") {\n this.log.debug(\n `Platform hook ${hook.name} failed to unregister: ${(err as Error).message}`,\n );\n } else {\n throw err;\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // plan\n // -------------------------------------------------------------------------\n\n public async plan(options: {\n root: string;\n env: string;\n apps: AppDefinition[];\n }): Promise<{\n config: ResolvedPlatformConfig;\n naming: NamingContext;\n apps: AppDefinition[];\n }> {\n const { root, env, apps } = options;\n const config = await this.inspector.resolveConfig(root);\n const namingCtx = this.naming.forContext(config.project, env);\n return { config, naming: namingCtx, apps };\n }\n\n // -------------------------------------------------------------------------\n // status\n // -------------------------------------------------------------------------\n\n public async status(options: {\n root: string;\n env: string;\n apps: AppDefinition[];\n run: RunnerMethod;\n }): Promise<{ config: ResolvedPlatformConfig; state: PlatformState }> {\n const { root, env, apps, run } = options;\n const envConfig = await this.inspector.resolveEnvironment(root, env);\n const config = await this.inspector.resolveConfig(root);\n const adapter = this.resolveAdapter(envConfig.adapter);\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx: PlatformContext = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n await adapter.authenticate(ctx, run);\n const state = await adapter.inspect(ctx, run);\n\n return { config, state };\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n public isTmpEnv(env: string): boolean {\n return env.startsWith(\"tmp\");\n }\n}\n","import { $inject, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\nimport type {\n RemoteSecret,\n SecretStoreProvider,\n} from \"./SecretStoreProvider.ts\";\n\n/**\n * GitHub Actions secret store backed by the `gh` CLI.\n *\n * Requires the GitHub CLI (`gh`) to be installed and authenticated.\n * Pushes secrets into GitHub Actions environments.\n */\nexport class GitHubSecretStore implements SecretStoreProvider {\n protected readonly log = $logger();\n protected readonly shell = $inject(ShellProvider);\n protected readonly fs = $inject(FileSystemProvider);\n\n /**\n * Verify that `gh` is installed and authenticated.\n */\n public async ensureAvailable(): Promise<void> {\n const installed = await this.shell.isInstalled(\"gh\");\n if (!installed) {\n throw new AlephaError(\n \"GitHub CLI (gh) is not installed. Install it from https://cli.github.com\",\n );\n }\n\n try {\n await this.shell.run(\"gh auth status\", { capture: true });\n } catch {\n throw new AlephaError(\n \"GitHub CLI is not authenticated. Run `gh auth login` first.\",\n );\n }\n }\n\n /**\n * Create the GitHub Actions environment if it doesn't exist.\n */\n public async ensureEnvironment(environment: string): Promise<void> {\n await this.shell.run(\n `gh api --method PUT /repos/{owner}/{repo}/environments/${environment} --silent`,\n { capture: true },\n );\n this.log.debug(`Ensured environment \"${environment}\" exists`);\n }\n\n /**\n * List all secrets in a GitHub Actions environment.\n */\n public async list(environment: string): Promise<RemoteSecret[]> {\n try {\n const output = await this.shell.run(\n `gh secret list --env ${environment} --json name,updatedAt`,\n { capture: true },\n );\n\n const parsed = JSON.parse(output || \"[]\") as Array<{\n name: string;\n updatedAt?: string;\n }>;\n\n return parsed.map((s) => ({\n name: s.name,\n updatedAt: s.updatedAt,\n }));\n } catch (error) {\n this.log.debug(\"Failed to list secrets\", { environment, error });\n return [];\n }\n }\n\n /**\n * Set a secret in a GitHub Actions environment.\n *\n * Writes a dotenv-formatted file and uses `gh secret set --env-file` to\n * avoid shell pipe issues with NodeShellProvider escaping the `|` character.\n */\n public async set(\n environment: string,\n key: string,\n value: string,\n ): Promise<void> {\n const tmpFile = `/tmp/alepha-secret-${key}-${Date.now()}`;\n const escaped = value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\");\n await this.fs.writeFile(tmpFile, `${key}=\"${escaped}\"\\n`);\n try {\n const output = await this.shell.run(\n `gh secret set -f ${tmpFile} --env ${environment}`,\n { capture: true },\n );\n this.log.debug(`Secret set: ${key}`, { output });\n } finally {\n await this.fs.rm(tmpFile);\n }\n }\n\n /**\n * Delete a secret from a GitHub Actions environment.\n */\n public async delete(environment: string, key: string): Promise<void> {\n await this.shell.run(`gh secret delete ${key} --env ${environment}`, {\n capture: true,\n });\n }\n}\n","/**\n * Filters environment variables for secret store syncing.\n *\n * Excludes platform-managed vars (NODE_ENV), build-time vars (VITE_*),\n * and empty values. Keeps everything else — including DATABASE_URL\n * and POSTGRES_SCHEMA which GitHub Actions needs.\n *\n * Also handles renaming GITHUB_* keys since GitHub Actions rejects\n * secret names starting with GITHUB_.\n */\nexport class SecretFilterService {\n protected static readonly EXCLUDED_KEYS = new Set([\"NODE_ENV\"]);\n protected static readonly GITHUB_PREFIX = \"GITHUB_\";\n protected static readonly REMOTE_PREFIX = \"APP_GITHUB_\";\n\n /**\n * Return only the entries that should be pushed to a secret store.\n */\n public filter(envVars: Record<string, string>): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(envVars)) {\n if (!value) continue;\n if (SecretFilterService.EXCLUDED_KEYS.has(key)) continue;\n if (key.startsWith(\"VITE_\")) continue;\n result[key] = value;\n }\n\n return result;\n }\n\n /**\n * Convert a local env key to a remote secret name.\n *\n * GITHUB_* keys are prefixed with APP_ since GitHub Actions rejects\n * secret names starting with GITHUB_.\n */\n public toRemoteName(key: string): string {\n if (key.startsWith(SecretFilterService.GITHUB_PREFIX)) {\n return `${SecretFilterService.REMOTE_PREFIX}${key.slice(SecretFilterService.GITHUB_PREFIX.length)}`;\n }\n return key;\n }\n\n /**\n * Convert a remote secret name back to the local env key.\n */\n public toLocalName(remoteName: string): string {\n if (remoteName.startsWith(SecretFilterService.REMOTE_PREFIX)) {\n return `${SecretFilterService.GITHUB_PREFIX}${remoteName.slice(SecretFilterService.REMOTE_PREFIX.length)}`;\n }\n return remoteName;\n }\n}\n","import { $inject, $state, AlephaError, t } from \"alepha\";\nimport { $command, EnvUtils } from \"alepha/command\";\nimport { $logger, ConsoleColorProvider } from \"alepha/logger\";\nimport { platformOptions } from \"../atoms/platformOptions.ts\";\nimport { GitHubSecretStore } from \"../providers/GitHubSecretStore.ts\";\nimport type { SecretStoreProvider } from \"../providers/SecretStoreProvider.ts\";\nimport { NamingService } from \"../services/NamingService.ts\";\nimport { PlatformInspector } from \"../services/PlatformInspector.ts\";\nimport { SecretFilterService } from \"../services/SecretFilterService.ts\";\n\nexport class SecretsCommand {\n protected readonly log = $logger();\n protected readonly options = $state(platformOptions);\n protected readonly inspector = $inject(PlatformInspector);\n protected readonly naming = $inject(NamingService);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly githubStore = $inject(GitHubSecretStore);\n protected readonly filter = $inject(SecretFilterService);\n protected readonly color = $inject(ConsoleColorProvider);\n\n protected readonly envFlags = t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n });\n\n // -----------------------------------------------------------------------\n // alepha p secrets list\n // -----------------------------------------------------------------------\n\n protected readonly list = $command({\n name: \"list\",\n aliases: [\"ls\"],\n description: \"List secrets in the remote store\",\n flags: t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n format: t.optional(\n t.text({\n aliases: [\"f\"],\n description: \"Output format: table (default), gha\",\n }),\n ),\n }),\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envName = this.resolveEnvironmentName(config.project, env);\n const format = flags.format ?? \"table\";\n\n const store = this.resolveStore();\n await store.ensureAvailable();\n const remoteSecrets = await store.list(envName);\n\n run.end();\n\n if (format === \"gha\") {\n process.stdout.write(\n `# Generated by alepha — environment: ${envName}\\n`,\n );\n process.stdout.write(\"env:\\n\");\n for (const secret of remoteSecrets) {\n const localName = this.filter.toLocalName(secret.name);\n process.stdout.write(\n ` ${localName}: \\${{ secrets.${secret.name} }}\\n`,\n );\n }\n return;\n }\n\n // table format\n const c = this.color;\n\n if (remoteSecrets.length === 0) {\n process.stdout.write(\n `\\nNo secrets in environment ${c.set(\"CYAN\", envName)}.\\n\\n`,\n );\n return;\n }\n\n process.stdout.write(\n `\\n${c.set(\"GREY_LIGHT\", \"Environment:\")} ${c.set(\"CYAN\", envName)}\\n\\n`,\n );\n\n const maxNameLen = Math.max(\n ...remoteSecrets.map((s) => s.name.length),\n 4,\n );\n\n process.stdout.write(\n ` ${c.set(\"GREY_LIGHT\", \"NAME\".padEnd(maxNameLen + 2))}${c.set(\"GREY_LIGHT\", \"UPDATED\")}\\n`,\n );\n\n for (const secret of remoteSecrets) {\n const updated = secret.updatedAt\n ? new Date(secret.updatedAt).toLocaleString()\n : \"-\";\n process.stdout.write(\n ` ${c.set(\"CYAN\", secret.name.padEnd(maxNameLen + 2))}${c.set(\"GREY_DARK\", updated)}\\n`,\n );\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p secrets diff\n // -----------------------------------------------------------------------\n\n protected readonly diff = $command({\n name: \"diff\",\n description: \"Compare local .env keys with remote store\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envName = this.resolveEnvironmentName(config.project, env);\n\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n const filtered = this.filter.filter(envVars);\n const localKeys = new Set(\n Object.keys(filtered).map((k) => this.filter.toRemoteName(k)),\n );\n\n const store = this.resolveStore();\n await store.ensureAvailable();\n const remoteSecrets = await store.list(envName);\n const remoteKeys = new Set(remoteSecrets.map((s) => s.name));\n\n run.end();\n\n const c = this.color;\n const allKeys = [...new Set([...localKeys, ...remoteKeys])].sort();\n\n process.stdout.write(\n `\\n${c.set(\"GREY_LIGHT\", \"Environment:\")} ${c.set(\"CYAN\", envName)}\\n\\n`,\n );\n\n let hasChanges = false;\n for (const key of allKeys) {\n const inLocal = localKeys.has(key);\n const inRemote = remoteKeys.has(key);\n\n if (inLocal && !inRemote) {\n process.stdout.write(` ${c.set(\"GREEN\", \"+\")} ${key}\\n`);\n hasChanges = true;\n } else if (!inLocal && inRemote) {\n process.stdout.write(` ${c.set(\"RED\", \"-\")} ${key}\\n`);\n hasChanges = true;\n } else {\n process.stdout.write(` ${c.set(\"GREY_DARK\", \"=\")} ${key}\\n`);\n }\n }\n\n if (!hasChanges) {\n process.stdout.write(\n ` ${c.set(\"GREEN\", \"Local and remote are in sync.\")}\\n`,\n );\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p secrets apply\n // -----------------------------------------------------------------------\n\n protected readonly apply = $command({\n name: \"apply\",\n description: \"Push local .env secrets to the remote store\",\n flags: t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n \"dry-run\": t.optional(\n t.boolean({\n description: \"Preview changes without pushing\",\n }),\n ),\n }),\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envName = this.resolveEnvironmentName(config.project, env);\n const dryRun = flags[\"dry-run\"] ?? false;\n\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n const filtered = this.filter.filter(envVars);\n const keys = Object.keys(filtered);\n\n if (keys.length === 0) {\n run.end();\n process.stdout.write(\"\\nNo secrets to push.\\n\\n\");\n return;\n }\n\n if (dryRun) {\n run.end();\n const c = this.color;\n process.stdout.write(\n `\\n${c.set(\"GREY_LIGHT\", \"Dry run — environment:\")} ${c.set(\"CYAN\", envName)}\\n\\n`,\n );\n for (const key of keys) {\n process.stdout.write(` ${c.set(\"GREEN\", \"+\")} ${key}\\n`);\n }\n process.stdout.write(\n `\\n ${keys.length} secret(s) would be pushed.\\n\\n`,\n );\n return;\n }\n\n const store = this.resolveStore();\n await store.ensureAvailable();\n await store.ensureEnvironment(envName);\n\n for (const key of keys) {\n const remoteName = this.filter.toRemoteName(key);\n await run({\n name: `push ${remoteName}`,\n handler: async () => {\n await store.set(envName, remoteName, filtered[key]);\n },\n });\n }\n\n run.end();\n process.stdout.write(\n `\\n${keys.length} secret(s) pushed to ${envName}.\\n`,\n );\n },\n });\n\n // -----------------------------------------------------------------------\n // Parent command\n // -----------------------------------------------------------------------\n\n public readonly secrets = $command({\n name: \"secrets\",\n aliases: [\"sec\"],\n description: \"Manage secrets in external stores\",\n children: [this.list, this.diff, this.apply],\n handler: async ({ help }) => {\n help();\n },\n });\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n public resolveStore(): SecretStoreProvider {\n const storeName = this.options?.secrets?.store ?? \"github\";\n switch (storeName) {\n case \"github\":\n return this.githubStore;\n default:\n throw new AlephaError(\n `Unknown secret store \"${storeName}\". Available: github`,\n );\n }\n }\n\n protected resolveEnvironmentName(project: string, env: string): string {\n const pattern =\n this.options?.secrets?.environmentPattern ?? \"{project}-{env}\";\n\n return pattern\n .replace(\"{project}\", this.naming.slugify(project))\n .replace(\"{env}\", this.naming.slugify(env));\n }\n}\n","import { $inject, $state, AlephaError, t } from \"alepha\";\nimport { AppEntryProvider, ViteBuildProvider } from \"alepha/cli\";\nimport { $command, EnvUtils } from \"alepha/command\";\nimport { $logger, ConsoleColorProvider } from \"alepha/logger\";\nimport { CloudflareAdapter } from \"../adapters/CloudflareAdapter.ts\";\nimport type {\n AppDefinition,\n DetectedResources,\n} from \"../adapters/PlatformAdapter.ts\";\nimport { VercelAdapter } from \"../adapters/VercelAdapter.ts\";\nimport { platformOptions } from \"../atoms/platformOptions.ts\";\nimport type {\n PlatformPlanOutput,\n PlatformStatusOutput,\n} from \"../schemas/platform.ts\";\nimport { NamingService } from \"../services/NamingService.ts\";\nimport {\n PlatformInspector,\n type ResolvedPlatformConfig,\n} from \"../services/PlatformInspector.ts\";\nimport { PlatformOrchestrator } from \"../services/PlatformOrchestrator.ts\";\nimport { SecretsCommand } from \"./SecretsCommand.ts\";\n\nexport class PlatformCommand {\n protected readonly log = $logger();\n protected readonly options = $state(platformOptions);\n protected readonly orchestrator = $inject(PlatformOrchestrator);\n protected readonly inspector = $inject(PlatformInspector);\n protected readonly naming = $inject(NamingService);\n protected readonly boot = $inject(AppEntryProvider);\n protected readonly viteBuild = $inject(ViteBuildProvider);\n protected readonly color = $inject(ConsoleColorProvider);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly secretsCommand = $inject(SecretsCommand);\n\n /**\n * Common flags for env/app targeting.\n */\n protected readonly envFlags = t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n app: t.optional(\n t.text({\n aliases: [\"a\"],\n description: \"Target specific app (monorepo)\",\n }),\n ),\n verbose: t.optional(\n t.boolean({\n aliases: [\"v\"],\n description: \"Verbose output\",\n }),\n ),\n json: t.optional(\n t.boolean({\n description: \"Output as JSON\",\n }),\n ),\n });\n\n // -----------------------------------------------------------------------\n // alepha p plan\n // -----------------------------------------------------------------------\n\n protected readonly plan = $command({\n name: \"plan\",\n description: \"Show project topology and resource names\",\n flags: this.envFlags,\n handler: async ({ flags, root }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapterName = envConfig?.adapter ?? \"cloudflare\";\n\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapterName),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n // --- Data collection ---\n\n const hasDB = apps.some((a) => a.resources.hasDatabase);\n const hasBucket = apps.some((a) => a.resources.hasBucket);\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n\n const resources: Array<{ label: string; value: string }> = [];\n\n const deployLabel = adapterName === \"vercel\" ? \"Project\" : \"Worker\";\n if (config.isMonorepo) {\n for (const app of apps) {\n resources.push({\n label: deployLabel,\n value: namingCtx.worker(app.name),\n });\n }\n } else {\n resources.push({ label: deployLabel, value: namingCtx.worker() });\n }\n\n if (adapterName === \"cloudflare\") {\n if (hasDB) {\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL;\n if (dbUrl?.startsWith(\"postgres:\")) {\n resources.push({\n label: \"Hyperdrive\",\n value: namingCtx.hyperdrive(),\n });\n } else {\n resources.push({ label: \"D1\", value: namingCtx.d1() });\n }\n }\n\n if (hasBucket) {\n resources.push({ label: \"R2\", value: namingCtx.r2() });\n }\n\n for (const app of apps) {\n if (app.resources.hasKV) {\n resources.push({\n label: \"KV\",\n value: namingCtx.kv(config.isMonorepo ? app.name : undefined),\n });\n }\n if (app.resources.hasQueue) {\n resources.push({\n label: \"Queue\",\n value: namingCtx.queue(config.isMonorepo ? app.name : undefined),\n });\n }\n }\n }\n\n const excludedKeys =\n adapterName === \"vercel\"\n ? VercelAdapter.EXCLUDED_SECRET_KEYS\n : CloudflareAdapter.EXCLUDED_SECRET_KEYS;\n const secretCount = Object.entries(envVars).filter(\n ([key, value]) =>\n value && !excludedKeys.has(key) && !key.startsWith(\"VITE_\"),\n ).length;\n\n // --- JSON output ---\n\n if (flags.json) {\n const environments: Record<\n string,\n { adapter: string; domain?: string }\n > = {};\n for (const [key, val] of Object.entries(config.environments)) {\n environments[key] = {\n adapter: val.adapter,\n ...(val.domain ? { domain: val.domain } : {}),\n };\n }\n\n const output: PlatformPlanOutput = {\n project: config.project,\n env,\n mode: config.isMonorepo ? \"monorepo\" : \"standalone\",\n apps: apps.map((a) => ({\n name: a.name,\n path: a.path,\n resources: a.resources,\n })),\n environments,\n resources,\n secretCount,\n };\n\n process.stdout.write(`${JSON.stringify(output, null, 2)}\\n`);\n return;\n }\n\n // --- Tree output ---\n\n const c = this.color;\n\n process.stdout.write(\n `\\n\\u{1F4E6} ${c.set(\"WHITE_BOLD\", config.project)} ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"CYAN\", env)}\\n\\n`,\n );\n\n if (config.isMonorepo) {\n process.stdout.write(\n ` ${c.set(\"GREY_LIGHT\", \"Mode:\")} monorepo (${config.appPaths.length} apps)\\n`,\n );\n for (const [i, appPath] of config.appPaths.entries()) {\n const appName = config.appNames.get(appPath) ?? appPath;\n const prefix =\n i === config.appPaths.length - 1\n ? \"\\u2514\\u2500\\u2500\"\n : \"\\u251C\\u2500\\u2500\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", prefix)} ${c.set(\"CYAN\", appName.padEnd(10))} ${c.set(\"GREY_DARK\", appPath)}\\n`,\n );\n }\n } else {\n process.stdout.write(` ${c.set(\"GREY_LIGHT\", \"Mode:\")} standalone\\n`);\n }\n\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Environments:\")}\\n`);\n const envKeys = Object.keys(config.environments);\n for (const [i, envKey] of envKeys.entries()) {\n const envConfig = config.environments[envKey];\n const prefix =\n i === envKeys.length - 1\n ? \"\\u2514\\u2500\\u2500\"\n : \"\\u251C\\u2500\\u2500\";\n const domain = envConfig.domain\n ? ` ${c.set(\"GREY_DARK\", envConfig.domain)}`\n : \"\";\n const marker = envKey === env ? ` ${c.set(\"GREEN\", \"\\u25C0\")}` : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", prefix)} ${c.set(\"CYAN\", envKey.padEnd(10))} ${c.set(\"GREY_LIGHT\", envConfig.adapter)}${domain}${marker}\\n`,\n );\n }\n\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Resources:\")}\\n`);\n\n if (secretCount > 0) {\n resources.push({\n label: \"Secrets\",\n value: `${secretCount} from .env.${env}`,\n });\n }\n\n for (const [i, res] of resources.entries()) {\n const isLast = i === resources.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"GREY_LIGHT\", res.label.padEnd(11))} ${c.set(\"CYAN\", res.value)}\\n`,\n );\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p up\n // -----------------------------------------------------------------------\n\n protected readonly up = $command({\n name: \"up\",\n mode: \"production\",\n description: \"Build, migrate, and deploy\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n process.env.NODE_ENV = \"production\";\n\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const adapter = config.environments[env]?.adapter ?? \"cloudflare\";\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapter),\n );\n\n await this.orchestrator.up({\n root,\n env,\n app: flags.app,\n apps,\n run,\n });\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p down\n // -----------------------------------------------------------------------\n\n protected readonly down = $command({\n name: \"down\",\n description: \"Tear down an environment\",\n flags: this.envFlags,\n handler: async ({ flags, root, run, ask }) => {\n if (!flags.env) {\n throw new AlephaError(\n \"--env is required for teardown. This command deletes resources.\",\n );\n }\n\n const config = await this.inspector.resolveConfig(root);\n const adapter = config.environments[flags.env]?.adapter ?? \"cloudflare\";\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapter),\n );\n\n await this.orchestrator.down({\n root,\n env: flags.env,\n app: flags.app,\n apps,\n run,\n confirm: async (prompt) => {\n ask.intro(\"Confirm teardown\");\n const value = await ask(prompt);\n ask.outro(\"\");\n return value;\n },\n });\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p status\n // -----------------------------------------------------------------------\n\n protected readonly status = $command({\n name: \"status\",\n aliases: [\"s\"],\n description: \"Show deployed state\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const adapter = config.environments[env]?.adapter ?? \"cloudflare\";\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapter),\n );\n\n const { state } = await this.orchestrator.status({\n root,\n env,\n apps,\n run,\n });\n\n // --- JSON output ---\n\n if (flags.json) {\n run.end();\n\n const output: PlatformStatusOutput = {\n project: config.project,\n env,\n adapter: config.environments[env].adapter,\n ...state,\n };\n\n process.stdout.write(`${JSON.stringify(output, null, 2)}\\n`);\n return;\n }\n\n // --- Tree output ---\n\n run.end();\n\n const c = this.color;\n\n process.stdout.write(\n `\\n\\u{1F4E6} ${c.set(\"WHITE_BOLD\", config.project)} ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"CYAN\", env)} ${c.set(\"GREY_DARK\", `(${config.environments[env].adapter})`)}\\n\\n`,\n );\n\n const hasDB = state.databases.length > 0;\n const hasBuckets = state.buckets.length > 0;\n\n process.stdout.write(` ${c.set(\"GREY_LIGHT\", \"Workers:\")}\\n`);\n for (const [i, w] of state.workers.entries()) {\n const isLast = i === state.workers.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (w.exists) {\n const versionShort = w.version?.slice(0, 8) ?? \"unknown\";\n const tag = w.tag ? ` ${c.set(\"GREY_DARK\", `(${w.tag})`)}` : \"\";\n const date = w.createdAt\n ? ` ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"GREY_DARK\", new Date(w.createdAt).toLocaleString())}`\n : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", w.name)} ${c.set(\"GREEN\", \"\\u2713\")} ${c.set(\"GREY_LIGHT\", versionShort)}${tag}${date}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", w.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not deployed\")}\\n`,\n );\n }\n }\n\n if (hasDB) {\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL;\n const dbLabel = dbUrl?.startsWith(\"postgres:\")\n ? \"Hyperdrive:\"\n : \"Database:\";\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", dbLabel)}\\n`);\n for (const [i, db] of state.databases.entries()) {\n const isLast = i === state.databases.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (db.exists) {\n const id = db.id\n ? ` ${c.set(\"GREY_LIGHT\", db.id.slice(0, 8))}`\n : \"\";\n const detail = db.detail\n ? ` ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"GREY_DARK\", db.detail.slice(0, 40))}`\n : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", db.name)} ${c.set(\"GREEN\", \"\\u2713\")}${id}${detail}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", db.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (hasBuckets) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Buckets:\")}\\n`);\n for (const [i, b] of state.buckets.entries()) {\n const isLast = i === state.buckets.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (b.exists) {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", b.name)} ${c.set(\"GREEN\", \"\\u2713\")}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", b.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (state.kvNamespaces.length > 0) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"KV:\")}\\n`);\n for (const [i, kv] of state.kvNamespaces.entries()) {\n const isLast = i === state.kvNamespaces.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (kv.exists) {\n const id = kv.id\n ? ` ${c.set(\"GREY_LIGHT\", kv.id.slice(0, 8))}`\n : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", kv.name)} ${c.set(\"GREEN\", \"\\u2713\")}${id}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", kv.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (state.queues.length > 0) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Queues:\")}\\n`);\n for (const [i, q] of state.queues.entries()) {\n const isLast = i === state.queues.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (q.exists) {\n const id = q.id ? ` ${c.set(\"GREY_LIGHT\", q.id.slice(0, 8))}` : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", q.name)} ${c.set(\"GREEN\", \"\\u2713\")}${id}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", q.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (state.secrets.length > 0) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Secrets:\")}\\n`);\n for (const [i, s] of state.secrets.entries()) {\n const isLast = i === state.secrets.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n const icon = s.deployed\n ? c.set(\"GREEN\", \"\\u2713\")\n : c.set(\"RED\", \"\\u2717\");\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", s.name)} ${icon}\\n`,\n );\n }\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // Granular commands\n // -----------------------------------------------------------------------\n\n protected readonly build = $command({\n name: \"build\",\n mode: \"production\",\n description: \"Build all apps locally\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n process.env.NODE_ENV = \"production\";\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapter = this.orchestrator.resolveAdapter(envConfig.adapter);\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(envConfig.adapter),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n const targets = flags.app\n ? apps.filter((a) => a.name === flags.app)\n : apps;\n\n for (const app of targets) {\n await adapter.build({ ...ctx, app }, run);\n }\n },\n });\n\n protected readonly deploy = $command({\n name: \"deploy\",\n description: \"Deploy apps to cloud\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapter = this.orchestrator.resolveAdapter(envConfig.adapter);\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(envConfig.adapter),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n await adapter.authenticate(ctx, run);\n\n const targets = flags.app\n ? apps.filter((a) => a.name === flags.app)\n : apps;\n\n for (const app of targets) {\n await adapter.deploy({ ...ctx, app }, run);\n }\n },\n });\n\n protected readonly migrate = $command({\n name: \"migrate\",\n description: \"Run database migrations\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapter = this.orchestrator.resolveAdapter(envConfig.adapter);\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(envConfig.adapter),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n await adapter.authenticate(ctx, run);\n await adapter.migrate(ctx, run);\n },\n });\n\n // -----------------------------------------------------------------------\n // Parent command\n // -----------------------------------------------------------------------\n\n public readonly platform = $command({\n name: \"platform\",\n aliases: [\"p\"],\n description: \"Cloud deployment orchestrator\",\n children: [\n this.plan,\n this.up,\n this.down,\n this.status,\n this.build,\n this.deploy,\n this.migrate,\n this.secretsCommand.secrets,\n ],\n handler: async ({ help, root }) => {\n await this.inspector.resolveConfig(root);\n help();\n },\n });\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n /**\n * Resolve app definitions.\n *\n * For standalone: returns a single app from the root.\n * For monorepo: resolves each app path, introspects for resources.\n *\n * NOTE: Resource detection (hasDatabase, hasBucket, etc.) requires\n * ViteBuildProvider.init() per app. This is expensive -- only done\n * for up/down/status, not for plan.\n */\n protected async resolveApps(\n root: string,\n config: ResolvedPlatformConfig,\n isServerless: boolean,\n ): Promise<AppDefinition[]> {\n if (!config.isMonorepo) {\n const entry = await this.boot.getAppEntry(root);\n if (isServerless) {\n process.env.ALEPHA_SERVERLESS = \"true\";\n }\n const appAlepha = await this.viteBuild.init({ entry });\n delete process.env.ALEPHA_SERVERLESS;\n const resources = this.detectResources(appAlepha);\n\n return [\n {\n name: config.project,\n path: \"\",\n entry,\n resources,\n },\n ];\n }\n\n const apps: AppDefinition[] = [];\n for (const appPath of config.appPaths) {\n const appRoot = `${root}/${appPath}`;\n const entry = await this.boot.getAppEntry(appRoot);\n if (isServerless) {\n process.env.ALEPHA_SERVERLESS = \"true\";\n }\n const appAlepha = await this.viteBuild.init({ entry });\n delete process.env.ALEPHA_SERVERLESS;\n const name = config.appNames.get(appPath) ?? appPath;\n const resources = this.detectResources(appAlepha);\n\n apps.push({ name, path: appPath, entry, resources });\n }\n\n return apps;\n }\n\n protected isServerless(adapter: string): boolean {\n return adapter === \"vercel\" || adapter === \"cloudflare\";\n }\n\n protected detectResources(alepha: any): DetectedResources {\n let hasDatabase = false;\n let hasBucket = false;\n let hasKV = false;\n let hasQueue = false;\n let hasCron = false;\n\n try {\n const repo = alepha.inject(\"RepositoryProvider\");\n hasDatabase = repo.getRepositories().length > 0;\n } catch {}\n\n try {\n const buckets = alepha.primitives(\"$bucket\");\n hasBucket = buckets.length > 0;\n } catch {}\n\n try {\n hasKV =\n alepha\n .primitives(\"cache\")\n .filter((it: any) => it.options?.provider !== \"memory\").length > 0;\n } catch {}\n\n try {\n hasQueue = alepha.primitives(\"queue\").length > 0;\n } catch {}\n\n try {\n const cron = alepha.inject(\"CronProvider\");\n hasCron = cron.getCronJobs().length > 0;\n } catch {}\n\n return { hasDatabase, hasBucket, hasKV, hasQueue, hasCron };\n }\n}\n","import { AlephaError } from \"alepha\";\nimport type {\n RemoteSecret,\n SecretStoreProvider,\n} from \"./SecretStoreProvider.ts\";\n\nexport interface MemorySecretStoreCall {\n method: \"ensureAvailable\" | \"ensureEnvironment\" | \"list\" | \"set\" | \"delete\";\n environment?: string;\n key?: string;\n value?: string;\n}\n\n/**\n * In-memory implementation of SecretStoreProvider for testing.\n * Records all operations and stores secrets in a nested Map.\n */\nexport class MemorySecretStore implements SecretStoreProvider {\n /**\n * Secrets keyed by environment, then by key.\n */\n public secrets = new Map<string, Map<string, string>>();\n\n /**\n * All recorded operations.\n */\n public calls: MemorySecretStoreCall[] = [];\n\n /**\n * When set, ensureAvailable() will throw with this message.\n */\n public availableError: string | null = null;\n\n public async ensureAvailable(): Promise<void> {\n this.calls.push({ method: \"ensureAvailable\" });\n if (this.availableError) {\n throw new AlephaError(this.availableError);\n }\n }\n\n public async ensureEnvironment(environment: string): Promise<void> {\n this.calls.push({ method: \"ensureEnvironment\", environment });\n if (!this.secrets.has(environment)) {\n this.secrets.set(environment, new Map());\n }\n }\n\n public async list(environment: string): Promise<RemoteSecret[]> {\n this.calls.push({ method: \"list\", environment });\n const envSecrets = this.secrets.get(environment);\n if (!envSecrets) return [];\n\n return Array.from(envSecrets.keys()).map((name) => ({ name }));\n }\n\n public async set(\n environment: string,\n key: string,\n value: string,\n ): Promise<void> {\n this.calls.push({ method: \"set\", environment, key, value });\n\n let envSecrets = this.secrets.get(environment);\n if (!envSecrets) {\n envSecrets = new Map();\n this.secrets.set(environment, envSecrets);\n }\n envSecrets.set(key, value);\n }\n\n public async delete(environment: string, key: string): Promise<void> {\n this.calls.push({ method: \"delete\", environment, key });\n this.secrets.get(environment)?.delete(key);\n }\n\n /**\n * Check if set() was called for a given environment and key.\n */\n public wasSet(environment: string, key: string): boolean {\n return this.calls.some(\n (c) =>\n c.method === \"set\" && c.environment === environment && c.key === key,\n );\n }\n\n /**\n * Check if delete() was called for a given environment and key.\n */\n public wasDeleted(environment: string, key: string): boolean {\n return this.calls.some(\n (c) =>\n c.method === \"delete\" && c.environment === environment && c.key === key,\n );\n }\n\n /**\n * Get all set() calls for a given environment.\n */\n public getSetCalls(\n environment: string,\n ): Array<{ key: string; value: string }> {\n return this.calls\n .filter((c) => c.method === \"set\" && c.environment === environment)\n .map((c) => ({ key: c.key!, value: c.value! }));\n }\n\n /**\n * Reset all state.\n */\n public reset(): void {\n this.secrets.clear();\n this.calls = [];\n this.availableError = null;\n }\n}\n","/**\n * A secret stored in a remote secret store.\n */\nexport interface RemoteSecret {\n name: string;\n updatedAt?: string;\n}\n\n/**\n * Abstract provider for managing secrets in an external store.\n *\n * Implementations: GitHubSecretStore, MemorySecretStore\n */\nexport abstract class SecretStoreProvider {\n /**\n * Verify the backing store is reachable and authenticated.\n */\n abstract ensureAvailable(): Promise<void>;\n\n /**\n * Ensure the target environment exists in the store, creating it if needed.\n */\n abstract ensureEnvironment(environment: string): Promise<void>;\n\n /**\n * List all secrets in a given environment.\n */\n abstract list(environment: string): Promise<RemoteSecret[]>;\n\n /**\n * Set (create or update) a secret in a given environment.\n */\n abstract set(environment: string, key: string, value: string): Promise<void>;\n\n /**\n * Delete a secret from a given environment.\n */\n abstract delete(environment: string, key: string): Promise<void>;\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\n// ---------------------------------------------------------------------------\n// Status output\n// ---------------------------------------------------------------------------\n\nexport const platformStatusWorkerSchema = t.object({\n name: t.string(),\n exists: t.boolean(),\n id: t.optional(t.string()),\n detail: t.optional(t.string()),\n version: t.optional(t.string()),\n tag: t.optional(t.string()),\n createdAt: t.optional(t.string()),\n});\n\nexport const platformStatusResourceSchema = t.object({\n name: t.string(),\n exists: t.boolean(),\n id: t.optional(t.string()),\n detail: t.optional(t.string()),\n});\n\nexport const platformStatusSecretSchema = t.object({\n name: t.string(),\n deployed: t.boolean(),\n});\n\nexport const platformStatusSchema = t.object({\n project: t.string(),\n env: t.string(),\n adapter: t.string(),\n workers: t.array(platformStatusWorkerSchema),\n databases: t.array(platformStatusResourceSchema),\n buckets: t.array(platformStatusResourceSchema),\n kvNamespaces: t.array(platformStatusResourceSchema),\n queues: t.array(platformStatusResourceSchema),\n secrets: t.array(platformStatusSecretSchema),\n});\n\nexport type PlatformStatusOutput = Static<typeof platformStatusSchema>;\n\n// ---------------------------------------------------------------------------\n// Plan output\n// ---------------------------------------------------------------------------\n\nexport const platformPlanAppResourcesSchema = t.object({\n hasDatabase: t.boolean(),\n hasBucket: t.boolean(),\n hasKV: t.boolean(),\n hasQueue: t.boolean(),\n hasCron: t.boolean(),\n});\n\nexport const platformPlanAppSchema = t.object({\n name: t.string(),\n path: t.string(),\n resources: platformPlanAppResourcesSchema,\n});\n\nexport const platformPlanEnvironmentSchema = t.object({\n adapter: t.string(),\n domain: t.optional(t.string()),\n});\n\nexport const platformPlanResourceSchema = t.object({\n label: t.string(),\n value: t.string(),\n});\n\nexport const platformPlanSchema = t.object({\n project: t.string(),\n env: t.string(),\n mode: t.enum([\"monorepo\", \"standalone\"]),\n apps: t.array(platformPlanAppSchema),\n environments: t.record(t.string(), platformPlanEnvironmentSchema),\n resources: t.array(platformPlanResourceSchema),\n secretCount: t.number(),\n});\n\nexport type PlatformPlanOutput = Static<typeof platformPlanSchema>;\n","import { $module } from \"alepha\";\nimport { AlephaCli } from \"alepha/cli\";\nimport { cliConfigPlugins } from \"alepha/cli/config\";\nimport { CloudflareAdapter } from \"./adapters/CloudflareAdapter.ts\";\nimport { VercelAdapter } from \"./adapters/VercelAdapter.ts\";\nimport {\n type PlatformOptions,\n platformOptions,\n} from \"./atoms/platformOptions.ts\";\nimport { PlatformCommand } from \"./commands/platform.ts\";\nimport { SecretsCommand } from \"./commands/SecretsCommand.ts\";\nimport { GitHubSecretStore } from \"./providers/GitHubSecretStore.ts\";\nimport { MemorySecretStore } from \"./providers/MemorySecretStore.ts\";\nimport { PlatformCacheProvider } from \"./providers/PlatformCacheProvider.ts\";\nimport { CloudflareApi } from \"./services/CloudflareApi.ts\";\nimport { NamingService } from \"./services/NamingService.ts\";\nimport { PlatformInspector } from \"./services/PlatformInspector.ts\";\nimport { PlatformOrchestrator } from \"./services/PlatformOrchestrator.ts\";\nimport { SecretFilterService } from \"./services/SecretFilterService.ts\";\nimport { VercelApi } from \"./services/VercelApi.ts\";\nimport { VercelCli } from \"./services/VercelCli.ts\";\nimport { WranglerApi } from \"./services/WranglerApi.ts\";\n\n// ---------------------------------------------------------------------------\n\ndeclare module \"alepha/cli/config\" {\n interface AlephaCliConfig {\n platform?: PlatformOptions;\n }\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * CLI plugin for multi-cloud deployment orchestration.\n *\n * Manages the full lifecycle of deploying Alepha apps: provision resources,\n * build, migrate databases, deploy, and sync secrets. Supports Cloudflare\n * Workers and Vercel.\n *\n * Commands:\n * - `alepha platform plan` — show project topology and resource names\n * - `alepha platform up` — full deployment pipeline\n * - `alepha platform down` — teardown an environment\n * - `alepha platform status` — inspect deployed resources\n * - `alepha platform build` — build apps locally\n * - `alepha platform deploy` — deploy to cloud\n * - `alepha platform migrate` — run database migrations\n * - `alepha platform secrets` — manage external secret stores\n *\n * Configuration in `alepha.config.ts`:\n *\n * ```typescript\n * import { AlephaCliPlatformPlugin } from \"alepha/cli/platform\";\n *\n * export default defineConfig({\n * services: [AlephaCliPlatformPlugin],\n * platform: {\n * environments: {\n * production: { adapter: \"cloudflare\", domain: \"myapp.com\" },\n * },\n * },\n * });\n * ```\n */\nexport const AlephaCliPlatformPlugin = $module({\n name: \"alepha.cli.plugins.platform\",\n services: [\n AlephaCli,\n PlatformCommand,\n SecretsCommand,\n CloudflareAdapter,\n CloudflareApi,\n VercelAdapter,\n VercelApi,\n VercelCli,\n WranglerApi,\n PlatformCacheProvider,\n GitHubSecretStore,\n MemorySecretStore,\n NamingService,\n SecretFilterService,\n PlatformInspector,\n PlatformOrchestrator,\n ],\n});\n\n// ---------------------------------------------------------------------------\n\ncliConfigPlugins.push((config, alepha) => {\n if (config.platform) {\n alepha.set(platformOptions, config.platform);\n }\n});\n\n// ---------------------------------------------------------------------------\n\nexport * from \"./adapters/CloudflareAdapter.ts\";\nexport * from \"./adapters/PlatformAdapter.ts\";\nexport * from \"./adapters/VercelAdapter.ts\";\nexport * from \"./atoms/platformOptions.ts\";\nexport * from \"./commands/platform.ts\";\nexport * from \"./commands/SecretsCommand.ts\";\nexport * from \"./hooks/PlatformHook.ts\";\nexport * from \"./providers/GitHubSecretStore.ts\";\nexport * from \"./providers/MemorySecretStore.ts\";\nexport * from \"./providers/PlatformCacheProvider.ts\";\nexport * from \"./providers/SecretStoreProvider.ts\";\nexport * from \"./schemas/cloudflare.ts\";\nexport * from \"./schemas/platform.ts\";\nexport * from \"./schemas/vercel.ts\";\nexport * from \"./services/CloudflareApi.ts\";\nexport * from \"./services/NamingService.ts\";\nexport * from \"./services/PlatformInspector.ts\";\nexport * from \"./services/PlatformOrchestrator.ts\";\nexport * from \"./services/SecretFilterService.ts\";\nexport * from \"./services/VercelApi.ts\";\nexport * from \"./services/VercelCli.ts\";\nexport * from \"./services/WranglerApi.ts\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["platform"],"sources":["../../../src/cli/platform/providers/PlatformCacheProvider.ts","../../../src/cli/platform/schemas/cloudflare.ts","../../../src/cli/platform/services/WranglerApi.ts","../../../src/cli/platform/services/CloudflareApi.ts","../../../src/cli/platform/adapters/PlatformAdapter.ts","../../../src/cli/platform/adapters/CloudflareAdapter.ts","../../../src/cli/platform/schemas/vercel.ts","../../../src/cli/platform/services/VercelCli.ts","../../../src/cli/platform/services/VercelApi.ts","../../../src/cli/platform/adapters/VercelAdapter.ts","../../../src/cli/platform/atoms/platformOptions.ts","../../../src/cli/platform/services/NamingService.ts","../../../src/cli/platform/services/PlatformInspector.ts","../../../src/cli/platform/hooks/PlatformHook.ts","../../../src/cli/platform/services/PlatformOrchestrator.ts","../../../src/cli/platform/providers/GitHubSecretStore.ts","../../../src/cli/platform/services/SecretFilterService.ts","../../../src/cli/platform/commands/SecretsCommand.ts","../../../src/cli/platform/commands/platform.ts","../../../src/cli/platform/providers/MemorySecretStore.ts","../../../src/cli/platform/providers/SecretStoreProvider.ts","../../../src/cli/platform/schemas/platform.ts","../../../src/cli/platform/index.ts"],"sourcesContent":["import { $inject } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { FileSystemProvider } from \"alepha/system\";\n\ninterface PlatformCache {\n [adapter: string]: {\n lastLoginCheck: number;\n accountId?: string;\n };\n}\n\n/**\n * Caches cloud provider login state to avoid slow auth checks.\n *\n * Stored in node_modules/.alepha/platform.json (gitignored, project-scoped).\n * TTL: 4 hours.\n */\nexport class PlatformCacheProvider {\n protected static readonly TTL_MS = 4 * 60 * 60 * 1000;\n\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly dateTime = $inject(DateTimeProvider);\n\n protected cachePath(root: string): string {\n return this.fs.join(root, \"node_modules\", \".alepha\", \"platform.json\");\n }\n\n public async isLoginFresh(root: string, adapter: string): Promise<boolean> {\n const cache = await this.readCache(root);\n const entry = cache[adapter];\n if (!entry) {\n return false;\n }\n const age = this.dateTime.nowMillis() - entry.lastLoginCheck;\n return age < PlatformCacheProvider.TTL_MS;\n }\n\n public async getAccountId(\n root: string,\n adapter: string,\n ): Promise<string | undefined> {\n const cache = await this.readCache(root);\n return cache[adapter]?.accountId;\n }\n\n public async recordLogin(\n root: string,\n adapter: string,\n accountId?: string,\n ): Promise<void> {\n const cache = await this.readCache(root);\n cache[adapter] = {\n lastLoginCheck: this.dateTime.nowMillis(),\n accountId,\n };\n await this.writeCache(root, cache);\n }\n\n protected async readCache(root: string): Promise<PlatformCache> {\n const path = this.cachePath(root);\n try {\n return await this.fs.readJsonFile<PlatformCache>(path);\n } catch {\n return {};\n }\n }\n\n protected async writeCache(\n root: string,\n cache: PlatformCache,\n ): Promise<void> {\n const path = this.cachePath(root);\n const lastSlash = path.lastIndexOf(\"/\");\n const dir = lastSlash > 0 ? path.slice(0, lastSlash) : path;\n await this.fs.mkdir(dir, { recursive: true }).catch(() => null);\n await this.fs.writeFile(path, JSON.stringify(cache, null, 2));\n }\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\n// ---------------------------------------------------------------------------\n// Account\n// ---------------------------------------------------------------------------\n\nexport const cloudflareAccountSchema = t.object({\n id: t.string(),\n name: t.string(),\n});\n\nexport type CloudflareAccount = Static<typeof cloudflareAccountSchema>;\n\n// ---------------------------------------------------------------------------\n// D1\n// ---------------------------------------------------------------------------\n\nexport const cloudflareD1Schema = t.object({\n uuid: t.string(),\n name: t.string(),\n});\n\nexport type CloudflareD1 = Static<typeof cloudflareD1Schema>;\n\n// ---------------------------------------------------------------------------\n// KV\n// ---------------------------------------------------------------------------\n\nexport const cloudflareKVSchema = t.object({\n id: t.string(),\n title: t.string(),\n});\n\nexport type CloudflareKV = Static<typeof cloudflareKVSchema>;\n\n// ---------------------------------------------------------------------------\n// R2\n// ---------------------------------------------------------------------------\n\nexport const cloudflareR2Schema = t.object({\n name: t.string(),\n creation_date: t.optional(t.string()),\n});\n\nexport type CloudflareR2 = Static<typeof cloudflareR2Schema>;\n\nexport const cloudflareR2ListSchema = t.object({\n buckets: t.array(cloudflareR2Schema),\n});\n\n// ---------------------------------------------------------------------------\n// Queue\n// ---------------------------------------------------------------------------\n\nexport const cloudflareQueueSchema = t.object({\n queue_id: t.string(),\n queue_name: t.string(),\n});\n\nexport type CloudflareQueue = Static<typeof cloudflareQueueSchema>;\n\nexport const cloudflareQueueConsumerSchema = t.object({\n consumer_id: t.string(),\n service: t.string(),\n environment: t.optional(t.string()),\n});\n\nexport type CloudflareQueueConsumer = Static<\n typeof cloudflareQueueConsumerSchema\n>;\n\n// ---------------------------------------------------------------------------\n// Hyperdrive\n// ---------------------------------------------------------------------------\n\nexport const cloudflareHyperdriveOriginSchema = t.object({\n host: t.string(),\n});\n\nexport const cloudflareHyperdriveSchema = t.object({\n id: t.string(),\n name: t.string(),\n origin: cloudflareHyperdriveOriginSchema,\n});\n\nexport type CloudflareHyperdrive = Static<typeof cloudflareHyperdriveSchema>;\n\n// ---------------------------------------------------------------------------\n// Worker\n// ---------------------------------------------------------------------------\n\nexport const cloudflareWorkerSchema = t.object({\n id: t.string(),\n created_on: t.string(),\n modified_on: t.string(),\n});\n\nexport type CloudflareWorker = Static<typeof cloudflareWorkerSchema>;\n\n// ---------------------------------------------------------------------------\n// Deployment\n// ---------------------------------------------------------------------------\n\nexport const cloudflareDeploymentVersionSchema = t.object({\n version_id: t.string(),\n percentage: t.number(),\n});\n\nexport const cloudflareDeploymentSchema = t.object({\n id: t.string(),\n versions: t.array(cloudflareDeploymentVersionSchema),\n created_on: t.string(),\n});\n\nexport type CloudflareDeployment = Static<typeof cloudflareDeploymentSchema>;\n\nexport const cloudflareDeploymentListSchema = t.object({\n deployments: t.array(cloudflareDeploymentSchema),\n});\n\n// ---------------------------------------------------------------------------\n// Version\n// ---------------------------------------------------------------------------\n\nexport const cloudflareVersionSchema = t.object({\n id: t.string(),\n metadata: t.object({\n created_on: t.string(),\n }),\n annotations: t.optional(t.record(t.string(), t.string())),\n});\n\nexport type CloudflareVersion = Static<typeof cloudflareVersionSchema>;\n\nexport const cloudflareVersionListSchema = t.object({\n items: t.array(cloudflareVersionSchema),\n});\n\n// ---------------------------------------------------------------------------\n// Secret\n// ---------------------------------------------------------------------------\n\nexport const cloudflareSecretSchema = t.object({\n name: t.string(),\n type: t.string(),\n});\n\nexport type CloudflareSecret = Static<typeof cloudflareSecretSchema>;\n\n// ---------------------------------------------------------------------------\n// Request bodies\n// ---------------------------------------------------------------------------\n\nexport const createD1BodySchema = t.object({\n name: t.string(),\n primary_location_hint: t.optional(t.string()),\n jurisdiction: t.optional(t.string()),\n});\n\nexport const createKVBodySchema = t.object({\n title: t.string(),\n});\n\nexport const createR2BodySchema = t.object({\n name: t.string(),\n});\n\nexport const createQueueBodySchema = t.object({\n queue_name: t.string(),\n});\n\nexport const createHyperdriveOriginSchema = t.object({\n scheme: t.string(),\n host: t.string(),\n port: t.number(),\n database: t.string(),\n user: t.string(),\n password: t.string(),\n});\n\nexport const createHyperdriveBodySchema = t.object({\n name: t.string(),\n origin: createHyperdriveOriginSchema,\n});\n\nexport const putSecretBodySchema = t.object({\n name: t.string(),\n text: t.string(),\n type: t.string(),\n});\n\n// ---------------------------------------------------------------------------\n// API envelope\n// ---------------------------------------------------------------------------\n\nexport const cloudflareApiErrorSchema = t.object({\n code: t.number(),\n message: t.string(),\n});\n\nexport type CloudflareApiError = Static<typeof cloudflareApiErrorSchema>;\n","import { $inject } from \"alepha\";\nimport { AlephaCliUtils, PackageManagerUtils } from \"alepha/cli\";\nimport { Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { ShellProvider } from \"alepha/system\";\n\n/**\n * Wraps wrangler CLI commands that are kept as shell-outs.\n *\n * Only used for operations where wrangler provides value\n * beyond a raw API call: OAuth login, worker deploy (bundling/upload),\n * D1 migrations, and secret bulk push.\n */\nexport class WranglerApi {\n protected readonly log = $logger();\n protected readonly shell = $inject(ShellProvider);\n protected readonly utils = $inject(AlephaCliUtils);\n protected readonly pm = $inject(PackageManagerUtils);\n protected readonly runner = $inject(Runner);\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Ensure wrangler is installed in the project.\n */\n public async ensureInstalled(root: string, run: RunnerMethod): Promise<void> {\n await this.pm.ensureDependency(root, \"wrangler\", {\n dev: true,\n exec: async (cmd, opts) => {\n run.pause();\n try {\n await this.utils.exec(cmd, opts);\n } finally {\n run.resume();\n }\n },\n });\n }\n\n /**\n * Check if the user is authenticated. Returns the whoami output.\n */\n public async whoami(): Promise<string> {\n return await this.runShell(\"wrangler whoami\", {\n resolve: true,\n capture: true,\n });\n }\n\n /**\n * Open the browser-based OAuth login flow.\n */\n public async login(): Promise<void> {\n await this.runShell(\"wrangler login\", { resolve: true });\n }\n\n /**\n * Get the current auth token from wrangler (auto-refreshes if expired).\n */\n public async getAuthToken(): Promise<string> {\n const output = await this.shell.run(\"wrangler auth token --json\", {\n resolve: true,\n capture: true,\n });\n\n const parsed = JSON.parse(output) as { type: string; token: string };\n return parsed.token;\n }\n\n // -------------------------------------------------------------------------\n // Deploy\n // -------------------------------------------------------------------------\n\n /**\n * Deploy a worker via wrangler (handles bundling and upload).\n *\n * Returns the workers.dev URL if found in the output.\n */\n public async deploy(\n workerName: string,\n configPath: string,\n ): Promise<string | undefined> {\n const output = await this.runShell(\n `wrangler deploy --name=${workerName} --no-bundle --config=${configPath}`,\n { resolve: true, capture: true },\n );\n\n const match = output.match(/https:\\/\\/[^\\s]*\\.workers\\.dev/);\n return match?.[0];\n }\n\n // -------------------------------------------------------------------------\n // D1 Migrations\n // -------------------------------------------------------------------------\n\n /**\n * Apply D1 migrations remotely.\n */\n public async d1MigrationsApply(\n dbName: string,\n configPath: string,\n ): Promise<void> {\n await this.runShell(\n `wrangler d1 migrations apply ${dbName} --remote --config=${configPath}`,\n { resolve: true, env: { CI: \"1\" } },\n );\n }\n}\n","import { $inject, Alepha, AlephaError, type TSchema, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type {\n CloudflareAccount,\n CloudflareApiError,\n CloudflareD1,\n CloudflareDeployment,\n CloudflareHyperdrive,\n CloudflareKV,\n CloudflareQueue,\n CloudflareQueueConsumer,\n CloudflareR2,\n CloudflareSecret,\n CloudflareVersion,\n CloudflareWorker,\n} from \"../schemas/cloudflare.ts\";\nimport {\n cloudflareAccountSchema,\n cloudflareD1Schema,\n cloudflareDeploymentListSchema,\n cloudflareHyperdriveSchema,\n cloudflareKVSchema,\n cloudflareQueueConsumerSchema,\n cloudflareQueueSchema,\n cloudflareR2Schema,\n cloudflareSecretSchema,\n cloudflareVersionSchema,\n cloudflareWorkerSchema,\n createD1BodySchema,\n createHyperdriveBodySchema,\n createKVBodySchema,\n createQueueBodySchema,\n createR2BodySchema,\n putSecretBodySchema,\n} from \"../schemas/cloudflare.ts\";\nimport { WranglerApi } from \"./WranglerApi.ts\";\n\nexport type {\n CloudflareD1,\n CloudflareDeployment,\n CloudflareHyperdrive,\n CloudflareKV,\n CloudflareQueue,\n CloudflareQueueConsumer,\n CloudflareR2,\n CloudflareSecret,\n CloudflareVersion,\n CloudflareWorker,\n};\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\n/**\n * Thin wrapper over the Cloudflare REST API.\n *\n * Uses `wrangler auth token` to obtain credentials,\n * then calls `fetch()` directly for all CRUD operations.\n */\nexport class CloudflareApi {\n protected static readonly BASE = \"https://api.cloudflare.com/client/v4\";\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly wrangler = $inject(WranglerApi);\n\n protected token?: string;\n protected accountId?: string;\n protected jurisdiction?: \"eu\" | \"fedramp\";\n\n /**\n * Set the Cloudflare data jurisdiction for R2 and D1 resources.\n *\n * R2 buckets and D1 databases created under a jurisdiction live in a\n * separate namespace — every R2 API call (list/create/delete) must include\n * the `cf-r2-jurisdiction` header, and D1 create must include the field\n * in the request body. Omit / pass `undefined` for the default (global).\n */\n public setJurisdiction(jurisdiction?: \"eu\" | \"fedramp\"): void {\n this.jurisdiction = jurisdiction;\n }\n\n /**\n * Override the Cloudflare account ID (from platform config).\n *\n * When unset, `resolveAccountId` falls back to `CLOUDFLARE_ACCOUNT_ID` env\n * var or the token's single account.\n */\n public setAccountId(accountId?: string): void {\n this.accountId = accountId;\n }\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Obtain the current auth token from wrangler.\n */\n public async resolveToken(): Promise<string> {\n if (this.token) {\n return this.token;\n }\n\n this.token = await this.wrangler.getAuthToken();\n return this.token;\n }\n\n /**\n * Resolve the Cloudflare account ID.\n *\n * Calls /accounts and picks the first one. Cached after first call.\n */\n public async resolveAccountId(): Promise<string> {\n if (this.accountId) {\n return this.accountId;\n }\n\n const fromEnv = process.env.CLOUDFLARE_ACCOUNT_ID;\n if (fromEnv) {\n this.accountId = fromEnv;\n return this.accountId;\n }\n\n const res = await this.fetch<CloudflareAccount[]>(\"/accounts\", {\n schema: t.array(cloudflareAccountSchema),\n });\n\n if (res.length === 0) {\n throw new AlephaError(\"No Cloudflare accounts found for this token.\");\n }\n\n if (res.length > 1) {\n const list = res.map((a) => ` - ${a.id} ${a.name}`).join(\"\\n\");\n throw new AlephaError(\n `Cloudflare token has access to ${res.length} accounts; set ` +\n `\\`CLOUDFLARE_ACCOUNT_ID\\` or the \\`accountId\\` field in your ` +\n `platform config to pick one:\\n${list}`,\n );\n }\n\n this.accountId = res[0].id;\n return this.accountId;\n }\n\n // -------------------------------------------------------------------------\n // D1\n // -------------------------------------------------------------------------\n\n public async listD1(): Promise<CloudflareD1[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareD1>(\n `/accounts/${accountId}/d1/database`,\n cloudflareD1Schema,\n );\n }\n\n public async createD1(\n name: string,\n location = \"weur\", // TODO: move to config (or auto-resolve based on account info, or ask ?)\n ): Promise<CloudflareD1> {\n const accountId = await this.resolveAccountId();\n // When jurisdiction is set, `primary_location_hint` is silently ignored\n // by the API, so omit it to avoid confusion.\n const body: Record<string, unknown> = { name };\n if (this.jurisdiction) {\n body.jurisdiction = this.jurisdiction;\n } else {\n body.primary_location_hint = location;\n }\n return await this.fetch<CloudflareD1>(\n `/accounts/${accountId}/d1/database`,\n {\n method: \"POST\",\n body,\n bodySchema: createD1BodySchema,\n schema: cloudflareD1Schema,\n },\n );\n }\n\n public async deleteD1(databaseId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/d1/database/${databaseId}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // KV\n // -------------------------------------------------------------------------\n\n public async listKV(): Promise<CloudflareKV[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareKV>(\n `/accounts/${accountId}/storage/kv/namespaces`,\n cloudflareKVSchema,\n 100, // KV list caps at 100 per page\n );\n }\n\n public async createKV(title: string): Promise<CloudflareKV> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareKV>(\n `/accounts/${accountId}/storage/kv/namespaces`,\n {\n method: \"POST\",\n body: { title },\n bodySchema: createKVBodySchema,\n schema: cloudflareKVSchema,\n },\n );\n }\n\n public async deleteKV(namespaceId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(\n `/accounts/${accountId}/storage/kv/namespaces/${namespaceId}`,\n { method: \"DELETE\" },\n );\n }\n\n // -------------------------------------------------------------------------\n // R2\n // -------------------------------------------------------------------------\n\n public async listR2(): Promise<CloudflareR2[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginateCursor<CloudflareR2>(\n `/accounts/${accountId}/r2/buckets`,\n \"buckets\",\n cloudflareR2Schema,\n );\n }\n\n public async createR2(name: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/r2/buckets`, {\n method: \"POST\",\n body: { name },\n bodySchema: createR2BodySchema,\n });\n }\n\n public async deleteR2(name: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/r2/buckets/${name}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // Queues\n // -------------------------------------------------------------------------\n\n public async listQueues(): Promise<CloudflareQueue[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareQueue>(\n `/accounts/${accountId}/queues`,\n cloudflareQueueSchema,\n );\n }\n\n public async createQueue(name: string): Promise<CloudflareQueue> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareQueue>(`/accounts/${accountId}/queues`, {\n method: \"POST\",\n body: { queue_name: name },\n bodySchema: createQueueBodySchema,\n schema: cloudflareQueueSchema,\n });\n }\n\n public async deleteQueue(queueId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/queues/${queueId}`, {\n method: \"DELETE\",\n });\n }\n\n public async listQueueConsumers(\n queueId: string,\n ): Promise<CloudflareQueueConsumer[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareQueueConsumer>(\n `/accounts/${accountId}/queues/${queueId}/consumers`,\n cloudflareQueueConsumerSchema,\n );\n }\n\n public async deleteQueueConsumer(\n queueId: string,\n consumerService: string,\n ): Promise<void> {\n const accountId = await this.resolveAccountId();\n const consumers = await this.listQueueConsumers(queueId);\n const consumer = consumers.find((c) => c.service === consumerService);\n if (!consumer) {\n return;\n }\n await this.fetch(\n `/accounts/${accountId}/queues/${queueId}/consumers/${consumer.consumer_id}`,\n { method: \"DELETE\" },\n );\n }\n\n // -------------------------------------------------------------------------\n // Hyperdrive\n // -------------------------------------------------------------------------\n\n public async listHyperdrive(): Promise<CloudflareHyperdrive[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginate<CloudflareHyperdrive>(\n `/accounts/${accountId}/hyperdrive/configs`,\n cloudflareHyperdriveSchema,\n );\n }\n\n public async createHyperdrive(\n name: string,\n connectionString: string,\n ): Promise<CloudflareHyperdrive> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareHyperdrive>(\n `/accounts/${accountId}/hyperdrive/configs`,\n {\n method: \"POST\",\n body: {\n name,\n origin: this.parseConnectionString(connectionString),\n },\n bodySchema: createHyperdriveBodySchema,\n schema: cloudflareHyperdriveSchema,\n },\n );\n }\n\n public async deleteHyperdrive(configId: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/hyperdrive/configs/${configId}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // Workers\n // -------------------------------------------------------------------------\n\n public async getWorker(\n scriptName: string,\n ): Promise<CloudflareWorker | undefined> {\n const accountId = await this.resolveAccountId();\n try {\n return await this.fetch<CloudflareWorker>(\n `/accounts/${accountId}/workers/scripts/${scriptName}`,\n { schema: cloudflareWorkerSchema },\n );\n } catch {\n return undefined;\n }\n }\n\n public async deleteWorker(scriptName: string): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(`/accounts/${accountId}/workers/scripts/${scriptName}`, {\n method: \"DELETE\",\n query: { force: \"true\" },\n });\n }\n\n public async listDeployments(\n scriptName: string,\n ): Promise<CloudflareDeployment[]> {\n const accountId = await this.resolveAccountId();\n // Deployments list is wrapped in `{ deployments }` and returns newest\n // first; for picking the active deployment we only need the top page.\n const res = await this.fetch<{ deployments: CloudflareDeployment[] }>(\n `/accounts/${accountId}/workers/scripts/${scriptName}/deployments`,\n { schema: cloudflareDeploymentListSchema, query: { per_page: \"100\" } },\n );\n return res.deployments;\n }\n\n public async listVersions(scriptName: string): Promise<CloudflareVersion[]> {\n const accountId = await this.resolveAccountId();\n return await this.paginateCursor<CloudflareVersion>(\n `/accounts/${accountId}/workers/scripts/${scriptName}/versions`,\n \"items\",\n cloudflareVersionSchema,\n );\n }\n\n // -------------------------------------------------------------------------\n // Secrets\n // -------------------------------------------------------------------------\n\n public async listSecrets(scriptName: string): Promise<CloudflareSecret[]> {\n const accountId = await this.resolveAccountId();\n return await this.fetch<CloudflareSecret[]>(\n `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`,\n { schema: t.array(cloudflareSecretSchema) },\n );\n }\n\n public async putSecret(\n scriptName: string,\n name: string,\n value: string,\n ): Promise<void> {\n const accountId = await this.resolveAccountId();\n await this.fetch(\n `/accounts/${accountId}/workers/scripts/${scriptName}/secrets`,\n {\n method: \"PUT\",\n body: { name, text: value, type: \"secret_text\" },\n bodySchema: putSecretBodySchema,\n },\n );\n }\n\n // -------------------------------------------------------------------------\n // Core fetch\n // -------------------------------------------------------------------------\n\n protected async fetch<T = unknown>(\n path: string,\n options: {\n method?: string;\n body?: unknown;\n bodySchema?: TSchema;\n schema?: TSchema;\n query?: Record<string, string>;\n } = {},\n ): Promise<T> {\n const token = await this.resolveToken();\n const { method = \"GET\", body, query } = options;\n\n let url = `${CloudflareApi.BASE}${path}`;\n if (query) {\n const params = new URLSearchParams(query);\n url += `?${params.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n\n if (this.jurisdiction && /\\/r2\\//.test(path)) {\n headers[\"cf-r2-jurisdiction\"] = this.jurisdiction;\n }\n\n const init: RequestInit = { method, headers };\n\n if (body) {\n headers[\"Content-Type\"] = \"application/json\";\n const validated = options.bodySchema\n ? this.alepha.codec.validate(options.bodySchema, body)\n : body;\n init.body = JSON.stringify(validated);\n }\n\n const response = await globalThis.fetch(url, init);\n const json = (await response.json()) as {\n success: boolean;\n result: T;\n errors: CloudflareApiError[];\n result_info?: {\n page: number;\n per_page: number;\n total_pages?: number;\n count?: number;\n total_count?: number;\n };\n };\n\n if (!json.success) {\n const messages = json.errors.map((e) => e.message).join(\", \");\n throw new AlephaError(\n `Cloudflare API error (${method} ${path}): ${messages}`,\n );\n }\n\n if (options.schema) {\n return this.alepha.codec.validate(options.schema, json.result) as T;\n }\n\n return json.result;\n }\n\n /**\n * Paginate a page-based list endpoint (`result_info.total_pages`).\n *\n * Cloudflare defaults to `per_page=20`; we push it to 1000 (max on most\n * list endpoints) and loop if more pages exist. Each page is validated\n * against the item schema.\n */\n protected async paginate<T>(\n path: string,\n itemSchema: TSchema,\n perPage = 1000,\n ): Promise<T[]> {\n const results: T[] = [];\n let page = 1;\n\n while (true) {\n const token = await this.resolveToken();\n const url = `${CloudflareApi.BASE}${path}?per_page=${perPage}&page=${page}`;\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n if (this.jurisdiction && /\\/r2\\//.test(path)) {\n headers[\"cf-r2-jurisdiction\"] = this.jurisdiction;\n }\n\n const response = await globalThis.fetch(url, { method: \"GET\", headers });\n const json = (await response.json()) as {\n success: boolean;\n result: T[];\n errors: CloudflareApiError[];\n result_info?: { page: number; total_pages?: number };\n };\n\n if (!json.success) {\n const messages = json.errors.map((e) => e.message).join(\", \");\n throw new AlephaError(\n `Cloudflare API error (GET ${path}): ${messages}`,\n );\n }\n\n const validated = this.alepha.codec.validate(\n t.array(itemSchema),\n json.result,\n ) as T[];\n results.push(...validated);\n\n const totalPages = json.result_info?.total_pages;\n if (!totalPages || page >= totalPages || validated.length === 0) {\n break;\n }\n page++;\n }\n\n return results;\n }\n\n /**\n * Paginate a cursor-based list endpoint where `result` is an object\n * containing both the items array and a `cursor` field (R2 buckets,\n * Workers versions). Returns the flattened item array.\n */\n protected async paginateCursor<T>(\n path: string,\n itemsKey: string,\n itemSchema: TSchema,\n perPage = 1000,\n ): Promise<T[]> {\n const results: T[] = [];\n let cursor: string | undefined;\n\n while (true) {\n const query: Record<string, string> = { per_page: String(perPage) };\n if (cursor) {\n query.cursor = cursor;\n }\n\n const res = await this.fetch<Record<string, unknown>>(path, { query });\n const items = (res[itemsKey] as unknown[]) ?? [];\n const validated = this.alepha.codec.validate(\n t.array(itemSchema),\n items,\n ) as T[];\n results.push(...validated);\n\n const nextCursor = res.cursor as string | undefined;\n if (!nextCursor || validated.length === 0) {\n break;\n }\n cursor = nextCursor;\n }\n\n return results;\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n /**\n * Parse a postgres:// connection string into Hyperdrive origin fields.\n */\n protected parseConnectionString(connectionString: string): {\n scheme: string;\n host: string;\n port: number;\n database: string;\n user: string;\n password: string;\n } {\n const url = new URL(connectionString);\n return {\n scheme: \"postgres\",\n host: url.hostname,\n port: Number(url.port) || 5432,\n database: url.pathname.slice(1),\n user: decodeURIComponent(url.username),\n password: decodeURIComponent(url.password),\n };\n }\n}\n","import type { AppEntry } from \"alepha/cli\";\nimport type { RunnerMethod } from \"alepha/command\";\nimport type { EnvironmentConfig } from \"../atoms/platformOptions.ts\";\nimport type { NamingContext } from \"../services/NamingService.ts\";\n\n// ---------------------------------------------------------------------------\n// Context types\n// ---------------------------------------------------------------------------\n\nexport interface DetectedResources {\n hasDatabase: boolean;\n hasBucket: boolean;\n hasKV: boolean;\n hasQueue: boolean;\n hasCron: boolean;\n}\n\nexport interface AppDefinition {\n /**\n * Slugified app name (from package.json).\n */\n name: string;\n\n /**\n * Relative path from root (e.g., \"apps/api\").\n * Empty string for standalone apps.\n */\n path: string;\n\n /**\n * Resolved entry points for this app.\n */\n entry: AppEntry;\n\n /**\n * Cloud resources detected by introspecting the app.\n */\n resources: DetectedResources;\n}\n\nexport interface PlatformContext {\n /**\n * Slugified project name (from root package.json or config).\n */\n project: string;\n\n /**\n * Environment key (e.g., \"production\", \"staging\", \"tmp-bug001\").\n */\n env: string;\n\n /**\n * Environment configuration from alepha.config.ts.\n */\n envConfig: EnvironmentConfig;\n\n /**\n * All apps in the project.\n */\n apps: AppDefinition[];\n\n /**\n * Monorepo/project root path.\n */\n root: string;\n\n /**\n * Resource name generator bound to this project+env.\n */\n naming: NamingContext;\n}\n\nexport interface AppContext extends PlatformContext {\n /**\n * The specific app being operated on.\n */\n app: AppDefinition;\n}\n\n// ---------------------------------------------------------------------------\n// State types (returned by inspect)\n// ---------------------------------------------------------------------------\n\nexport interface ResourceState {\n name: string;\n exists: boolean;\n id?: string;\n detail?: string;\n}\n\nexport interface WorkerState extends ResourceState {\n version?: string;\n tag?: string;\n createdAt?: string;\n}\n\nexport interface SecretState {\n name: string;\n deployed: boolean;\n}\n\nexport interface PlatformState {\n workers: WorkerState[];\n databases: ResourceState[];\n buckets: ResourceState[];\n kvNamespaces: ResourceState[];\n queues: ResourceState[];\n secrets: SecretState[];\n}\n\n// ---------------------------------------------------------------------------\n// Adapter contract\n// ---------------------------------------------------------------------------\n\n/**\n * Abstract platform adapter.\n *\n * Each cloud provider (Cloudflare, AKS, docker-compose) implements this.\n * The PlatformOrchestrator calls these methods in the correct order.\n */\nexport abstract class PlatformAdapter {\n /**\n * Ensure the user is authenticated with the cloud provider.\n * May use cached credentials to avoid slow checks.\n */\n abstract authenticate(ctx: PlatformContext, run: RunnerMethod): Promise<void>;\n\n /**\n * Build artifacts for a single app.\n */\n abstract build(ctx: AppContext, run: RunnerMethod): Promise<void>;\n\n /**\n * Deploy a single app (upload + activate atomically, e.g., wrangler deploy).\n * Returns the live URL if the platform provides one.\n */\n abstract deploy(\n ctx: AppContext,\n run: RunnerMethod,\n ): Promise<string | undefined>;\n\n /**\n * Create/ensure cloud resources exist (DB, buckets, queues).\n * Not all adapters provision -- AKS defers to Helm.\n */\n async provision(_ctx: PlatformContext, _run: RunnerMethod): Promise<void> {}\n\n /**\n * Run database migrations.\n */\n async migrate(_ctx: PlatformContext, _run: RunnerMethod): Promise<void> {}\n\n /**\n * Push runtime secrets to the deployed worker(s).\n *\n * Reads secrets from `.env.{env}` files (parsed, not from process.env),\n * filters out vars already handled by bindings (DATABASE_URL, R2, etc.),\n * and pushes the rest via the platform's secret management.\n */\n async secrets(_ctx: PlatformContext, _run: RunnerMethod): Promise<void> {}\n\n /**\n * Detect existing resources and their state.\n * Used by `plan` and `status` commands.\n */\n abstract inspect(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<PlatformState>;\n\n /**\n * Tear down all resources for an environment.\n */\n abstract teardown(ctx: PlatformContext, run: RunnerMethod): Promise<void>;\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { EnvUtils, Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\nimport { PlatformCacheProvider } from \"../providers/PlatformCacheProvider.ts\";\nimport { CloudflareApi } from \"../services/CloudflareApi.ts\";\nimport { WranglerApi } from \"../services/WranglerApi.ts\";\nimport {\n type AppContext,\n PlatformAdapter,\n type PlatformContext,\n type PlatformState,\n} from \"./PlatformAdapter.ts\";\n\n/**\n * Cloudflare Workers adapter.\n *\n * Uses the Cloudflare REST API (via CloudflareApi) for resource provisioning\n * and teardown, and wrangler CLI (via WranglerApi) for login, deploy,\n * D1 migrations, and secret bulk push.\n */\nexport class CloudflareAdapter extends PlatformAdapter {\n protected readonly log = $logger();\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly shell = $inject(ShellProvider);\n protected readonly cache = $inject(PlatformCacheProvider);\n protected readonly alepha = $inject(Alepha);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly api = $inject(CloudflareApi);\n protected readonly wrangler = $inject(WranglerApi);\n protected readonly runner = $inject(Runner);\n\n protected provisionedD1Id?: string;\n protected provisionedHyperdriveId?: string;\n protected provisionedKVIds = new Map<string, string>();\n\n /**\n * Check if the user's DATABASE_URL points to an external Postgres database.\n * If so, we use Hyperdrive instead of D1.\n *\n * Reads from `.env.{env}` first, falls back to `process.env`.\n */\n protected async isPostgres(ctx: PlatformContext): Promise<boolean> {\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL;\n return !!dbUrl?.startsWith(\"postgres:\");\n }\n\n /**\n * Propagate the environment's data-jurisdiction setting to the API client.\n *\n * Must be invoked at the top of every entry point (authenticate, build,\n * deploy, secrets, provision, migrate, inspect, teardown) because\n * CloudflareApi is a singleton reused across env invocations.\n */\n protected configureApi(ctx: PlatformContext): void {\n this.api.setJurisdiction(ctx.envConfig.jurisdiction);\n this.api.setAccountId(ctx.envConfig.accountId);\n }\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // authenticate\n // -------------------------------------------------------------------------\n\n async authenticate(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n this.configureApi(ctx);\n await run({\n name: \"authenticate\",\n handler: async () => {\n await this.wrangler.ensureInstalled(ctx.root, run);\n\n // Always validate the token — refresh tokens can expire between runs\n // even when the cache TTL hasn't elapsed.\n let needsLogin = false;\n\n try {\n await this.wrangler.getAuthToken();\n } catch {\n needsLogin = true;\n }\n\n if (needsLogin) {\n run.pause();\n await this.wrangler.login();\n run.resume();\n }\n\n // Skip account resolution if cache is fresh\n if (await this.cache.isLoginFresh(ctx.root, \"cloudflare\")) {\n return;\n }\n\n // Resolve account ID via REST API (typed, no regex)\n try {\n const accountId = await this.api.resolveAccountId();\n await this.cache.recordLogin(ctx.root, \"cloudflare\", accountId);\n } catch {\n await this.cache.recordLogin(ctx.root, \"cloudflare\");\n }\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // build\n // -------------------------------------------------------------------------\n\n async build(ctx: AppContext, run: RunnerMethod): Promise<void> {\n this.configureApi(ctx);\n const appDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path)\n : ctx.root;\n\n const env: Record<string, string> = {};\n\n if (ctx.app.resources.hasDatabase) {\n if (this.provisionedHyperdriveId) {\n env.HYPERDRIVE_ID = this.provisionedHyperdriveId;\n const envVars = await this.envUtils.parseEnv(ctx.root, [\n `.env.${ctx.env}`,\n ]);\n const pgSchema = envVars.POSTGRES_SCHEMA ?? process.env.POSTGRES_SCHEMA;\n if (pgSchema) {\n env.POSTGRES_SCHEMA = pgSchema;\n }\n } else if (this.provisionedD1Id) {\n const dbName = ctx.naming.d1();\n env.DATABASE_URL = `d1://${dbName}:${this.provisionedD1Id}`;\n }\n }\n\n if (ctx.app.resources.hasBucket) {\n env.R2_BUCKET_NAME = ctx.naming.r2();\n }\n\n if (ctx.app.resources.hasKV) {\n const kvName = ctx.naming.kv(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n env.CLOUDFLARE_KV_NAME = kvName;\n const kvId = this.provisionedKVIds.get(kvName);\n if (kvId) {\n env.CLOUDFLARE_KV_ID = kvId;\n }\n }\n\n if (ctx.app.resources.hasQueue) {\n env.CLOUDFLARE_QUEUE_NAME = ctx.naming.queue(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n }\n\n if (ctx.envConfig.domain) {\n env.CLOUDFLARE_DOMAIN = ctx.envConfig.domain;\n }\n\n if (ctx.envConfig.jurisdiction) {\n env.CLOUDFLARE_JURISDICTION = ctx.envConfig.jurisdiction;\n }\n\n await run({\n name: \"alepha build -t cloudflare\",\n handler: async () => {\n await this.runShell(\"alepha build -t cloudflare\", {\n root: appDir,\n env,\n });\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // deploy (wrangler — handles bundling/upload)\n // -------------------------------------------------------------------------\n\n async deploy(\n ctx: AppContext,\n run: RunnerMethod,\n ): Promise<string | undefined> {\n this.configureApi(ctx);\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n const distDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path, \"dist\")\n : this.fs.join(ctx.root, \"dist\");\n\n let url: string | undefined;\n\n await run({\n name: `deploy worker ${ctx.app.name}`,\n handler: async () => {\n url = await this.wrangler.deploy(\n workerName,\n `${distDir}/wrangler.jsonc`,\n );\n },\n });\n\n return url;\n }\n\n // -------------------------------------------------------------------------\n // secrets (wrangler — bulk push)\n // -------------------------------------------------------------------------\n\n /**\n * Vars that are handled by wrangler bindings or build config.\n * These should not be pushed as secrets.\n */\n static readonly EXCLUDED_SECRET_KEYS = new Set([\n \"DATABASE_URL\",\n \"R2_BUCKET_NAME\",\n \"CLOUDFLARE_DOMAIN\",\n \"CLOUDFLARE_JURISDICTION\",\n \"HYPERDRIVE_ID\",\n \"POSTGRES_SCHEMA\",\n \"NODE_ENV\",\n ]);\n\n override async secrets(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n this.configureApi(ctx);\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n\n // Filter out binding/build vars, VITE_* vars, and empty values\n const secrets: Record<string, string> = {};\n for (const [key, value] of Object.entries(envVars)) {\n if (!value) continue;\n if (CloudflareAdapter.EXCLUDED_SECRET_KEYS.has(key)) continue;\n if (key.startsWith(\"VITE_\")) continue;\n secrets[key] = value;\n }\n\n if (Object.keys(secrets).length === 0) {\n return;\n }\n\n // Push secrets to each worker via the REST API (one PUT per secret).\n // Historically we shelled out to `wrangler secret bulk`, but it has an\n // open hang issue (workers-sdk#10555) and is redundant given putSecret.\n for (const app of ctx.apps) {\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n await run({\n name: `push secrets to ${workerName}`,\n handler: async () => {\n for (const [name, value] of Object.entries(secrets)) {\n await this.api.putSecret(workerName, name, value);\n }\n },\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // provision (REST API)\n // -------------------------------------------------------------------------\n\n override async provision(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n this.configureApi(ctx);\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n const needsBucket = ctx.apps.some((a) => a.resources.hasBucket);\n const postgres = needsDB && (await this.isPostgres(ctx));\n\n const tasks: Array<{ name: string; handler: () => Promise<void> }> = [];\n\n if (needsDB) {\n if (postgres) {\n const hdName = ctx.naming.hyperdrive();\n const envVars = await this.envUtils.parseEnv(ctx.root, [\n `.env.${ctx.env}`,\n ]);\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL!;\n tasks.push({\n name: `provision hyperdrive (${hdName})`,\n handler: async () => {\n this.provisionedHyperdriveId = await this.ensureHyperdrive(\n hdName,\n dbUrl,\n );\n },\n });\n } else {\n const dbName = ctx.naming.d1();\n tasks.push({\n name: `provision d1 (${dbName})`,\n handler: async () => {\n this.provisionedD1Id = await this.ensureD1(dbName);\n },\n });\n }\n }\n\n if (needsBucket) {\n const bucketName = ctx.naming.r2();\n tasks.push({\n name: `provision r2 (${bucketName})`,\n handler: async () => {\n await this.ensureR2(bucketName);\n },\n });\n }\n\n for (const app of ctx.apps) {\n if (app.resources.hasKV) {\n const kvName = ctx.naming.kv(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `provision kv (${kvName})`,\n handler: async () => {\n this.provisionedKVIds.set(kvName, await this.ensureKV(kvName));\n },\n });\n }\n\n if (app.resources.hasQueue) {\n const queueName = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `provision queue (${queueName})`,\n handler: async () => {\n await this.ensureQueue(queueName);\n },\n });\n }\n }\n\n await run(tasks);\n }\n\n // -------------------------------------------------------------------------\n // migrate (wrangler — D1 migration runner)\n // -------------------------------------------------------------------------\n\n override async migrate(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n this.configureApi(ctx);\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n if (!needsDB) {\n return;\n }\n\n if (await this.isPostgres(ctx)) {\n await this.migratePostgres(ctx, run);\n } else {\n await this.migrateD1(ctx, run);\n }\n }\n\n protected async migrateD1(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n const dbName = ctx.naming.d1();\n\n await run({\n name: \"migrate d1\",\n handler: async () => {\n const migrationsDir = this.fs.join(ctx.root, \"migrations\", \"sqlite\");\n const dbUrl = this.provisionedD1Id\n ? `d1://${dbName}:${this.provisionedD1Id}`\n : `d1://${dbName}`;\n const env = { DATABASE_URL: dbUrl };\n\n if (await this.fs.exists(migrationsDir)) {\n await this.runShell(`alepha db migrations check --mode ${ctx.env}`, {\n resolve: true,\n env,\n });\n } else {\n await this.runShell(`alepha db migrations create --mode ${ctx.env}`, {\n resolve: true,\n env,\n });\n }\n\n // Copy migrations to dist for wrangler, apply, then clean up\n const distMigrations = this.fs.join(ctx.root, \"dist\", \"migrations\");\n await this.fs.cp(migrationsDir, distMigrations);\n\n await this.wrangler.d1MigrationsApply(dbName, \"dist/wrangler.jsonc\");\n\n await this.fs.rm(distMigrations, { recursive: true });\n },\n });\n }\n\n protected async migratePostgres(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n await run({\n name: \"migrate postgres\",\n handler: async () => {\n const envVars = await this.envUtils.parseEnv(ctx.root, [\n `.env.${ctx.env}`,\n ]);\n\n const env: Record<string, string> = {\n DATABASE_URL: envVars.DATABASE_URL ?? process.env.DATABASE_URL!,\n };\n\n if (envVars.POSTGRES_SCHEMA ?? process.env.POSTGRES_SCHEMA) {\n env.POSTGRES_SCHEMA = (envVars.POSTGRES_SCHEMA ??\n process.env.POSTGRES_SCHEMA)!;\n }\n\n await this.runShell(`alepha db migrations apply --mode ${ctx.env}`, {\n resolve: true,\n env,\n });\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // inspect (REST API)\n // -------------------------------------------------------------------------\n\n async inspect(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<PlatformState> {\n this.configureApi(ctx);\n const state: PlatformState = {\n workers: [],\n databases: [],\n buckets: [],\n kvNamespaces: [],\n queues: [],\n secrets: [],\n };\n\n const tasks: Array<{ name: string; handler: () => Promise<void> }> = [];\n\n // Workers\n for (const app of ctx.apps) {\n const name = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n tasks.push({\n name: `inspect worker (${name})`,\n handler: async () => {\n try {\n const deployment = await this.getActiveDeployment(name);\n if (deployment) {\n state.workers.push({\n name,\n exists: true,\n version: deployment.versionId,\n tag: deployment.tag,\n createdAt: deployment.createdAt,\n });\n } else {\n state.workers.push({ name, exists: false });\n }\n } catch {\n state.workers.push({ name, exists: false });\n }\n },\n });\n }\n\n // Database\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n if (needsDB) {\n if (await this.isPostgres(ctx)) {\n const hdName = ctx.naming.hyperdrive();\n tasks.push({\n name: `inspect hyperdrive (${hdName})`,\n handler: async () => {\n const configs = await this.api.listHyperdrive();\n const existing = configs.find((c) => c.name === hdName);\n state.databases.push({\n name: hdName,\n exists: !!existing,\n id: existing?.id,\n detail: existing?.origin.host,\n });\n },\n });\n } else {\n const dbName = ctx.naming.d1();\n tasks.push({\n name: `inspect d1 (${dbName})`,\n handler: async () => {\n const databases = await this.api.listD1();\n const existing = databases.find((db) => db.name === dbName);\n state.databases.push({\n name: dbName,\n exists: !!existing,\n id: existing?.uuid,\n });\n },\n });\n }\n }\n\n // R2\n const needsBucket = ctx.apps.some((a) => a.resources.hasBucket);\n if (needsBucket) {\n const bucketName = ctx.naming.r2();\n tasks.push({\n name: `inspect r2 (${bucketName})`,\n handler: async () => {\n const buckets = await this.api.listR2();\n const existing = buckets.find((b) => b.name === bucketName);\n state.buckets.push({\n name: bucketName,\n exists: !!existing,\n id: existing?.creation_date,\n });\n },\n });\n }\n\n // KV\n for (const app of ctx.apps) {\n if (app.resources.hasKV) {\n const kvName = ctx.naming.kv(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `inspect kv (${kvName})`,\n handler: async () => {\n const namespaces = await this.api.listKV();\n const existing = namespaces.find((ns) => ns.title === kvName);\n state.kvNamespaces.push({\n name: kvName,\n exists: !!existing,\n id: existing?.id,\n });\n },\n });\n }\n }\n\n // Queues\n for (const app of ctx.apps) {\n if (app.resources.hasQueue) {\n const queueName = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n tasks.push({\n name: `inspect queue (${queueName})`,\n handler: async () => {\n const queues = await this.api.listQueues();\n const existing = queues.find((q) => q.queue_name === queueName);\n state.queues.push({\n name: queueName,\n exists: !!existing,\n id: existing?.queue_id,\n });\n },\n });\n }\n }\n\n // Secrets\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n const expectedSecrets = Object.keys(envVars).filter(\n (key) =>\n envVars[key] &&\n !CloudflareAdapter.EXCLUDED_SECRET_KEYS.has(key) &&\n !key.startsWith(\"VITE_\"),\n );\n\n if (expectedSecrets.length > 0) {\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.apps[0].name : undefined,\n );\n tasks.push({\n name: \"inspect secrets\",\n handler: async () => {\n try {\n const deployed = await this.api.listSecrets(workerName);\n const deployedNames = new Set(deployed.map((s) => s.name));\n for (const key of expectedSecrets) {\n state.secrets.push({\n name: key,\n deployed: deployedNames.has(key),\n });\n }\n } catch {\n for (const key of expectedSecrets) {\n state.secrets.push({ name: key, deployed: false });\n }\n }\n },\n });\n }\n\n await run(tasks);\n\n return state;\n }\n\n // -------------------------------------------------------------------------\n // teardown (REST API)\n // -------------------------------------------------------------------------\n\n async teardown(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n this.configureApi(ctx);\n // 1. Remove queue consumers (must happen before worker or queue deletion)\n for (const app of ctx.apps) {\n if (app.resources.hasQueue) {\n const workerName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n const queueName = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n await run({\n name: `unbind queue consumer ${queueName}`,\n handler: async () => {\n try {\n const queues = await this.api.listQueues();\n const queue = queues.find((q) => q.queue_name === queueName);\n if (queue) {\n await this.api.deleteQueueConsumer(queue.queue_id, workerName);\n }\n } catch (error: any) {\n this.log.warn(\n `Failed to unbind queue consumer: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n\n // 2. Delete workers\n for (const app of ctx.apps) {\n const name = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n await run({\n name: `delete worker ${name}`,\n handler: async () => {\n try {\n await this.api.deleteWorker(name);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete worker ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n\n // 3. Delete queues (after worker is gone)\n for (const app of ctx.apps) {\n if (app.resources.hasQueue) {\n const name = ctx.naming.queue(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n await run({\n name: `delete queue ${name}`,\n handler: async () => {\n try {\n const queues = await this.api.listQueues();\n const queue = queues.find((q) => q.queue_name === name);\n if (!queue) {\n this.log.debug(`Queue ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteQueue(queue.queue_id);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete queue ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n\n // 4. Delete KV namespaces\n for (const app of ctx.apps) {\n if (app.resources.hasKV) {\n const name = ctx.naming.kv(ctx.apps.length > 1 ? app.name : undefined);\n await run({\n name: `delete kv ${name}`,\n handler: async () => {\n try {\n const namespaces = await this.api.listKV();\n const existing = namespaces.find((ns) => ns.title === name);\n if (!existing) {\n this.log.debug(`KV namespace ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteKV(existing.id);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete kv ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n\n // 5. Delete R2 bucket\n // TODO: empty bucket via S3-compatible API before deletion (needs native S3 client)\n // const needsBucket = ctx.apps.some((a) => a.resources.hasBucket);\n // if (needsBucket) {\n // const name = ctx.naming.r2();\n // await run({\n // name: `delete r2 ${name}`,\n // handler: async () => {\n // try {\n // await this.api.deleteR2(name);\n // } catch (error: any) {\n // const msg = String(error.message || \"\");\n // if (\n // msg.includes(\"does not exist\") ||\n // msg.includes(\"NoSuchBucket\")\n // ) {\n // // Already gone, nothing to do\n // } else if (\n // msg.includes(\"not empty\") ||\n // msg.includes(\"BucketNotEmpty\")\n // ) {\n // this.log.warn(\n // `Bucket ${name} is not empty -- skipped. Empty it manually.`,\n // );\n // } else {\n // this.log.warn(`Failed to delete r2 ${name}: ${msg}`);\n // }\n // }\n // },\n // });\n // }\n\n // 6. Delete D1 or Hyperdrive\n const needsDB = ctx.apps.some((a) => a.resources.hasDatabase);\n if (needsDB) {\n if (await this.isPostgres(ctx)) {\n const name = ctx.naming.hyperdrive();\n await run({\n name: `delete hyperdrive ${name}`,\n handler: async () => {\n try {\n const configs = await this.api.listHyperdrive();\n const existing = configs.find((c) => c.name === name);\n if (!existing) {\n this.log.debug(`Hyperdrive ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteHyperdrive(existing.id);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete hyperdrive ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n } else {\n const name = ctx.naming.d1();\n await run({\n name: `delete d1 ${name}`,\n handler: async () => {\n try {\n const databases = await this.api.listD1();\n const existing = databases.find((db) => db.name === name);\n if (!existing) {\n this.log.debug(`D1 database ${name} not found — skipping.`);\n return;\n }\n await this.api.deleteD1(existing.uuid);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete d1 ${name}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Resource helpers (REST API)\n // -------------------------------------------------------------------------\n\n protected async ensureD1(name: string): Promise<string> {\n const databases = await this.api.listD1();\n const existing = databases.find((db) => db.name === name);\n if (existing) {\n return existing.uuid;\n }\n\n const created = await this.api.createD1(name);\n return created.uuid;\n }\n\n protected async ensureHyperdrive(\n name: string,\n connectionString: string,\n ): Promise<string> {\n const configs = await this.api.listHyperdrive();\n const existing = configs.find((c) => c.name === name);\n if (existing) {\n return existing.id;\n }\n\n const created = await this.api.createHyperdrive(name, connectionString);\n return created.id;\n }\n\n protected async ensureR2(name: string): Promise<void> {\n const buckets = await this.api.listR2();\n const existing = buckets.find((b) => b.name === name);\n if (existing) {\n return;\n }\n\n await this.api.createR2(name);\n }\n\n protected async ensureKV(name: string): Promise<string> {\n const namespaces = await this.api.listKV();\n const existing = namespaces.find((ns) => ns.title === name);\n if (existing) {\n return existing.id;\n }\n\n const created = await this.api.createKV(name);\n return created.id;\n }\n\n protected async ensureQueue(name: string): Promise<void> {\n const queues = await this.api.listQueues();\n const existing = queues.find((q) => q.queue_name === name);\n if (existing) {\n return;\n }\n\n await this.api.createQueue(name);\n }\n\n /**\n * Get the currently active deployment for a worker.\n */\n protected async getActiveDeployment(\n workerName: string,\n ): Promise<\n { versionId: string; tag?: string; createdAt?: string } | undefined\n > {\n const deployments = await this.api.listDeployments(workerName);\n\n // API ordering is not guaranteed across releases — sort explicitly.\n const sorted = [...deployments].sort((a, b) =>\n b.created_on.localeCompare(a.created_on),\n );\n const latest = sorted[0];\n if (!latest?.versions?.[0]) {\n return undefined;\n }\n\n const activeVersionId = latest.versions[0].version_id;\n\n const versions = await this.api.listVersions(workerName);\n const version = versions.find((v) => v.id === activeVersionId);\n\n return {\n versionId: activeVersionId,\n tag: version?.annotations?.[\"workers/tag\"],\n createdAt: version?.metadata.created_on,\n };\n }\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\n// ---------------------------------------------------------------------------\n// Project\n// ---------------------------------------------------------------------------\n\nexport const vercelProjectSchema = t.object({\n id: t.string(),\n name: t.string(),\n accountId: t.string(),\n});\n\nexport type VercelProject = Static<typeof vercelProjectSchema>;\n\nexport const createProjectBodySchema = t.object({\n name: t.string(),\n framework: t.optional(t.null()),\n});\n\n// ---------------------------------------------------------------------------\n// Deployment\n// ---------------------------------------------------------------------------\n\nexport const vercelDeploymentSchema = t.object({\n uid: t.string(),\n name: t.string(),\n url: t.string(),\n state: t.optional(t.string()),\n readyState: t.optional(t.string()),\n created: t.optional(t.number()),\n target: t.optional(t.string()),\n alias: t.optional(t.array(t.string())),\n});\n\nexport type VercelDeployment = Static<typeof vercelDeploymentSchema>;\n\n// ---------------------------------------------------------------------------\n// Environment Variable\n// ---------------------------------------------------------------------------\n\nexport const vercelEnvVarSchema = t.object({\n id: t.string(),\n key: t.string(),\n value: t.optional(t.string()),\n type: t.string(),\n target: t.array(t.string()),\n});\n\nexport type VercelEnvVar = Static<typeof vercelEnvVarSchema>;\n\nexport const createEnvVarBodySchema = t.object({\n key: t.string(),\n value: t.string(),\n type: t.string(),\n target: t.array(t.string()),\n});\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { $inject, AlephaError } from \"alepha\";\nimport { AlephaCliUtils, PackageManagerUtils } from \"alepha/cli\";\nimport { Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\n\n/**\n * Wraps Vercel CLI commands and token management.\n *\n * Used for operations where the Vercel CLI provides value:\n * OAuth login, prebuilt deploy, and auth token extraction.\n */\nexport class VercelCli {\n protected readonly log = $logger();\n protected readonly shell = $inject(ShellProvider);\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly utils = $inject(AlephaCliUtils);\n protected readonly pm = $inject(PackageManagerUtils);\n protected readonly runner = $inject(Runner);\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // Install\n // -------------------------------------------------------------------------\n\n /**\n * Ensure vercel CLI is installed in the project.\n */\n public async ensureInstalled(root: string, run: RunnerMethod): Promise<void> {\n await this.pm.ensureDependency(root, \"vercel\", {\n dev: true,\n exec: async (cmd, opts) => {\n run.pause();\n try {\n await this.utils.exec(cmd, opts);\n } finally {\n run.resume();\n }\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Get the Vercel auth token.\n *\n * Priority:\n * 1. VERCEL_TOKEN environment variable (CI/CD)\n * 2. Vercel CLI auth.json file (local dev)\n */\n public async getAuthToken(): Promise<string> {\n const envToken = process.env.VERCEL_TOKEN;\n if (envToken) {\n return envToken;\n }\n\n const authPath = this.getAuthFilePath();\n if (!(await this.fs.exists(authPath))) {\n throw new AlephaError(\n \"Vercel auth token not found. Run `vercel login` or set VERCEL_TOKEN.\",\n );\n }\n\n const content = await this.fs.readFile(authPath);\n const parsed = JSON.parse(content.toString()) as { token?: string };\n\n if (!parsed.token) {\n throw new AlephaError(\n \"Vercel auth.json exists but contains no token. Run `vercel login`.\",\n );\n }\n\n return parsed.token;\n }\n\n /**\n * Validate the current auth token.\n */\n public async whoami(): Promise<string> {\n return await this.runShell(\"vercel whoami\", {\n resolve: true,\n capture: true,\n });\n }\n\n /**\n * Open the browser-based login flow.\n */\n public async login(): Promise<void> {\n await this.runShell(\"vercel login\", { resolve: true });\n }\n\n // -------------------------------------------------------------------------\n // Deploy\n // -------------------------------------------------------------------------\n\n /**\n * Deploy a prebuilt .vercel/output/ directory.\n *\n * Returns the deployment URL.\n */\n public async deploy(\n distDir: string,\n options: { prod?: boolean; token?: string },\n ): Promise<string | undefined> {\n const args = [\"vercel\", \"deploy\", \"--prebuilt\"];\n\n if (options.prod) {\n args.push(\"--prod\");\n }\n\n if (options.token) {\n args.push(`--token=${options.token}`);\n }\n\n const output = await this.runShell(args.join(\" \"), {\n resolve: true,\n capture: true,\n root: distDir,\n });\n\n // Vercel CLI outputs the deployment URL on the last non-empty line\n const lines = output.trim().split(\"\\n\");\n const url = lines\n .reverse()\n .find((line) => line.trim().startsWith(\"https://\"));\n return url?.trim();\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n /**\n * Resolve the path to Vercel CLI auth.json.\n */\n protected getAuthFilePath(): string {\n const os = platform();\n\n if (os === \"darwin\") {\n return join(\n homedir(),\n \"Library\",\n \"Application Support\",\n \"com.vercel.cli\",\n \"auth.json\",\n );\n }\n\n if (os === \"win32\") {\n return join(\n homedir(),\n \"AppData\",\n \"Roaming\",\n \"xdg.data\",\n \"com.vercel.cli\",\n \"auth.json\",\n );\n }\n\n // Linux / other\n return join(homedir(), \".local\", \"share\", \"com.vercel.cli\", \"auth.json\");\n }\n}\n","import { $inject, Alepha, AlephaError, type TSchema, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type {\n VercelDeployment,\n VercelEnvVar,\n VercelProject,\n} from \"../schemas/vercel.ts\";\nimport {\n createEnvVarBodySchema,\n createProjectBodySchema,\n vercelDeploymentSchema,\n vercelEnvVarSchema,\n vercelProjectSchema,\n} from \"../schemas/vercel.ts\";\nimport { VercelCli } from \"./VercelCli.ts\";\n\n/**\n * Thin wrapper over the Vercel REST API.\n *\n * Uses the auth token from VercelCli for all requests.\n */\nexport class VercelApi {\n protected static readonly BASE = \"https://api.vercel.com\";\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly vercelCli = $inject(VercelCli);\n\n protected token?: string;\n\n // -------------------------------------------------------------------------\n // Auth\n // -------------------------------------------------------------------------\n\n /**\n * Obtain the current auth token from the Vercel CLI.\n */\n public async resolveToken(): Promise<string> {\n if (this.token) {\n return this.token;\n }\n\n this.token = await this.vercelCli.getAuthToken();\n return this.token;\n }\n\n // -------------------------------------------------------------------------\n // Projects\n // -------------------------------------------------------------------------\n\n public async listProjects(): Promise<VercelProject[]> {\n const res = await this.fetch<{ projects: VercelProject[] }>(\n \"/v10/projects\",\n { schema: t.object({ projects: t.array(vercelProjectSchema) }) },\n );\n return res.projects;\n }\n\n public async getProject(\n nameOrId: string,\n ): Promise<VercelProject | undefined> {\n try {\n return await this.fetch<VercelProject>(\n `/v9/projects/${encodeURIComponent(nameOrId)}`,\n { schema: vercelProjectSchema },\n );\n } catch {\n return undefined;\n }\n }\n\n public async createProject(name: string): Promise<VercelProject> {\n return await this.fetch<VercelProject>(\"/v11/projects\", {\n method: \"POST\",\n body: { name, framework: null },\n bodySchema: createProjectBodySchema,\n schema: vercelProjectSchema,\n });\n }\n\n public async updateProject(\n nameOrId: string,\n settings: { framework?: null },\n ): Promise<void> {\n await this.fetch(`/v9/projects/${encodeURIComponent(nameOrId)}`, {\n method: \"PATCH\",\n body: settings,\n });\n }\n\n public async deleteProject(nameOrId: string): Promise<void> {\n await this.fetch(`/v9/projects/${encodeURIComponent(nameOrId)}`, {\n method: \"DELETE\",\n });\n }\n\n // -------------------------------------------------------------------------\n // Deployments\n // -------------------------------------------------------------------------\n\n public async listDeployments(\n projectId: string,\n options?: { limit?: number; target?: string },\n ): Promise<VercelDeployment[]> {\n const query: Record<string, string> = { projectId };\n if (options?.limit) {\n query.limit = String(options.limit);\n }\n if (options?.target) {\n query.target = options.target;\n }\n\n const res = await this.fetch<{ deployments: VercelDeployment[] }>(\n \"/v6/deployments\",\n {\n query,\n schema: t.object({ deployments: t.array(vercelDeploymentSchema) }),\n },\n );\n return res.deployments;\n }\n\n // -------------------------------------------------------------------------\n // Environment Variables\n // -------------------------------------------------------------------------\n\n public async listEnvVars(projectId: string): Promise<VercelEnvVar[]> {\n const res = await this.fetch<{ envs: VercelEnvVar[] }>(\n `/v10/projects/${encodeURIComponent(projectId)}/env`,\n {\n query: { decrypt: \"true\" },\n schema: t.object({ envs: t.array(vercelEnvVarSchema) }),\n },\n );\n return res.envs;\n }\n\n public async upsertEnvVars(\n projectId: string,\n vars: Array<{\n key: string;\n value: string;\n target: string[];\n }>,\n ): Promise<void> {\n for (const v of vars) {\n await this.fetch(`/v10/projects/${encodeURIComponent(projectId)}/env`, {\n method: \"POST\",\n query: { upsert: \"true\" },\n body: {\n key: v.key,\n value: v.value,\n type: \"encrypted\",\n target: v.target,\n },\n bodySchema: createEnvVarBodySchema,\n });\n }\n }\n\n public async deleteEnvVar(\n projectId: string,\n envVarId: string,\n ): Promise<void> {\n await this.fetch(\n `/v9/projects/${encodeURIComponent(projectId)}/env/${envVarId}`,\n { method: \"DELETE\" },\n );\n }\n\n // -------------------------------------------------------------------------\n // Core fetch\n // -------------------------------------------------------------------------\n\n protected async fetch<T = unknown>(\n path: string,\n options: {\n method?: string;\n body?: unknown;\n bodySchema?: TSchema;\n schema?: TSchema;\n query?: Record<string, string>;\n } = {},\n ): Promise<T> {\n const token = await this.resolveToken();\n const { method = \"GET\", body, query } = options;\n\n let url = `${VercelApi.BASE}${path}`;\n if (query) {\n const params = new URLSearchParams(query);\n url += `?${params.toString()}`;\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${token}`,\n };\n\n const init: RequestInit = { method, headers };\n\n if (body) {\n headers[\"Content-Type\"] = \"application/json\";\n const validated = options.bodySchema\n ? this.alepha.codec.validate(options.bodySchema, body)\n : body;\n init.body = JSON.stringify(validated);\n }\n\n const response = await globalThis.fetch(url, init);\n\n // DELETE returns 204 with no body\n if (response.status === 204) {\n return undefined as T;\n }\n\n const json = await response.json();\n\n // Vercel error format: { error: { message, code } }\n if (json.error) {\n throw new AlephaError(\n `Vercel API error (${method} ${path}): ${json.error.message ?? JSON.stringify(json.error)}`,\n );\n }\n\n if (!response.ok) {\n throw new AlephaError(\n `Vercel API error (${method} ${path}): HTTP ${response.status}`,\n );\n }\n\n if (options.schema) {\n return this.alepha.codec.validate(options.schema, json) as T;\n }\n\n return json as T;\n }\n}\n","import { $inject, Alepha } from \"alepha\";\nimport { AlephaCliUtils } from \"alepha/cli\";\nimport { EnvUtils, Runner, type RunnerMethod } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\nimport { PlatformCacheProvider } from \"../providers/PlatformCacheProvider.ts\";\nimport { VercelApi } from \"../services/VercelApi.ts\";\nimport { VercelCli } from \"../services/VercelCli.ts\";\nimport {\n type AppContext,\n PlatformAdapter,\n type PlatformContext,\n type PlatformState,\n} from \"./PlatformAdapter.ts\";\n\n/**\n * Vercel platform adapter.\n *\n * Uses the Vercel CLI for login and deploy (--prebuilt),\n * and the Vercel REST API for project management, env vars, and inspection.\n *\n * v1 scope: deploy pipeline only. No DB/storage/KV provisioning.\n */\nexport class VercelAdapter extends PlatformAdapter {\n protected readonly log = $logger();\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly shell = $inject(ShellProvider);\n protected readonly utils = $inject(AlephaCliUtils);\n protected readonly cache = $inject(PlatformCacheProvider);\n protected readonly alepha = $inject(Alepha);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly api = $inject(VercelApi);\n protected readonly vercelCli = $inject(VercelCli);\n protected readonly runner = $inject(Runner);\n\n /**\n * Vars that should not be pushed as env vars.\n * These are either handled by the build or are internal.\n */\n static readonly EXCLUDED_SECRET_KEYS = new Set([\"NODE_ENV\"]);\n\n protected async runShell(\n command: string,\n options: Parameters<ShellProvider[\"run\"]>[1] = {},\n ) {\n const capture = options.capture;\n const output = await this.shell.run(command, {\n ...options,\n capture: capture ?? this.runner.useDynamicLogger,\n });\n\n if (capture && !this.runner.useDynamicLogger) {\n this.log.info(output);\n }\n\n return output;\n }\n\n // -------------------------------------------------------------------------\n // authenticate\n // -------------------------------------------------------------------------\n\n async authenticate(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n await run({\n name: \"authenticate\",\n handler: async () => {\n await this.vercelCli.ensureInstalled(ctx.root, run);\n\n let needsLogin = false;\n\n try {\n await this.vercelCli.getAuthToken();\n await this.vercelCli.whoami();\n } catch {\n needsLogin = true;\n }\n\n if (needsLogin) {\n run.pause();\n await this.vercelCli.login();\n run.resume();\n }\n\n if (await this.cache.isLoginFresh(ctx.root, \"vercel\")) {\n return;\n }\n\n await this.cache.recordLogin(ctx.root, \"vercel\");\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // build\n // -------------------------------------------------------------------------\n\n async build(ctx: AppContext, run: RunnerMethod): Promise<void> {\n const appDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path)\n : ctx.root;\n\n await run({\n name: \"alepha build -t vercel\",\n handler: async () => {\n await this.runShell(\"alepha build -t vercel\", {\n root: appDir,\n });\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // deploy\n // -------------------------------------------------------------------------\n\n async deploy(\n ctx: AppContext,\n run: RunnerMethod,\n ): Promise<string | undefined> {\n const distDir = ctx.app.path\n ? this.fs.join(ctx.root, ctx.app.path, \"dist\")\n : this.fs.join(ctx.root, \"dist\");\n\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.app.name : undefined,\n );\n\n let url: string | undefined;\n\n await run({\n name: `deploy ${ctx.app.name}`,\n handler: async () => {\n // Ensure project exists and has framework: null for prebuilt deploys\n let project = await this.api.getProject(projectName);\n if (!project) {\n project = await this.api.createProject(projectName);\n }\n await this.api.updateProject(projectName, { framework: null });\n\n // Write project.json so vercel CLI knows which project to deploy to\n const vercelDir = this.fs.join(distDir, \".vercel\");\n await this.fs.mkdir(vercelDir);\n await this.fs.writeFile(\n this.fs.join(vercelDir, \"project.json\"),\n JSON.stringify(\n {\n projectId: project.id,\n orgId: project.accountId,\n },\n null,\n 2,\n ),\n );\n\n // Use env token for deploy if available (CI)\n const token = process.env.VERCEL_TOKEN;\n\n await this.vercelCli.deploy(distDir, {\n prod: true,\n token,\n });\n\n // Resolve production URL from latest deployment alias\n const deployments = await this.api.listDeployments(project.id, {\n limit: 1,\n target: \"production\",\n });\n const latest = deployments[0];\n url = latest?.alias?.[0]\n ? `https://${latest.alias[0]}`\n : `https://${projectName}.vercel.app`;\n },\n });\n\n return url;\n }\n\n // -------------------------------------------------------------------------\n // secrets\n // -------------------------------------------------------------------------\n\n override async secrets(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<void> {\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n\n const vars: Array<{ key: string; value: string; target: string[] }> = [];\n for (const [key, value] of Object.entries(envVars)) {\n if (!value) continue;\n if (VercelAdapter.EXCLUDED_SECRET_KEYS.has(key)) continue;\n if (key.startsWith(\"VITE_\")) continue;\n vars.push({\n key,\n value,\n target: [\"production\", \"preview\"],\n });\n }\n\n if (vars.length === 0) {\n return;\n }\n\n for (const app of ctx.apps) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n await run({\n name: `push env vars to ${projectName}`,\n handler: async () => {\n await this.api.upsertEnvVars(projectName, vars);\n },\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // inspect\n // -------------------------------------------------------------------------\n\n async inspect(\n ctx: PlatformContext,\n run: RunnerMethod,\n ): Promise<PlatformState> {\n const state: PlatformState = {\n workers: [],\n databases: [],\n buckets: [],\n kvNamespaces: [],\n queues: [],\n secrets: [],\n };\n\n const tasks: Array<{ name: string; handler: () => Promise<void> }> = [];\n\n // Projects/deployments (mapped to \"workers\" in PlatformState)\n for (const app of ctx.apps) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n tasks.push({\n name: `inspect project (${projectName})`,\n handler: async () => {\n const project = await this.api.getProject(projectName);\n if (!project) {\n state.workers.push({ name: projectName, exists: false });\n return;\n }\n\n const deployments = await this.api.listDeployments(project.id, {\n limit: 1,\n });\n const latest = deployments[0];\n\n state.workers.push({\n name: projectName,\n exists: true,\n version: latest?.uid,\n createdAt: latest?.created\n ? new Date(latest.created).toISOString()\n : undefined,\n });\n },\n });\n }\n\n // Env vars (mapped to \"secrets\")\n const envVars = await this.envUtils.parseEnv(ctx.root, [`.env.${ctx.env}`]);\n const expectedVars = Object.keys(envVars).filter(\n (key) =>\n envVars[key] &&\n !VercelAdapter.EXCLUDED_SECRET_KEYS.has(key) &&\n !key.startsWith(\"VITE_\"),\n );\n\n if (expectedVars.length > 0) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? ctx.apps[0].name : undefined,\n );\n\n tasks.push({\n name: \"inspect env vars\",\n handler: async () => {\n try {\n const deployed = await this.api.listEnvVars(projectName);\n const deployedKeys = new Set(deployed.map((v) => v.key));\n for (const key of expectedVars) {\n state.secrets.push({\n name: key,\n deployed: deployedKeys.has(key),\n });\n }\n } catch {\n for (const key of expectedVars) {\n state.secrets.push({ name: key, deployed: false });\n }\n }\n },\n });\n }\n\n await run(tasks);\n\n return state;\n }\n\n // -------------------------------------------------------------------------\n // teardown\n // -------------------------------------------------------------------------\n\n async teardown(ctx: PlatformContext, run: RunnerMethod): Promise<void> {\n for (const app of ctx.apps) {\n const projectName = ctx.naming.worker(\n ctx.apps.length > 1 ? app.name : undefined,\n );\n\n await run({\n name: `delete project ${projectName}`,\n handler: async () => {\n try {\n await this.api.deleteProject(projectName);\n } catch (error: any) {\n this.log.warn(\n `Failed to delete project ${projectName}: ${String(error.message || \"\")}`,\n );\n }\n },\n });\n }\n }\n}\n","import { $atom, type Static, t } from \"alepha\";\n\n/**\n * Platform deployment configuration atom.\n *\n * Filled from the `platform` section of `alepha.config.ts`.\n * Read by `PlatformCommand` to resolve environments and adapters.\n */\nexport const platformOptions = $atom({\n name: \"alepha.cli.platform.options\",\n description: \"Platform deployment configuration\",\n schema: t.optional(\n t.object({\n /**\n * Project name override. Defaults to root package.json \"name\".\n */\n name: t.optional(t.text()),\n\n /**\n * Monorepo app paths relative to root. Omit for standalone apps.\n */\n apps: t.optional(t.array(t.text())),\n\n /**\n * Default environment when --env is omitted.\n *\n * @default \"production\"\n */\n default: t.optional(t.text()),\n\n /**\n * Secret store configuration for syncing .env secrets\n * to external providers (e.g. GitHub Actions environments).\n */\n secrets: t.optional(\n t.object({\n /**\n * Secret store backend.\n */\n store: t.enum([\"github\"]),\n\n /**\n * Pattern for resolving environment names in the store.\n * Placeholders: {project}, {env}.\n *\n * @default \"{project}-{env}\"\n */\n environmentPattern: t.optional(t.text()),\n }),\n ),\n\n /**\n * Named environments with their adapter and configuration.\n */\n environments: t.record(\n t.text({\n description:\n \"Environment name (e.g. 'production', 'staging', 'preview'). Used in resource naming and selected via --env.\",\n }),\n t.object({\n adapter: t.enum([\"cloudflare\", \"vercel\"]),\n /**\n * Custom domain for the deployed worker (e.g. \"api.example.com\").\n *\n * On Cloudflare this is attached as a custom-domain route.\n * Omit to use the adapter's default `*.workers.dev` / preview URL.\n */\n domain: t.optional(t.text()),\n /**\n * Cloudflare data jurisdiction for R2 buckets and D1 databases.\n * - \"eu\": data stays within the EU\n * - \"fedramp\": FedRAMP-authorized regions\n *\n * Omit for the default (global) jurisdiction.\n */\n jurisdiction: t.optional(t.enum([\"eu\", \"fedramp\"])),\n /**\n * Cloudflare account ID to deploy into.\n *\n * Falls back to `CLOUDFLARE_ACCOUNT_ID` env var, then to the\n * token's account when the token is scoped to exactly one.\n * Required when the token has access to multiple accounts.\n */\n accountId: t.optional(t.text()),\n }),\n ),\n }),\n ),\n});\n\n/**\n * Type for platform options.\n */\nexport type PlatformOptions = Static<typeof platformOptions.schema>;\n\n/**\n * Configuration for a single named environment.\n */\nexport interface EnvironmentConfig {\n adapter: \"cloudflare\" | \"vercel\";\n domain?: string;\n vars?: Record<string, string>;\n jurisdiction?: \"eu\" | \"fedramp\";\n accountId?: string;\n}\n","/**\n * Generates deterministic resource names for cloud deployments.\n *\n * Pattern: <project>-<env>[-<app>]\n *\n * All segments are slugified (lowercase, alphanumeric + dashes, max 63 chars).\n */\nexport class NamingService {\n public forContext(project: string, env: string): NamingContext {\n const prefix = `${this.slugify(project)}-${this.slugify(env)}`;\n return new NamingContext(prefix, this);\n }\n\n public slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 63);\n }\n}\n\nexport class NamingContext {\n protected readonly prefix: string;\n protected readonly naming: NamingService;\n\n constructor(prefix: string, naming: NamingService) {\n this.prefix = prefix;\n this.naming = naming;\n }\n\n public worker(app?: string): string {\n return app ? `${this.prefix}-${this.naming.slugify(app)}` : this.prefix;\n }\n\n public d1(): string {\n return this.prefix;\n }\n\n public hyperdrive(): string {\n return this.prefix;\n }\n\n public r2(): string {\n return this.prefix;\n }\n\n public kv(app?: string): string {\n return app ? `${this.prefix}-${this.naming.slugify(app)}` : this.prefix;\n }\n\n public queue(app?: string): string {\n return app ? `${this.prefix}-${this.naming.slugify(app)}` : this.prefix;\n }\n}\n","import { $inject, $state, Alepha, AlephaError } from \"alepha\";\nimport { Asker } from \"alepha/command\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider } from \"alepha/system\";\nimport {\n type EnvironmentConfig,\n platformOptions,\n} from \"../atoms/platformOptions.ts\";\nimport { NamingService } from \"./NamingService.ts\";\n\nexport interface ResolvedPlatformConfig {\n project: string;\n defaultEnv: string;\n environments: Record<string, EnvironmentConfig>;\n isMonorepo: boolean;\n appPaths: string[];\n appNames: Map<string, string>;\n}\n\n/**\n * Reads platform config and resolves project topology.\n *\n * Validates project names, app paths, and environment configuration.\n * Does NOT introspect app code for resources — that happens at deploy time\n * via ViteBuildProvider.\n */\nexport class PlatformInspector {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly fs = $inject(FileSystemProvider);\n protected readonly asker = $inject(Asker);\n protected readonly options = $state(platformOptions);\n protected readonly naming = $inject(NamingService);\n\n /**\n * Resolve and validate the full platform configuration.\n */\n public async resolveConfig(root: string): Promise<ResolvedPlatformConfig> {\n if (!this.options) {\n this.log.warn(` alepha.config.ts not found or missing platform config.\n\nPlease add a \"platform\" section to alepha.config.ts:\n\nexport default defineConfig({\n platform: {\n environments: {\n production: { adapter: \"cloudflare\" },\n },\n },\n});\n `);\n throw new AlephaError(\"Missing platform configuration.\");\n }\n\n // Re-read after potential wizard\n const opts = this.options;\n const platform = opts;\n\n // Resolve project name\n const project = await this.resolveProjectName(root, opts.name);\n\n // Resolve apps\n const appPaths = opts.apps ?? [];\n const isMonorepo = appPaths.length > 0;\n const appNames = new Map<string, string>();\n\n for (const appPath of appPaths) {\n const name = await this.resolveAppName(root, appPath);\n appNames.set(appPath, name);\n }\n\n return {\n project: this.naming.slugify(project),\n defaultEnv: platform.default ?? \"production\",\n environments: platform.environments as Record<string, EnvironmentConfig>,\n isMonorepo,\n appPaths,\n appNames,\n };\n }\n\n /**\n * Resolve a specific environment, validating it exists.\n */\n public async resolveEnvironment(\n root: string,\n envName: string,\n ): Promise<EnvironmentConfig> {\n const config = await this.resolveConfig(root);\n const envConfig = config.environments[envName];\n\n if (!envConfig) {\n const available = Object.keys(config.environments).join(\", \");\n throw new AlephaError(\n `Unknown environment \"${envName}\". Available: ${available}`,\n );\n }\n\n return envConfig;\n }\n\n protected async resolveProjectName(\n root: string,\n configName?: string,\n ): Promise<string> {\n if (configName) {\n return configName;\n }\n\n try {\n const pkgPath = this.fs.join(root, \"package.json\");\n const pkg = await this.fs.readJsonFile<{ name?: string }>(pkgPath);\n if (pkg.name) {\n return pkg.name;\n }\n } catch {}\n\n throw new AlephaError(\n 'Missing project name. Set \"name\" in alepha.config.ts or add a \"name\" field to package.json.',\n );\n }\n\n protected async resolveAppName(\n root: string,\n appPath: string,\n ): Promise<string> {\n const pkgPath = this.fs.join(root, appPath, \"package.json\");\n\n try {\n const pkg = await this.fs.readJsonFile<{ name?: string }>(pkgPath);\n if (pkg.name) {\n return this.naming.slugify(pkg.name);\n }\n } catch {}\n\n throw new AlephaError(\n `Missing \"name\" field in package.json for app at ${appPath}.`,\n );\n }\n}\n","import type { RunnerMethod } from \"alepha/command\";\nimport type { PlatformContext } from \"../adapters/PlatformAdapter.ts\";\n\n/**\n * Context passed to platform hooks.\n *\n * Extends PlatformContext with the fully-qualified base URL of the\n * deployed app (derived from `envConfig.domain` or the adapter's deploy\n * URL) and the active RunnerMethod.\n */\nexport interface PlatformHookContext extends PlatformContext {\n /**\n * Fully-qualified base URL of the deployed app, e.g. \"https://foo.com\".\n */\n baseUrl: string;\n run: RunnerMethod;\n}\n\n/**\n * Third-party provisioning hook for `alepha platform up` / `down`.\n *\n * Plugins can extend this to register resources in external services\n * (Stripe webhooks, Sentry projects, Resend domains, etc.) tied to a\n * deployment. Hooks are discovered via `alepha.services(PlatformHook)`,\n * so adding a plugin to `services: [...]` in `alepha.config.ts` is all\n * it takes to wire one in.\n *\n * Lifecycle:\n * - `register` runs after `deploy` and before `adapter.secrets()` so\n * any secret a hook writes to `.env.<env>` is picked up in the same\n * `up` cycle.\n * - `unregister` runs on `down` before `adapter.teardown()`.\n *\n * Implementations MUST be idempotent: `register` is called on every `up`.\n */\nexport abstract class PlatformHook {\n /**\n * Stable identifier. Used for log output.\n */\n abstract readonly name: string;\n\n /**\n * Create or update external resources. Must tolerate pre-existing state.\n */\n abstract register(ctx: PlatformHookContext): Promise<void>;\n\n /**\n * Remove external resources. Must tolerate missing state.\n */\n abstract unregister(ctx: PlatformHookContext): Promise<void>;\n}\n","import { $inject, Alepha, AlephaError } from \"alepha\";\nimport type { RunnerMethod } from \"alepha/command\";\nimport { $logger, ConsoleColorProvider } from \"alepha/logger\";\nimport { CloudflareAdapter } from \"../adapters/CloudflareAdapter.ts\";\nimport type {\n AppDefinition,\n PlatformAdapter,\n PlatformContext,\n PlatformState,\n} from \"../adapters/PlatformAdapter.ts\";\nimport { VercelAdapter } from \"../adapters/VercelAdapter.ts\";\nimport {\n PlatformHook,\n type PlatformHookContext,\n} from \"../hooks/PlatformHook.ts\";\nimport { type NamingContext, NamingService } from \"./NamingService.ts\";\nimport {\n PlatformInspector,\n type ResolvedPlatformConfig,\n} from \"./PlatformInspector.ts\";\n\n/**\n * Orchestrates platform lifecycle operations.\n *\n * Coordinates adapter calls in the correct order for\n * up (build -> migrate -> deploy), down, plan, and status.\n */\nexport class PlatformOrchestrator {\n protected readonly log = $logger();\n protected readonly color = $inject(ConsoleColorProvider);\n protected readonly inspector = $inject(PlatformInspector);\n protected readonly naming = $inject(NamingService);\n protected readonly cloudflareAdapter = $inject(CloudflareAdapter);\n protected readonly vercelAdapter = $inject(VercelAdapter);\n protected readonly alepha = $inject(Alepha);\n\n // -------------------------------------------------------------------------\n // Adapter resolution\n // -------------------------------------------------------------------------\n\n public resolveAdapter(adapterName: string): PlatformAdapter {\n switch (adapterName) {\n case \"cloudflare\":\n return this.cloudflareAdapter;\n case \"vercel\":\n return this.vercelAdapter;\n default:\n throw new AlephaError(`Unknown adapter: \"${adapterName}\"`);\n }\n }\n\n // -------------------------------------------------------------------------\n // up\n // -------------------------------------------------------------------------\n\n public async up(options: {\n root: string;\n env: string;\n app?: string;\n apps: AppDefinition[];\n run: RunnerMethod;\n }): Promise<void> {\n const { root, env, app: appFilter, apps, run } = options;\n const envConfig = await this.inspector.resolveEnvironment(root, env);\n const config = await this.inspector.resolveConfig(root);\n const adapter = this.resolveAdapter(envConfig.adapter);\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx: PlatformContext = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n // 1. Auth\n await adapter.authenticate(ctx, run);\n\n // 2. Filter apps\n const targetApps = appFilter\n ? apps.filter((a) => a.name === appFilter)\n : apps;\n\n if (targetApps.length === 0 && appFilter) {\n throw new AlephaError(\n `App \"${appFilter}\" not found. Available: ${apps.map((a) => a.name).join(\", \")}`,\n );\n }\n\n // 3. Provision (before build so resource IDs are available for wrangler config)\n await adapter.provision(ctx, run);\n\n // 4. Build\n for (const a of targetApps) {\n await adapter.build({ ...ctx, app: a }, run);\n }\n\n // 5. Migrate\n await adapter.migrate(ctx, run);\n\n // 6. Deploy\n const urls: string[] = [];\n for (const a of targetApps) {\n const url = await adapter.deploy({ ...ctx, app: a }, run);\n if (url) {\n urls.push(url);\n }\n }\n\n // 7. Platform hooks (register external resources: Stripe webhooks, etc.)\n // Run before secrets() so any secret a hook writes to .env.<env>\n // gets pushed to the deployed worker in the same up cycle.\n await this.runHooks(\"register\", ctx, urls, run);\n\n // 8. Secrets (push .env.{env} secrets to deployed workers)\n await adapter.secrets(ctx, run);\n\n run.end();\n\n const c = this.color;\n\n if (envConfig.domain) {\n this.log.info(\"\");\n this.log.info(\n ` ${c.set(\"GREEN\", \"\\u2192\")} ${c.set(\"CYAN\", `https://${envConfig.domain}`)}`,\n );\n this.log.info(\"\");\n } else {\n for (const url of urls) {\n this.log.info(\"\");\n this.log.info(` ${c.set(\"GREEN\", \"\\u2192\")} ${c.set(\"CYAN\", url)}`);\n this.log.info(\"\");\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // down\n // -------------------------------------------------------------------------\n\n public async down(options: {\n root: string;\n env: string;\n app?: string;\n apps: AppDefinition[];\n run: RunnerMethod;\n confirm: (prompt: string) => Promise<string>;\n }): Promise<boolean> {\n const { root, env, app: appFilter, apps, run, confirm } = options;\n const envConfig = await this.inspector.resolveEnvironment(root, env);\n const config = await this.inspector.resolveConfig(root);\n const adapter = this.resolveAdapter(envConfig.adapter);\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx: PlatformContext = {\n project: config.project,\n env,\n envConfig,\n apps: appFilter ? apps.filter((a) => a.name === appFilter) : apps,\n root,\n naming: namingCtx,\n };\n\n // Confirm (skip for tmp envs)\n if (!this.isTmpEnv(env)) {\n const answer = await confirm(`Type \"${env}\" to confirm teardown:`);\n\n if (answer !== env) {\n this.log.info(\"Aborted.\");\n return false;\n }\n }\n\n // Auth\n await adapter.authenticate(ctx, run);\n\n // Platform hooks (tear down external resources first, while creds still valid)\n await this.runHooks(\"unregister\", ctx, [], run);\n\n // Teardown\n await adapter.teardown(ctx, run);\n run.end();\n\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Platform hooks\n // -------------------------------------------------------------------------\n\n /**\n * Run all registered PlatformHook instances.\n *\n * Discovered dynamically via `alepha.services(PlatformHook)`: any plugin\n * that registers a PlatformHook subclass in its `$module.services`\n * participates automatically, without the core knowing about it.\n */\n protected async runHooks(\n phase: \"register\" | \"unregister\",\n ctx: PlatformContext,\n deployUrls: string[],\n run: RunnerMethod,\n ): Promise<void> {\n const hooks = this.alepha.services(PlatformHook);\n if (hooks.length === 0) return;\n\n const baseUrl = ctx.envConfig.domain\n ? `https://${ctx.envConfig.domain}`\n : deployUrls[0];\n\n if (!baseUrl) {\n this.log.debug(\"Skipping platform hooks: no base URL available\");\n return;\n }\n\n const hookCtx: PlatformHookContext = { ...ctx, baseUrl, run };\n\n for (const hook of hooks) {\n this.log.debug(`Platform hook: ${hook.name} (${phase})`);\n try {\n if (phase === \"register\") {\n await hook.register(hookCtx);\n } else {\n await hook.unregister(hookCtx);\n }\n } catch (err) {\n // unregister must never block teardown\n if (phase === \"unregister\") {\n this.log.debug(\n `Platform hook ${hook.name} failed to unregister: ${(err as Error).message}`,\n );\n } else {\n throw err;\n }\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // plan\n // -------------------------------------------------------------------------\n\n public async plan(options: {\n root: string;\n env: string;\n apps: AppDefinition[];\n }): Promise<{\n config: ResolvedPlatformConfig;\n naming: NamingContext;\n apps: AppDefinition[];\n }> {\n const { root, env, apps } = options;\n const config = await this.inspector.resolveConfig(root);\n const namingCtx = this.naming.forContext(config.project, env);\n return { config, naming: namingCtx, apps };\n }\n\n // -------------------------------------------------------------------------\n // status\n // -------------------------------------------------------------------------\n\n public async status(options: {\n root: string;\n env: string;\n apps: AppDefinition[];\n run: RunnerMethod;\n }): Promise<{ config: ResolvedPlatformConfig; state: PlatformState }> {\n const { root, env, apps, run } = options;\n const envConfig = await this.inspector.resolveEnvironment(root, env);\n const config = await this.inspector.resolveConfig(root);\n const adapter = this.resolveAdapter(envConfig.adapter);\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx: PlatformContext = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n await adapter.authenticate(ctx, run);\n const state = await adapter.inspect(ctx, run);\n\n return { config, state };\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n public isTmpEnv(env: string): boolean {\n return env.startsWith(\"tmp\");\n }\n}\n","import { $inject, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { FileSystemProvider, ShellProvider } from \"alepha/system\";\nimport type {\n RemoteSecret,\n SecretStoreProvider,\n} from \"./SecretStoreProvider.ts\";\n\n/**\n * GitHub Actions secret store backed by the `gh` CLI.\n *\n * Requires the GitHub CLI (`gh`) to be installed and authenticated.\n * Pushes secrets into GitHub Actions environments.\n */\nexport class GitHubSecretStore implements SecretStoreProvider {\n protected readonly log = $logger();\n protected readonly shell = $inject(ShellProvider);\n protected readonly fs = $inject(FileSystemProvider);\n\n /**\n * Verify that `gh` is installed and authenticated.\n */\n public async ensureAvailable(): Promise<void> {\n const installed = await this.shell.isInstalled(\"gh\");\n if (!installed) {\n throw new AlephaError(\n \"GitHub CLI (gh) is not installed. Install it from https://cli.github.com\",\n );\n }\n\n try {\n await this.shell.run(\"gh auth status\", { capture: true });\n } catch {\n throw new AlephaError(\n \"GitHub CLI is not authenticated. Run `gh auth login` first.\",\n );\n }\n }\n\n /**\n * Create the GitHub Actions environment if it doesn't exist.\n */\n public async ensureEnvironment(environment: string): Promise<void> {\n await this.shell.run(\n `gh api --method PUT /repos/{owner}/{repo}/environments/${environment} --silent`,\n { capture: true },\n );\n this.log.debug(`Ensured environment \"${environment}\" exists`);\n }\n\n /**\n * List all secrets in a GitHub Actions environment.\n */\n public async list(environment: string): Promise<RemoteSecret[]> {\n try {\n const output = await this.shell.run(\n `gh secret list --env ${environment} --json name,updatedAt`,\n { capture: true },\n );\n\n const parsed = JSON.parse(output || \"[]\") as Array<{\n name: string;\n updatedAt?: string;\n }>;\n\n return parsed.map((s) => ({\n name: s.name,\n updatedAt: s.updatedAt,\n }));\n } catch (error) {\n this.log.debug(\"Failed to list secrets\", { environment, error });\n return [];\n }\n }\n\n /**\n * Set a secret in a GitHub Actions environment.\n *\n * Writes a dotenv-formatted file and uses `gh secret set --env-file` to\n * avoid shell pipe issues with NodeShellProvider escaping the `|` character.\n */\n public async set(\n environment: string,\n key: string,\n value: string,\n ): Promise<void> {\n const tmpFile = `/tmp/alepha-secret-${key}-${Date.now()}`;\n const escaped = value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\");\n await this.fs.writeFile(tmpFile, `${key}=\"${escaped}\"\\n`);\n try {\n const output = await this.shell.run(\n `gh secret set -f ${tmpFile} --env ${environment}`,\n { capture: true },\n );\n this.log.debug(`Secret set: ${key}`, { output });\n } finally {\n await this.fs.rm(tmpFile);\n }\n }\n\n /**\n * Delete a secret from a GitHub Actions environment.\n */\n public async delete(environment: string, key: string): Promise<void> {\n await this.shell.run(`gh secret delete ${key} --env ${environment}`, {\n capture: true,\n });\n }\n}\n","/**\n * Filters environment variables for secret store syncing.\n *\n * Excludes platform-managed vars (NODE_ENV), build-time vars (VITE_*),\n * and empty values. Keeps everything else — including DATABASE_URL\n * and POSTGRES_SCHEMA which GitHub Actions needs.\n *\n * Also handles renaming GITHUB_* keys since GitHub Actions rejects\n * secret names starting with GITHUB_.\n */\nexport class SecretFilterService {\n protected static readonly EXCLUDED_KEYS = new Set([\"NODE_ENV\"]);\n protected static readonly GITHUB_PREFIX = \"GITHUB_\";\n protected static readonly REMOTE_PREFIX = \"APP_GITHUB_\";\n\n /**\n * Return only the entries that should be pushed to a secret store.\n */\n public filter(envVars: Record<string, string>): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(envVars)) {\n if (!value) continue;\n if (SecretFilterService.EXCLUDED_KEYS.has(key)) continue;\n if (key.startsWith(\"VITE_\")) continue;\n result[key] = value;\n }\n\n return result;\n }\n\n /**\n * Convert a local env key to a remote secret name.\n *\n * GITHUB_* keys are prefixed with APP_ since GitHub Actions rejects\n * secret names starting with GITHUB_.\n */\n public toRemoteName(key: string): string {\n if (key.startsWith(SecretFilterService.GITHUB_PREFIX)) {\n return `${SecretFilterService.REMOTE_PREFIX}${key.slice(SecretFilterService.GITHUB_PREFIX.length)}`;\n }\n return key;\n }\n\n /**\n * Convert a remote secret name back to the local env key.\n */\n public toLocalName(remoteName: string): string {\n if (remoteName.startsWith(SecretFilterService.REMOTE_PREFIX)) {\n return `${SecretFilterService.GITHUB_PREFIX}${remoteName.slice(SecretFilterService.REMOTE_PREFIX.length)}`;\n }\n return remoteName;\n }\n}\n","import { $inject, $state, AlephaError, t } from \"alepha\";\nimport { $command, EnvUtils } from \"alepha/command\";\nimport { $logger, ConsoleColorProvider } from \"alepha/logger\";\nimport { platformOptions } from \"../atoms/platformOptions.ts\";\nimport { GitHubSecretStore } from \"../providers/GitHubSecretStore.ts\";\nimport type { SecretStoreProvider } from \"../providers/SecretStoreProvider.ts\";\nimport { NamingService } from \"../services/NamingService.ts\";\nimport { PlatformInspector } from \"../services/PlatformInspector.ts\";\nimport { SecretFilterService } from \"../services/SecretFilterService.ts\";\n\nexport class SecretsCommand {\n protected readonly log = $logger();\n protected readonly options = $state(platformOptions);\n protected readonly inspector = $inject(PlatformInspector);\n protected readonly naming = $inject(NamingService);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly githubStore = $inject(GitHubSecretStore);\n protected readonly filter = $inject(SecretFilterService);\n protected readonly color = $inject(ConsoleColorProvider);\n\n protected readonly envFlags = t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n });\n\n // -----------------------------------------------------------------------\n // alepha p secrets list\n // -----------------------------------------------------------------------\n\n protected readonly list = $command({\n name: \"list\",\n aliases: [\"ls\"],\n description: \"List secrets in the remote store\",\n flags: t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n format: t.optional(\n t.text({\n aliases: [\"f\"],\n description: \"Output format: table (default), gha\",\n }),\n ),\n }),\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envName = this.resolveEnvironmentName(config.project, env);\n const format = flags.format ?? \"table\";\n\n const store = this.resolveStore();\n await store.ensureAvailable();\n const remoteSecrets = await store.list(envName);\n\n run.end();\n\n if (format === \"gha\") {\n process.stdout.write(\n `# Generated by alepha — environment: ${envName}\\n`,\n );\n process.stdout.write(\"env:\\n\");\n for (const secret of remoteSecrets) {\n const localName = this.filter.toLocalName(secret.name);\n process.stdout.write(\n ` ${localName}: \\${{ secrets.${secret.name} }}\\n`,\n );\n }\n return;\n }\n\n // table format\n const c = this.color;\n\n if (remoteSecrets.length === 0) {\n process.stdout.write(\n `\\nNo secrets in environment ${c.set(\"CYAN\", envName)}.\\n\\n`,\n );\n return;\n }\n\n process.stdout.write(\n `\\n${c.set(\"GREY_LIGHT\", \"Environment:\")} ${c.set(\"CYAN\", envName)}\\n\\n`,\n );\n\n const maxNameLen = Math.max(\n ...remoteSecrets.map((s) => s.name.length),\n 4,\n );\n\n process.stdout.write(\n ` ${c.set(\"GREY_LIGHT\", \"NAME\".padEnd(maxNameLen + 2))}${c.set(\"GREY_LIGHT\", \"UPDATED\")}\\n`,\n );\n\n for (const secret of remoteSecrets) {\n const updated = secret.updatedAt\n ? new Date(secret.updatedAt).toLocaleString()\n : \"-\";\n process.stdout.write(\n ` ${c.set(\"CYAN\", secret.name.padEnd(maxNameLen + 2))}${c.set(\"GREY_DARK\", updated)}\\n`,\n );\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p secrets diff\n // -----------------------------------------------------------------------\n\n protected readonly diff = $command({\n name: \"diff\",\n description: \"Compare local .env keys with remote store\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envName = this.resolveEnvironmentName(config.project, env);\n\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n const filtered = this.filter.filter(envVars);\n const localKeys = new Set(\n Object.keys(filtered).map((k) => this.filter.toRemoteName(k)),\n );\n\n const store = this.resolveStore();\n await store.ensureAvailable();\n const remoteSecrets = await store.list(envName);\n const remoteKeys = new Set(remoteSecrets.map((s) => s.name));\n\n run.end();\n\n const c = this.color;\n const allKeys = [...new Set([...localKeys, ...remoteKeys])].sort();\n\n process.stdout.write(\n `\\n${c.set(\"GREY_LIGHT\", \"Environment:\")} ${c.set(\"CYAN\", envName)}\\n\\n`,\n );\n\n let hasChanges = false;\n for (const key of allKeys) {\n const inLocal = localKeys.has(key);\n const inRemote = remoteKeys.has(key);\n\n if (inLocal && !inRemote) {\n process.stdout.write(` ${c.set(\"GREEN\", \"+\")} ${key}\\n`);\n hasChanges = true;\n } else if (!inLocal && inRemote) {\n process.stdout.write(` ${c.set(\"RED\", \"-\")} ${key}\\n`);\n hasChanges = true;\n } else {\n process.stdout.write(` ${c.set(\"GREY_DARK\", \"=\")} ${key}\\n`);\n }\n }\n\n if (!hasChanges) {\n process.stdout.write(\n ` ${c.set(\"GREEN\", \"Local and remote are in sync.\")}\\n`,\n );\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p secrets apply\n // -----------------------------------------------------------------------\n\n protected readonly apply = $command({\n name: \"apply\",\n description: \"Push local .env secrets to the remote store\",\n flags: t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n \"dry-run\": t.optional(\n t.boolean({\n description: \"Preview changes without pushing\",\n }),\n ),\n }),\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envName = this.resolveEnvironmentName(config.project, env);\n const dryRun = flags[\"dry-run\"] ?? false;\n\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n const filtered = this.filter.filter(envVars);\n const keys = Object.keys(filtered);\n\n if (keys.length === 0) {\n run.end();\n process.stdout.write(\"\\nNo secrets to push.\\n\\n\");\n return;\n }\n\n if (dryRun) {\n run.end();\n const c = this.color;\n process.stdout.write(\n `\\n${c.set(\"GREY_LIGHT\", \"Dry run — environment:\")} ${c.set(\"CYAN\", envName)}\\n\\n`,\n );\n for (const key of keys) {\n process.stdout.write(` ${c.set(\"GREEN\", \"+\")} ${key}\\n`);\n }\n process.stdout.write(\n `\\n ${keys.length} secret(s) would be pushed.\\n\\n`,\n );\n return;\n }\n\n const store = this.resolveStore();\n await store.ensureAvailable();\n await store.ensureEnvironment(envName);\n\n for (const key of keys) {\n const remoteName = this.filter.toRemoteName(key);\n await run({\n name: `push ${remoteName}`,\n handler: async () => {\n await store.set(envName, remoteName, filtered[key]);\n },\n });\n }\n\n run.end();\n process.stdout.write(\n `\\n${keys.length} secret(s) pushed to ${envName}.\\n`,\n );\n },\n });\n\n // -----------------------------------------------------------------------\n // Parent command\n // -----------------------------------------------------------------------\n\n public readonly secrets = $command({\n name: \"secrets\",\n aliases: [\"sec\"],\n description: \"Manage secrets in external stores\",\n children: [this.list, this.diff, this.apply],\n handler: async ({ help }) => {\n help();\n },\n });\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n public resolveStore(): SecretStoreProvider {\n const storeName = this.options?.secrets?.store ?? \"github\";\n switch (storeName) {\n case \"github\":\n return this.githubStore;\n default:\n throw new AlephaError(\n `Unknown secret store \"${storeName}\". Available: github`,\n );\n }\n }\n\n protected resolveEnvironmentName(project: string, env: string): string {\n const pattern =\n this.options?.secrets?.environmentPattern ?? \"{project}-{env}\";\n\n return pattern\n .replace(\"{project}\", this.naming.slugify(project))\n .replace(\"{env}\", this.naming.slugify(env));\n }\n}\n","import { $inject, $state, AlephaError, t } from \"alepha\";\nimport { AppEntryProvider, ViteBuildProvider } from \"alepha/cli\";\nimport { $command, EnvUtils } from \"alepha/command\";\nimport { $logger, ConsoleColorProvider } from \"alepha/logger\";\nimport { CloudflareAdapter } from \"../adapters/CloudflareAdapter.ts\";\nimport type {\n AppDefinition,\n DetectedResources,\n} from \"../adapters/PlatformAdapter.ts\";\nimport { VercelAdapter } from \"../adapters/VercelAdapter.ts\";\nimport { platformOptions } from \"../atoms/platformOptions.ts\";\nimport type {\n PlatformPlanOutput,\n PlatformStatusOutput,\n} from \"../schemas/platform.ts\";\nimport { NamingService } from \"../services/NamingService.ts\";\nimport {\n PlatformInspector,\n type ResolvedPlatformConfig,\n} from \"../services/PlatformInspector.ts\";\nimport { PlatformOrchestrator } from \"../services/PlatformOrchestrator.ts\";\nimport { SecretsCommand } from \"./SecretsCommand.ts\";\n\nexport class PlatformCommand {\n protected readonly log = $logger();\n protected readonly options = $state(platformOptions);\n protected readonly orchestrator = $inject(PlatformOrchestrator);\n protected readonly inspector = $inject(PlatformInspector);\n protected readonly naming = $inject(NamingService);\n protected readonly boot = $inject(AppEntryProvider);\n protected readonly viteBuild = $inject(ViteBuildProvider);\n protected readonly color = $inject(ConsoleColorProvider);\n protected readonly envUtils = $inject(EnvUtils);\n protected readonly secretsCommand = $inject(SecretsCommand);\n\n /**\n * Common flags for env/app targeting.\n */\n protected readonly envFlags = t.object({\n env: t.optional(\n t.text({\n aliases: [\"e\"],\n description: \"Target environment\",\n }),\n ),\n app: t.optional(\n t.text({\n aliases: [\"a\"],\n description: \"Target specific app (monorepo)\",\n }),\n ),\n verbose: t.optional(\n t.boolean({\n aliases: [\"v\"],\n description: \"Verbose output\",\n }),\n ),\n json: t.optional(\n t.boolean({\n description: \"Output as JSON\",\n }),\n ),\n });\n\n // -----------------------------------------------------------------------\n // alepha p plan\n // -----------------------------------------------------------------------\n\n protected readonly plan = $command({\n name: \"plan\",\n description: \"Show project topology and resource names\",\n flags: this.envFlags,\n handler: async ({ flags, root }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapterName = envConfig?.adapter ?? \"cloudflare\";\n\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapterName),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n // --- Data collection ---\n\n const hasDB = apps.some((a) => a.resources.hasDatabase);\n const hasBucket = apps.some((a) => a.resources.hasBucket);\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n\n const resources: Array<{ label: string; value: string }> = [];\n\n const deployLabel = adapterName === \"vercel\" ? \"Project\" : \"Worker\";\n if (config.isMonorepo) {\n for (const app of apps) {\n resources.push({\n label: deployLabel,\n value: namingCtx.worker(app.name),\n });\n }\n } else {\n resources.push({ label: deployLabel, value: namingCtx.worker() });\n }\n\n if (adapterName === \"cloudflare\") {\n if (hasDB) {\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL;\n if (dbUrl?.startsWith(\"postgres:\")) {\n resources.push({\n label: \"Hyperdrive\",\n value: namingCtx.hyperdrive(),\n });\n } else {\n resources.push({ label: \"D1\", value: namingCtx.d1() });\n }\n }\n\n if (hasBucket) {\n resources.push({ label: \"R2\", value: namingCtx.r2() });\n }\n\n for (const app of apps) {\n if (app.resources.hasKV) {\n resources.push({\n label: \"KV\",\n value: namingCtx.kv(config.isMonorepo ? app.name : undefined),\n });\n }\n if (app.resources.hasQueue) {\n resources.push({\n label: \"Queue\",\n value: namingCtx.queue(config.isMonorepo ? app.name : undefined),\n });\n }\n }\n }\n\n const excludedKeys =\n adapterName === \"vercel\"\n ? VercelAdapter.EXCLUDED_SECRET_KEYS\n : CloudflareAdapter.EXCLUDED_SECRET_KEYS;\n const secretCount = Object.entries(envVars).filter(\n ([key, value]) =>\n value && !excludedKeys.has(key) && !key.startsWith(\"VITE_\"),\n ).length;\n\n // --- JSON output ---\n\n if (flags.json) {\n const environments: Record<\n string,\n { adapter: string; domain?: string }\n > = {};\n for (const [key, val] of Object.entries(config.environments)) {\n environments[key] = {\n adapter: val.adapter,\n ...(val.domain ? { domain: val.domain } : {}),\n };\n }\n\n const output: PlatformPlanOutput = {\n project: config.project,\n env,\n mode: config.isMonorepo ? \"monorepo\" : \"standalone\",\n apps: apps.map((a) => ({\n name: a.name,\n path: a.path,\n resources: a.resources,\n })),\n environments,\n resources,\n secretCount,\n };\n\n process.stdout.write(`${JSON.stringify(output, null, 2)}\\n`);\n return;\n }\n\n // --- Tree output ---\n\n const c = this.color;\n\n process.stdout.write(\n `\\n\\u{1F4E6} ${c.set(\"WHITE_BOLD\", config.project)} ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"CYAN\", env)}\\n\\n`,\n );\n\n if (config.isMonorepo) {\n process.stdout.write(\n ` ${c.set(\"GREY_LIGHT\", \"Mode:\")} monorepo (${config.appPaths.length} apps)\\n`,\n );\n for (const [i, appPath] of config.appPaths.entries()) {\n const appName = config.appNames.get(appPath) ?? appPath;\n const prefix =\n i === config.appPaths.length - 1\n ? \"\\u2514\\u2500\\u2500\"\n : \"\\u251C\\u2500\\u2500\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", prefix)} ${c.set(\"CYAN\", appName.padEnd(10))} ${c.set(\"GREY_DARK\", appPath)}\\n`,\n );\n }\n } else {\n process.stdout.write(` ${c.set(\"GREY_LIGHT\", \"Mode:\")} standalone\\n`);\n }\n\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Environments:\")}\\n`);\n const envKeys = Object.keys(config.environments);\n for (const [i, envKey] of envKeys.entries()) {\n const envConfig = config.environments[envKey];\n const prefix =\n i === envKeys.length - 1\n ? \"\\u2514\\u2500\\u2500\"\n : \"\\u251C\\u2500\\u2500\";\n const domain = envConfig.domain\n ? ` ${c.set(\"GREY_DARK\", envConfig.domain)}`\n : \"\";\n const marker = envKey === env ? ` ${c.set(\"GREEN\", \"\\u25C0\")}` : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", prefix)} ${c.set(\"CYAN\", envKey.padEnd(10))} ${c.set(\"GREY_LIGHT\", envConfig.adapter)}${domain}${marker}\\n`,\n );\n }\n\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Resources:\")}\\n`);\n\n if (secretCount > 0) {\n resources.push({\n label: \"Secrets\",\n value: `${secretCount} from .env.${env}`,\n });\n }\n\n for (const [i, res] of resources.entries()) {\n const isLast = i === resources.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"GREY_LIGHT\", res.label.padEnd(11))} ${c.set(\"CYAN\", res.value)}\\n`,\n );\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p up\n // -----------------------------------------------------------------------\n\n protected readonly up = $command({\n name: \"up\",\n mode: \"production\",\n description: \"Build, migrate, and deploy\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n process.env.NODE_ENV = \"production\";\n\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const adapter = config.environments[env]?.adapter ?? \"cloudflare\";\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapter),\n );\n\n await this.orchestrator.up({\n root,\n env,\n app: flags.app,\n apps,\n run,\n });\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p down\n // -----------------------------------------------------------------------\n\n protected readonly down = $command({\n name: \"down\",\n description: \"Tear down an environment\",\n flags: this.envFlags,\n handler: async ({ flags, root, run, ask }) => {\n if (!flags.env) {\n throw new AlephaError(\n \"--env is required for teardown. This command deletes resources.\",\n );\n }\n\n const config = await this.inspector.resolveConfig(root);\n const adapter = config.environments[flags.env]?.adapter ?? \"cloudflare\";\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapter),\n );\n\n await this.orchestrator.down({\n root,\n env: flags.env,\n app: flags.app,\n apps,\n run,\n confirm: async (prompt) => {\n ask.intro(\"Confirm teardown\");\n const value = await ask(prompt);\n ask.outro(\"\");\n return value;\n },\n });\n },\n });\n\n // -----------------------------------------------------------------------\n // alepha p status\n // -----------------------------------------------------------------------\n\n protected readonly status = $command({\n name: \"status\",\n aliases: [\"s\"],\n description: \"Show deployed state\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const adapter = config.environments[env]?.adapter ?? \"cloudflare\";\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(adapter),\n );\n\n const { state } = await this.orchestrator.status({\n root,\n env,\n apps,\n run,\n });\n\n // --- JSON output ---\n\n if (flags.json) {\n run.end();\n\n const output: PlatformStatusOutput = {\n project: config.project,\n env,\n adapter: config.environments[env].adapter,\n ...state,\n };\n\n process.stdout.write(`${JSON.stringify(output, null, 2)}\\n`);\n return;\n }\n\n // --- Tree output ---\n\n run.end();\n\n const c = this.color;\n\n process.stdout.write(\n `\\n\\u{1F4E6} ${c.set(\"WHITE_BOLD\", config.project)} ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"CYAN\", env)} ${c.set(\"GREY_DARK\", `(${config.environments[env].adapter})`)}\\n\\n`,\n );\n\n const hasDB = state.databases.length > 0;\n const hasBuckets = state.buckets.length > 0;\n\n process.stdout.write(` ${c.set(\"GREY_LIGHT\", \"Workers:\")}\\n`);\n for (const [i, w] of state.workers.entries()) {\n const isLast = i === state.workers.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (w.exists) {\n const versionShort = w.version?.slice(0, 8) ?? \"unknown\";\n const tag = w.tag ? ` ${c.set(\"GREY_DARK\", `(${w.tag})`)}` : \"\";\n const date = w.createdAt\n ? ` ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"GREY_DARK\", new Date(w.createdAt).toLocaleString())}`\n : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", w.name)} ${c.set(\"GREEN\", \"\\u2713\")} ${c.set(\"GREY_LIGHT\", versionShort)}${tag}${date}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", w.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not deployed\")}\\n`,\n );\n }\n }\n\n if (hasDB) {\n const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);\n const dbUrl = envVars.DATABASE_URL ?? process.env.DATABASE_URL;\n const dbLabel = dbUrl?.startsWith(\"postgres:\")\n ? \"Hyperdrive:\"\n : \"Database:\";\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", dbLabel)}\\n`);\n for (const [i, db] of state.databases.entries()) {\n const isLast = i === state.databases.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (db.exists) {\n const id = db.id\n ? ` ${c.set(\"GREY_LIGHT\", db.id.slice(0, 8))}`\n : \"\";\n const detail = db.detail\n ? ` ${c.set(\"GREY_DARK\", \"\\u2014\")} ${c.set(\"GREY_DARK\", db.detail.slice(0, 40))}`\n : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", db.name)} ${c.set(\"GREEN\", \"\\u2713\")}${id}${detail}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", db.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (hasBuckets) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Buckets:\")}\\n`);\n for (const [i, b] of state.buckets.entries()) {\n const isLast = i === state.buckets.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (b.exists) {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", b.name)} ${c.set(\"GREEN\", \"\\u2713\")}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", b.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (state.kvNamespaces.length > 0) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"KV:\")}\\n`);\n for (const [i, kv] of state.kvNamespaces.entries()) {\n const isLast = i === state.kvNamespaces.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (kv.exists) {\n const id = kv.id\n ? ` ${c.set(\"GREY_LIGHT\", kv.id.slice(0, 8))}`\n : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", kv.name)} ${c.set(\"GREEN\", \"\\u2713\")}${id}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", kv.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (state.queues.length > 0) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Queues:\")}\\n`);\n for (const [i, q] of state.queues.entries()) {\n const isLast = i === state.queues.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n if (q.exists) {\n const id = q.id ? ` ${c.set(\"GREY_LIGHT\", q.id.slice(0, 8))}` : \"\";\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", q.name)} ${c.set(\"GREEN\", \"\\u2713\")}${id}\\n`,\n );\n } else {\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", q.name)} ${c.set(\"RED\", \"\\u2717\")} ${c.set(\"RED\", \"not provisioned\")}\\n`,\n );\n }\n }\n }\n\n if (state.secrets.length > 0) {\n process.stdout.write(`\\n ${c.set(\"GREY_LIGHT\", \"Secrets:\")}\\n`);\n for (const [i, s] of state.secrets.entries()) {\n const isLast = i === state.secrets.length - 1;\n const branch = isLast ? \"\\u2514\\u2500\\u2500\" : \"\\u251C\\u2500\\u2500\";\n const icon = s.deployed\n ? c.set(\"GREEN\", \"\\u2713\")\n : c.set(\"RED\", \"\\u2717\");\n process.stdout.write(\n ` ${c.set(\"GREY_DARK\", branch)} ${c.set(\"CYAN\", s.name)} ${icon}\\n`,\n );\n }\n }\n\n process.stdout.write(\"\\n\");\n },\n });\n\n // -----------------------------------------------------------------------\n // Granular commands\n // -----------------------------------------------------------------------\n\n protected readonly build = $command({\n name: \"build\",\n mode: \"production\",\n description: \"Build all apps locally\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n process.env.NODE_ENV = \"production\";\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapter = this.orchestrator.resolveAdapter(envConfig.adapter);\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(envConfig.adapter),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n const targets = flags.app\n ? apps.filter((a) => a.name === flags.app)\n : apps;\n\n for (const app of targets) {\n await adapter.build({ ...ctx, app }, run);\n }\n },\n });\n\n protected readonly deploy = $command({\n name: \"deploy\",\n description: \"Deploy apps to cloud\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapter = this.orchestrator.resolveAdapter(envConfig.adapter);\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(envConfig.adapter),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n await adapter.authenticate(ctx, run);\n\n const targets = flags.app\n ? apps.filter((a) => a.name === flags.app)\n : apps;\n\n for (const app of targets) {\n await adapter.deploy({ ...ctx, app }, run);\n }\n },\n });\n\n protected readonly migrate = $command({\n name: \"migrate\",\n description: \"Run database migrations\",\n flags: this.envFlags,\n handler: async ({ flags, root, run }) => {\n const config = await this.inspector.resolveConfig(root);\n const env = flags.env ?? config.defaultEnv;\n const envConfig = config.environments[env];\n const adapter = this.orchestrator.resolveAdapter(envConfig.adapter);\n const apps = await this.resolveApps(\n root,\n config,\n this.isServerless(envConfig.adapter),\n );\n const namingCtx = this.naming.forContext(config.project, env);\n\n const ctx = {\n project: config.project,\n env,\n envConfig,\n apps,\n root,\n naming: namingCtx,\n };\n\n await adapter.authenticate(ctx, run);\n await adapter.migrate(ctx, run);\n },\n });\n\n // -----------------------------------------------------------------------\n // Parent command\n // -----------------------------------------------------------------------\n\n public readonly platform = $command({\n name: \"platform\",\n aliases: [\"p\"],\n description: \"Cloud deployment orchestrator\",\n children: [\n this.plan,\n this.up,\n this.down,\n this.status,\n this.build,\n this.deploy,\n this.migrate,\n this.secretsCommand.secrets,\n ],\n handler: async ({ help, root }) => {\n await this.inspector.resolveConfig(root);\n help();\n },\n });\n\n // -----------------------------------------------------------------------\n // Helpers\n // -----------------------------------------------------------------------\n\n /**\n * Resolve app definitions.\n *\n * For standalone: returns a single app from the root.\n * For monorepo: resolves each app path, introspects for resources.\n *\n * NOTE: Resource detection (hasDatabase, hasBucket, etc.) requires\n * ViteBuildProvider.init() per app. This is expensive -- only done\n * for up/down/status, not for plan.\n */\n protected async resolveApps(\n root: string,\n config: ResolvedPlatformConfig,\n isServerless: boolean,\n ): Promise<AppDefinition[]> {\n if (!config.isMonorepo) {\n const entry = await this.boot.getAppEntry(root);\n if (isServerless) {\n process.env.ALEPHA_SERVERLESS = \"true\";\n }\n const appAlepha = await this.viteBuild.init({ entry });\n delete process.env.ALEPHA_SERVERLESS;\n const resources = this.detectResources(appAlepha);\n\n return [\n {\n name: config.project,\n path: \"\",\n entry,\n resources,\n },\n ];\n }\n\n const apps: AppDefinition[] = [];\n for (const appPath of config.appPaths) {\n const appRoot = `${root}/${appPath}`;\n const entry = await this.boot.getAppEntry(appRoot);\n if (isServerless) {\n process.env.ALEPHA_SERVERLESS = \"true\";\n }\n const appAlepha = await this.viteBuild.init({ entry });\n delete process.env.ALEPHA_SERVERLESS;\n const name = config.appNames.get(appPath) ?? appPath;\n const resources = this.detectResources(appAlepha);\n\n apps.push({ name, path: appPath, entry, resources });\n }\n\n return apps;\n }\n\n protected isServerless(adapter: string): boolean {\n return adapter === \"vercel\" || adapter === \"cloudflare\";\n }\n\n protected detectResources(alepha: any): DetectedResources {\n let hasDatabase = false;\n let hasBucket = false;\n let hasKV = false;\n let hasQueue = false;\n let hasCron = false;\n\n try {\n const repo = alepha.inject(\"RepositoryProvider\");\n hasDatabase = repo.getRepositories().length > 0;\n } catch {}\n\n try {\n const buckets = alepha.primitives(\"$bucket\");\n hasBucket = buckets.length > 0;\n } catch {}\n\n try {\n hasKV =\n alepha\n .primitives(\"cache\")\n .filter((it: any) => it.options?.provider !== \"memory\").length > 0;\n } catch {}\n\n try {\n hasQueue = alepha.primitives(\"queue\").length > 0;\n } catch {}\n\n try {\n const cron = alepha.inject(\"CronProvider\");\n hasCron = cron.getCronJobs().length > 0;\n } catch {}\n\n return { hasDatabase, hasBucket, hasKV, hasQueue, hasCron };\n }\n}\n","import { AlephaError } from \"alepha\";\nimport type {\n RemoteSecret,\n SecretStoreProvider,\n} from \"./SecretStoreProvider.ts\";\n\nexport interface MemorySecretStoreCall {\n method: \"ensureAvailable\" | \"ensureEnvironment\" | \"list\" | \"set\" | \"delete\";\n environment?: string;\n key?: string;\n value?: string;\n}\n\n/**\n * In-memory implementation of SecretStoreProvider for testing.\n * Records all operations and stores secrets in a nested Map.\n */\nexport class MemorySecretStore implements SecretStoreProvider {\n /**\n * Secrets keyed by environment, then by key.\n */\n public secrets = new Map<string, Map<string, string>>();\n\n /**\n * All recorded operations.\n */\n public calls: MemorySecretStoreCall[] = [];\n\n /**\n * When set, ensureAvailable() will throw with this message.\n */\n public availableError: string | null = null;\n\n public async ensureAvailable(): Promise<void> {\n this.calls.push({ method: \"ensureAvailable\" });\n if (this.availableError) {\n throw new AlephaError(this.availableError);\n }\n }\n\n public async ensureEnvironment(environment: string): Promise<void> {\n this.calls.push({ method: \"ensureEnvironment\", environment });\n if (!this.secrets.has(environment)) {\n this.secrets.set(environment, new Map());\n }\n }\n\n public async list(environment: string): Promise<RemoteSecret[]> {\n this.calls.push({ method: \"list\", environment });\n const envSecrets = this.secrets.get(environment);\n if (!envSecrets) return [];\n\n return Array.from(envSecrets.keys()).map((name) => ({ name }));\n }\n\n public async set(\n environment: string,\n key: string,\n value: string,\n ): Promise<void> {\n this.calls.push({ method: \"set\", environment, key, value });\n\n let envSecrets = this.secrets.get(environment);\n if (!envSecrets) {\n envSecrets = new Map();\n this.secrets.set(environment, envSecrets);\n }\n envSecrets.set(key, value);\n }\n\n public async delete(environment: string, key: string): Promise<void> {\n this.calls.push({ method: \"delete\", environment, key });\n this.secrets.get(environment)?.delete(key);\n }\n\n /**\n * Check if set() was called for a given environment and key.\n */\n public wasSet(environment: string, key: string): boolean {\n return this.calls.some(\n (c) =>\n c.method === \"set\" && c.environment === environment && c.key === key,\n );\n }\n\n /**\n * Check if delete() was called for a given environment and key.\n */\n public wasDeleted(environment: string, key: string): boolean {\n return this.calls.some(\n (c) =>\n c.method === \"delete\" && c.environment === environment && c.key === key,\n );\n }\n\n /**\n * Get all set() calls for a given environment.\n */\n public getSetCalls(\n environment: string,\n ): Array<{ key: string; value: string }> {\n return this.calls\n .filter((c) => c.method === \"set\" && c.environment === environment)\n .map((c) => ({ key: c.key!, value: c.value! }));\n }\n\n /**\n * Reset all state.\n */\n public reset(): void {\n this.secrets.clear();\n this.calls = [];\n this.availableError = null;\n }\n}\n","/**\n * A secret stored in a remote secret store.\n */\nexport interface RemoteSecret {\n name: string;\n updatedAt?: string;\n}\n\n/**\n * Abstract provider for managing secrets in an external store.\n *\n * Implementations: GitHubSecretStore, MemorySecretStore\n */\nexport abstract class SecretStoreProvider {\n /**\n * Verify the backing store is reachable and authenticated.\n */\n abstract ensureAvailable(): Promise<void>;\n\n /**\n * Ensure the target environment exists in the store, creating it if needed.\n */\n abstract ensureEnvironment(environment: string): Promise<void>;\n\n /**\n * List all secrets in a given environment.\n */\n abstract list(environment: string): Promise<RemoteSecret[]>;\n\n /**\n * Set (create or update) a secret in a given environment.\n */\n abstract set(environment: string, key: string, value: string): Promise<void>;\n\n /**\n * Delete a secret from a given environment.\n */\n abstract delete(environment: string, key: string): Promise<void>;\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\n// ---------------------------------------------------------------------------\n// Status output\n// ---------------------------------------------------------------------------\n\nexport const platformStatusWorkerSchema = t.object({\n name: t.string(),\n exists: t.boolean(),\n id: t.optional(t.string()),\n detail: t.optional(t.string()),\n version: t.optional(t.string()),\n tag: t.optional(t.string()),\n createdAt: t.optional(t.string()),\n});\n\nexport const platformStatusResourceSchema = t.object({\n name: t.string(),\n exists: t.boolean(),\n id: t.optional(t.string()),\n detail: t.optional(t.string()),\n});\n\nexport const platformStatusSecretSchema = t.object({\n name: t.string(),\n deployed: t.boolean(),\n});\n\nexport const platformStatusSchema = t.object({\n project: t.string(),\n env: t.string(),\n adapter: t.string(),\n workers: t.array(platformStatusWorkerSchema),\n databases: t.array(platformStatusResourceSchema),\n buckets: t.array(platformStatusResourceSchema),\n kvNamespaces: t.array(platformStatusResourceSchema),\n queues: t.array(platformStatusResourceSchema),\n secrets: t.array(platformStatusSecretSchema),\n});\n\nexport type PlatformStatusOutput = Static<typeof platformStatusSchema>;\n\n// ---------------------------------------------------------------------------\n// Plan output\n// ---------------------------------------------------------------------------\n\nexport const platformPlanAppResourcesSchema = t.object({\n hasDatabase: t.boolean(),\n hasBucket: t.boolean(),\n hasKV: t.boolean(),\n hasQueue: t.boolean(),\n hasCron: t.boolean(),\n});\n\nexport const platformPlanAppSchema = t.object({\n name: t.string(),\n path: t.string(),\n resources: platformPlanAppResourcesSchema,\n});\n\nexport const platformPlanEnvironmentSchema = t.object({\n adapter: t.string(),\n domain: t.optional(t.string()),\n});\n\nexport const platformPlanResourceSchema = t.object({\n label: t.string(),\n value: t.string(),\n});\n\nexport const platformPlanSchema = t.object({\n project: t.string(),\n env: t.string(),\n mode: t.enum([\"monorepo\", \"standalone\"]),\n apps: t.array(platformPlanAppSchema),\n environments: t.record(t.string(), platformPlanEnvironmentSchema),\n resources: t.array(platformPlanResourceSchema),\n secretCount: t.number(),\n});\n\nexport type PlatformPlanOutput = Static<typeof platformPlanSchema>;\n","import { $context, $module } from \"alepha\";\nimport { AlephaCli } from \"alepha/cli\";\nimport { CloudflareAdapter } from \"./adapters/CloudflareAdapter.ts\";\nimport { VercelAdapter } from \"./adapters/VercelAdapter.ts\";\nimport {\n type PlatformOptions,\n platformOptions,\n} from \"./atoms/platformOptions.ts\";\nimport { PlatformCommand } from \"./commands/platform.ts\";\nimport { SecretsCommand } from \"./commands/SecretsCommand.ts\";\nimport { GitHubSecretStore } from \"./providers/GitHubSecretStore.ts\";\nimport { MemorySecretStore } from \"./providers/MemorySecretStore.ts\";\nimport { PlatformCacheProvider } from \"./providers/PlatformCacheProvider.ts\";\nimport { CloudflareApi } from \"./services/CloudflareApi.ts\";\nimport { NamingService } from \"./services/NamingService.ts\";\nimport { PlatformInspector } from \"./services/PlatformInspector.ts\";\nimport { PlatformOrchestrator } from \"./services/PlatformOrchestrator.ts\";\nimport { SecretFilterService } from \"./services/SecretFilterService.ts\";\nimport { VercelApi } from \"./services/VercelApi.ts\";\nimport { VercelCli } from \"./services/VercelCli.ts\";\nimport { WranglerApi } from \"./services/WranglerApi.ts\";\n\n// ---------------------------------------------------------------------------\n\n/**\n * CLI plugin for multi-cloud deployment orchestration.\n *\n * Manages the full lifecycle of deploying Alepha apps: provision resources,\n * build, migrate databases, deploy, and sync secrets. Supports Cloudflare\n * Workers and Vercel.\n *\n * Commands:\n * - `alepha platform plan` — show project topology and resource names\n * - `alepha platform up` — full deployment pipeline\n * - `alepha platform down` — teardown an environment\n * - `alepha platform status` — inspect deployed resources\n * - `alepha platform build` — build apps locally\n * - `alepha platform deploy` — deploy to cloud\n * - `alepha platform migrate` — run database migrations\n * - `alepha platform secrets` — manage external secret stores\n *\n * Configuration in `alepha.config.ts`:\n *\n * ```typescript\n * import { platform } from \"alepha/cli/platform\";\n *\n * export default defineConfig({\n * plugins: [\n * platform({\n * environments: {\n * production: { adapter: \"cloudflare\", domain: \"myapp.com\" },\n * },\n * }),\n * ],\n * });\n * ```\n */\nexport const AlephaCliPlatformPlugin = $module({\n name: \"alepha.cli.plugins.platform\",\n services: [\n AlephaCli,\n PlatformCommand,\n SecretsCommand,\n CloudflareAdapter,\n CloudflareApi,\n VercelAdapter,\n VercelApi,\n VercelCli,\n WranglerApi,\n PlatformCacheProvider,\n GitHubSecretStore,\n MemorySecretStore,\n NamingService,\n SecretFilterService,\n PlatformInspector,\n PlatformOrchestrator,\n ],\n});\n\nexport const platform = (options: PlatformOptions) => {\n return () => {\n const { alepha } = $context();\n alepha.with(AlephaCliPlatformPlugin).set(platformOptions, options);\n };\n};\n\n// ---------------------------------------------------------------------------\n\nexport * from \"./adapters/CloudflareAdapter.ts\";\nexport * from \"./adapters/PlatformAdapter.ts\";\nexport * from \"./adapters/VercelAdapter.ts\";\nexport * from \"./atoms/platformOptions.ts\";\nexport * from \"./commands/platform.ts\";\nexport * from \"./commands/SecretsCommand.ts\";\nexport * from \"./hooks/PlatformHook.ts\";\nexport * from \"./providers/GitHubSecretStore.ts\";\nexport * from \"./providers/MemorySecretStore.ts\";\nexport * from \"./providers/PlatformCacheProvider.ts\";\nexport * from \"./providers/SecretStoreProvider.ts\";\nexport * from \"./schemas/cloudflare.ts\";\nexport * from \"./schemas/platform.ts\";\nexport * from \"./schemas/vercel.ts\";\nexport * from \"./services/CloudflareApi.ts\";\nexport * from \"./services/NamingService.ts\";\nexport * from \"./services/PlatformInspector.ts\";\nexport * from \"./services/PlatformOrchestrator.ts\";\nexport * from \"./services/SecretFilterService.ts\";\nexport * from \"./services/VercelApi.ts\";\nexport * from \"./services/VercelCli.ts\";\nexport * from \"./services/WranglerApi.ts\";\n"],"mappings":"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"}
|