@caelo-cms/provisioning 0.1.0 → 0.1.1

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.
@@ -0,0 +1,95 @@
1
+ /**
2
+ * P15 — shared cloud-provider adapter contract.
3
+ *
4
+ * Every per-provider Pulumi stack at `packages/provisioning/stacks/<provider>/`
5
+ * exports a `provision(inputs: CloudAdapterInputs): CloudAdapterOutputs`
6
+ * function. The Caelo runtime never knows which provider it's running
7
+ * on — it just consumes the connection strings + URLs the adapter
8
+ * publishes via `CloudAdapterOutputs`. This keeps the per-provider
9
+ * surface small (~6 capabilities, see master plan) and the runtime
10
+ * provider-agnostic.
11
+ *
12
+ * Pulumi types are intentionally NOT imported here so that callers
13
+ * outside the Pulumi runtime (e.g. the cms-provision CLI, the admin
14
+ * app's DNS-guidance page) can consume the *plain* shape without
15
+ * dragging in the @pulumi/pulumi peer dep. Per-stack `index.ts` files
16
+ * narrow the output type to `pulumi.Output<T>` at their boundary.
17
+ */
18
+ export type Environment = "dev" | "staging" | "production";
19
+ export type LocaleStrategy = "subdirectory" | "subdomain" | "domain";
20
+ export interface LocaleConfig {
21
+ /** ISO code, e.g. "en", "de", "fr-CA". */
22
+ readonly code: string;
23
+ /** URL strategy. Mixed strategies in one install are explicitly supported. */
24
+ readonly strategy: LocaleStrategy;
25
+ /** Required when strategy is "subdomain" or "domain"; ignored for "subdirectory". */
26
+ readonly host?: string;
27
+ }
28
+ export interface CloudAdapterInputs {
29
+ /** Primary domain (e.g. example.com). Admin + production public both bind here. */
30
+ readonly domain: string;
31
+ /** Operator email used for ACME / cert provisioning + Pulumi notifications. */
32
+ readonly ownerEmail: string;
33
+ /** Three-env model (CMS_REQUIREMENTS §16.5). Cloud installs always provision all three. */
34
+ readonly environments: ReadonlyArray<Environment>;
35
+ /** Per-locale routing config — drives per-domain cert + DNS guidance + edge routing. */
36
+ readonly locales: ReadonlyArray<LocaleConfig>;
37
+ /** Optional pre-existing secret references (e.g. from a CI secrets manager). */
38
+ readonly preProvisionedSecrets?: {
39
+ readonly anthropicApiKey?: string;
40
+ readonly resendApiKey?: string;
41
+ };
42
+ }
43
+ /**
44
+ * DNS records the operator must create at their registrar to make the
45
+ * install reachable. Surfaced in the admin's /security/dns page with
46
+ * live resolver status badges.
47
+ */
48
+ export interface DnsRecord {
49
+ readonly hostname: string;
50
+ readonly type: "A" | "AAAA" | "CNAME" | "TXT";
51
+ readonly value: string;
52
+ readonly purpose: string;
53
+ }
54
+ /**
55
+ * Plain-data adapter outputs. Per-stack code wraps each field in
56
+ * `pulumi.Output<…>` at the Pulumi boundary, but the *shape* is shared
57
+ * across providers so the cms-provision CLI + the DNS UI can consume
58
+ * any provider's outputs uniformly.
59
+ */
60
+ export interface CloudAdapterOutputs {
61
+ /** DSN for cms_admin role (encrypted in Pulumi state). */
62
+ readonly adminDatabaseUrl: string;
63
+ /** DSN for cms_public role (encrypted in Pulumi state). */
64
+ readonly publicDatabaseUrl: string;
65
+ /** Provider-native blob URL (s3://, gs://, https://<account>.blob.core.windows.net/<container>). */
66
+ readonly mediaStorageUrl: string;
67
+ /** Public-facing URL the admin reaches for media reads. */
68
+ readonly mediaCdnBaseUrl: string;
69
+ /** Bootstrap-token URL — operator opens this once after `pulumi up`. */
70
+ readonly bootstrapUrl: string;
71
+ /** DNS records consumed by the admin's DNS-guidance page. */
72
+ readonly dnsRecordsRequired: ReadonlyArray<DnsRecord>;
73
+ /**
74
+ * Where edge-A/B assignment logs land — read by the P12A analytics plugin's
75
+ * provider-specific log adapter. Provider-native sink URL (BigQuery dataset,
76
+ * Athena database, Log Analytics workspace).
77
+ */
78
+ readonly edgeLogSinkUrl: string;
79
+ /** Which provider produced these outputs — drives the analytics plugin's adapter dispatch. */
80
+ readonly provider: SupportedProvider;
81
+ /** Which environment this output snapshot represents. */
82
+ readonly environment: Environment;
83
+ }
84
+ export type SupportedProvider = "self-hosted" | "gcp" | "aws" | "azure";
85
+ /**
86
+ * Convenience: the shape persisted in `cms_admin.provisioning_outputs.outputs_json`.
87
+ * Pulumi runs the adapter, the CLI's `pulumi-output-sync` subcommand reads
88
+ * `pulumi stack output --json`, hashes the result, and writes a row keyed on
89
+ * (provider, environment) so the admin UI can read without provider creds.
90
+ */
91
+ export interface ProvisioningOutputsJson {
92
+ readonly outputs: CloudAdapterOutputs;
93
+ readonly syncedAt: string;
94
+ }
95
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,CAAC;AAC3D,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,WAAW,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,qFAAqF;IACrF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2FAA2F;IAC3F,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAClD,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IAC9C,gFAAgF;IAChF,QAAQ,CAAC,qBAAqB,CAAC,EAAE;QAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,oGAAoG;IACpG,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,6DAA6D;IAC7D,QAAQ,CAAC,kBAAkB,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACtD;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,yDAAyD;IACzD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;CACnC;AAED,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAExE;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B"}
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ export {};
3
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,mCAAmC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * P14 — owner bootstrap token. cms-provision generates one at first
3
+ * `up`; the operator visits /setup?token=<…> to create the first
4
+ * Owner. Single-use, 24h TTL.
5
+ */
6
+ export interface BootstrapToken {
7
+ readonly token: string;
8
+ readonly expiresAt: string;
9
+ }
10
+ export declare function generateBootstrapToken(): BootstrapToken;
11
+ //# sourceMappingURL=bootstrap-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-token.d.ts","sourceRoot":"","sources":["../src/bootstrap-token.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,sBAAsB,IAAI,cAAc,CAMvD"}
@@ -0,0 +1,9 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ export function generateBootstrapToken() {
3
+ const bytes = new Uint8Array(32);
4
+ crypto.getRandomValues(bytes);
5
+ const token = [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
6
+ const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
7
+ return { token, expiresAt };
8
+ }
9
+ //# sourceMappingURL=bootstrap-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-token.js","sourceRoot":"","sources":["../src/bootstrap-token.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAanC,MAAM,UAAU,sBAAsB;IACpC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3E,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * P14 — Caddyfile generator.
3
+ *
4
+ * Reads the `domains` table + the deploy targets and emits a
5
+ * deterministic Caddyfile string. The CLI's `regenerate-caddy`
6
+ * sub-command writes this to `/etc/caddy/Caddyfile` and runs
7
+ * `caddy reload`.
8
+ *
9
+ * Per-vhost shape:
10
+ * <hostname> {
11
+ * # admin → reverse_proxy localhost:5173
12
+ * # public → root + try_files (static), with /api/* → gateway
13
+ * # locale → same as public, scoped to a per-locale dist dir
14
+ * tls <ownerEmail>
15
+ * }
16
+ *
17
+ * Staging vhosts force `X-Robots-Tag: noindex`.
18
+ */
19
+ export interface CaddyDomainSpec {
20
+ readonly hostname: string;
21
+ readonly kind: "admin" | "public" | "locale-public";
22
+ readonly localeCode?: string;
23
+ readonly env: "production" | "staging";
24
+ }
25
+ export interface CaddyfileSpec {
26
+ readonly ownerEmail: string;
27
+ readonly publicSiteRoot: string;
28
+ readonly stagingSiteRoot: string;
29
+ readonly adminPort: number;
30
+ readonly gatewayPort: number;
31
+ readonly domains: ReadonlyArray<CaddyDomainSpec>;
32
+ }
33
+ export declare function generateCaddyfile(spec: CaddyfileSpec): string;
34
+ //# sourceMappingURL=caddy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caddy.d.ts","sourceRoot":"","sources":["../src/caddy.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,eAAe,CAAC;IACpD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;CAClD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAyB7D"}
package/dist/caddy.js ADDED
@@ -0,0 +1,53 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ export function generateCaddyfile(spec) {
3
+ const blocks = [];
4
+ // Global options.
5
+ blocks.push(`{
6
+ email ${spec.ownerEmail}
7
+ }
8
+ `);
9
+ for (const d of spec.domains) {
10
+ blocks.push(vhost(d, spec));
11
+ }
12
+ // Localhost dev fallback when no domains are configured (so a fresh
13
+ // `cms-provision` produces a working Caddyfile even pre-DNS).
14
+ if (spec.domains.length === 0) {
15
+ blocks.push(`# No domains configured yet — cms-provision regenerate-caddy
16
+ # will overwrite this file when you add one at /security/domains.
17
+ :8081 {
18
+ reverse_proxy localhost:${spec.adminPort}
19
+ }
20
+ `);
21
+ }
22
+ return blocks.join("\n");
23
+ }
24
+ function vhost(d, spec) {
25
+ const noindex = d.env === "staging" ? `\n header X-Robots-Tag "noindex"` : "";
26
+ if (d.kind === "admin") {
27
+ return `${d.hostname} {${noindex}
28
+ reverse_proxy localhost:${spec.adminPort}
29
+ }
30
+ `;
31
+ }
32
+ // public / locale-public — same shape: API routes go to the gateway,
33
+ // the rest serves static files. Locale variants serve from a
34
+ // per-locale subdirectory.
35
+ const root = d.env === "staging" ? spec.stagingSiteRoot : spec.publicSiteRoot;
36
+ const localeSubdir = d.kind === "locale-public" && d.localeCode ? `/${d.localeCode}` : "";
37
+ return `${d.hostname} {${noindex}
38
+ root * ${root}${localeSubdir}
39
+ handle /api/* {
40
+ reverse_proxy localhost:${spec.gatewayPort}
41
+ }
42
+ handle /admin/* {
43
+ reverse_proxy localhost:${spec.adminPort}
44
+ }
45
+ handle {
46
+ file_server {
47
+ try_files {path} {path}/index.html /index.html
48
+ }
49
+ }
50
+ }
51
+ `;
52
+ }
53
+ //# sourceMappingURL=caddy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caddy.js","sourceRoot":"","sources":["../src/caddy.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAqCnC,MAAM,UAAU,iBAAiB,CAAC,IAAmB;IACnD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,kBAAkB;IAClB,MAAM,CAAC,IAAI,CAAC;UACJ,IAAI,CAAC,UAAU;;CAExB,CAAC,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9B,CAAC;IAED,oEAAoE;IACpE,8DAA8D;IAC9D,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC;;;4BAGY,IAAI,CAAC,SAAS;;CAEzC,CAAC,CAAC;IACD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,KAAK,CAAC,CAAkB,EAAE,IAAmB;IACpD,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,CAAC,QAAQ,KAAK,OAAO;4BACR,IAAI,CAAC,SAAS;;CAEzC,CAAC;IACA,CAAC;IACD,qEAAqE;IACrE,6DAA6D;IAC7D,2BAA2B;IAC3B,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC;IAC9E,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1F,OAAO,GAAG,CAAC,CAAC,QAAQ,KAAK,OAAO;WACvB,IAAI,GAAG,YAAY;;8BAEA,IAAI,CAAC,WAAW;;;8BAGhB,IAAI,CAAC,SAAS;;;;;;;;CAQ3C,CAAC;AACF,CAAC"}
@@ -1,5 +1,3 @@
1
- // SPDX-License-Identifier: MPL-2.0
2
-
3
1
  /**
4
2
  * P15 — per-provider CDN-copy adapter contract.
5
3
  *
@@ -21,32 +19,22 @@
21
19
  * `@aws-sdk/...`/`@google-cloud/...`/`@azure/...` as static deps). The
22
20
  * interface defined here is the only thing both sides agree on.
23
21
  */
24
-
25
22
  export interface CdnCopyAdapter {
26
- /**
27
- * Mark the asset at `assetKey` (object key in primary storage) as
28
- * CDN-cached. Returns the public CDN URL — admin uses this as the
29
- * canonical URL for the asset thereafter.
30
- */
31
- pin(assetKey: string): Promise<string>;
32
- /** Reverse — drop from CDN edge cache. */
33
- unpin(assetKey: string): Promise<void>;
23
+ /**
24
+ * Mark the asset at `assetKey` (object key in primary storage) as
25
+ * CDN-cached. Returns the public CDN URL — admin uses this as the
26
+ * canonical URL for the asset thereafter.
27
+ */
28
+ pin(assetKey: string): Promise<string>;
29
+ /** Reverse — drop from CDN edge cache. */
30
+ unpin(assetKey: string): Promise<void>;
34
31
  }
35
-
36
32
  /**
37
33
  * No-op adapter for self-hosted installs (Caddy serves directly from
38
34
  * disk; no separate CDN tier). Returns the input asset key as a relative
39
35
  * URL so callers don't have to special-case the no-CDN case.
40
36
  */
41
- export const selfHostedCdnCopy: CdnCopyAdapter = {
42
- async pin(assetKey) {
43
- return `/media/${assetKey}`;
44
- },
45
- async unpin() {
46
- // no-op
47
- },
48
- };
49
-
37
+ export declare const selfHostedCdnCopy: CdnCopyAdapter;
50
38
  /**
51
39
  * Resolves the right adapter per `process.env.CAELO_PROVIDER`. Lazy
52
40
  * dynamic-imports the per-provider implementation so a self-hosted
@@ -61,24 +49,5 @@ export const selfHostedCdnCopy: CdnCopyAdapter = {
61
49
  * a deploy bug + the orchestrator tick should crash loudly so the
62
50
  * operator notices instead of silently dropping CDN-pin requests.
63
51
  */
64
- export async function loadCdnCopyAdapter(provider?: string): Promise<CdnCopyAdapter> {
65
- switch (provider) {
66
- case "gcp":
67
- // biome-ignore lint/suspicious/noExplicitAny: opt-in dynamic import
68
- return ((await import("./cdn-copy-gcs.js" as string)) as any).gcsCloudCdnPin;
69
- case "aws":
70
- // biome-ignore lint/suspicious/noExplicitAny: opt-in dynamic import
71
- return ((await import("./cdn-copy-aws.js" as string)) as any).s3CloudfrontPrewarm;
72
- case "azure":
73
- // biome-ignore lint/suspicious/noExplicitAny: opt-in dynamic import
74
- return ((await import("./cdn-copy-azure.js" as string)) as any).azureBlobCdnPrefetch;
75
- case undefined:
76
- case "":
77
- case "self-hosted":
78
- return selfHostedCdnCopy;
79
- default:
80
- throw new Error(
81
- `loadCdnCopyAdapter: unknown CAELO_PROVIDER='${provider}'. Expected one of: self-hosted | gcp | aws | azure.`,
82
- );
83
- }
84
- }
52
+ export declare function loadCdnCopyAdapter(provider?: string): Promise<CdnCopyAdapter>;
53
+ //# sourceMappingURL=cdn-copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdn-copy.d.ts","sourceRoot":"","sources":["../src/cdn-copy.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,0CAA0C;IAC1C,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAO/B,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAoBnF"}
@@ -0,0 +1,48 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * No-op adapter for self-hosted installs (Caddy serves directly from
4
+ * disk; no separate CDN tier). Returns the input asset key as a relative
5
+ * URL so callers don't have to special-case the no-CDN case.
6
+ */
7
+ export const selfHostedCdnCopy = {
8
+ async pin(assetKey) {
9
+ return `/media/${assetKey}`;
10
+ },
11
+ async unpin() {
12
+ // no-op
13
+ },
14
+ };
15
+ /**
16
+ * Resolves the right adapter per `process.env.CAELO_PROVIDER`. Lazy
17
+ * dynamic-imports the per-provider implementation so a self-hosted
18
+ * install never loads the cloud SDKs.
19
+ *
20
+ * Returns `selfHostedCdnCopy` ONLY for `provider==='self-hosted'` or an
21
+ * unset env (treated as self-hosted). For `gcp`/`aws`/`azure`, the
22
+ * matching `cdn-copy-<gcs|aws|azure>.ts` file MUST exist in this
23
+ * directory — those land with the per-provider PRs. Per CLAUDE.md §2
24
+ * "no fallbacks pre-1.0" we deliberately do NOT silently degrade to
25
+ * the self-hosted no-op when the file is missing: a missing module is
26
+ * a deploy bug + the orchestrator tick should crash loudly so the
27
+ * operator notices instead of silently dropping CDN-pin requests.
28
+ */
29
+ export async function loadCdnCopyAdapter(provider) {
30
+ switch (provider) {
31
+ case "gcp":
32
+ // biome-ignore lint/suspicious/noExplicitAny: opt-in dynamic import
33
+ return (await import("./cdn-copy-gcs.js")).gcsCloudCdnPin;
34
+ case "aws":
35
+ // biome-ignore lint/suspicious/noExplicitAny: opt-in dynamic import
36
+ return (await import("./cdn-copy-aws.js")).s3CloudfrontPrewarm;
37
+ case "azure":
38
+ // biome-ignore lint/suspicious/noExplicitAny: opt-in dynamic import
39
+ return (await import("./cdn-copy-azure.js")).azureBlobCdnPrefetch;
40
+ case undefined:
41
+ case "":
42
+ case "self-hosted":
43
+ return selfHostedCdnCopy;
44
+ default:
45
+ throw new Error(`loadCdnCopyAdapter: unknown CAELO_PROVIDER='${provider}'. Expected one of: self-hosted | gcp | aws | azure.`);
46
+ }
47
+ }
48
+ //# sourceMappingURL=cdn-copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdn-copy.js","sourceRoot":"","sources":["../src/cdn-copy.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAmCnC;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAmB;IAC/C,KAAK,CAAC,GAAG,CAAC,QAAQ;QAChB,OAAO,UAAU,QAAQ,EAAE,CAAC;IAC9B,CAAC;IACD,KAAK,CAAC,KAAK;QACT,QAAQ;IACV,CAAC;CACF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAiB;IACxD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK;YACR,oEAAoE;YACpE,OAAQ,CAAC,MAAM,MAAM,CAAC,mBAA6B,CAAC,CAAS,CAAC,cAAc,CAAC;QAC/E,KAAK,KAAK;YACR,oEAAoE;YACpE,OAAQ,CAAC,MAAM,MAAM,CAAC,mBAA6B,CAAC,CAAS,CAAC,mBAAmB,CAAC;QACpF,KAAK,OAAO;YACV,oEAAoE;YACpE,OAAQ,CAAC,MAAM,MAAM,CAAC,qBAA+B,CAAC,CAAS,CAAC,oBAAoB,CAAC;QACvF,KAAK,SAAS,CAAC;QACf,KAAK,EAAE,CAAC;QACR,KAAK,aAAa;YAChB,OAAO,iBAAiB,CAAC;QAC3B;YACE,MAAM,IAAI,KAAK,CACb,+CAA+C,QAAQ,sDAAsD,CAC9G,CAAC;IACN,CAAC;AACH,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}