alchemy 0.1.12 → 0.1.14

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.
Files changed (168) hide show
  1. package/README.md +12 -2
  2. package/lib/$.d.ts +12 -0
  3. package/lib/$.d.ts.map +1 -0
  4. package/lib/$.js +42 -0
  5. package/lib/$.js.map +1 -0
  6. package/lib/alchemize.d.ts.map +1 -1
  7. package/lib/alchemize.js +7 -0
  8. package/lib/alchemize.js.map +1 -1
  9. package/lib/apply.d.ts +2 -2
  10. package/lib/apply.d.ts.map +1 -1
  11. package/lib/apply.js +1 -1
  12. package/lib/apply.js.map +1 -1
  13. package/lib/aws/account-id.d.ts +5 -0
  14. package/lib/aws/account-id.d.ts.map +1 -0
  15. package/lib/aws/account-id.js +10 -0
  16. package/lib/aws/account-id.js.map +1 -0
  17. package/lib/aws/index.d.ts +1 -0
  18. package/lib/aws/index.d.ts.map +1 -1
  19. package/lib/aws/index.js +1 -0
  20. package/lib/aws/index.js.map +1 -1
  21. package/lib/aws/oidc/github-oidc-provider.d.ts +11 -0
  22. package/lib/aws/oidc/github-oidc-provider.d.ts.map +1 -0
  23. package/lib/aws/oidc/github-oidc-provider.js +22 -0
  24. package/lib/aws/oidc/github-oidc-provider.js.map +1 -0
  25. package/lib/aws/oidc/index.d.ts +3 -0
  26. package/lib/aws/oidc/index.d.ts.map +1 -0
  27. package/lib/aws/oidc/index.js +3 -0
  28. package/lib/aws/oidc/index.js.map +1 -0
  29. package/lib/aws/oidc/oidc-provider.d.ts +60 -0
  30. package/lib/aws/oidc/oidc-provider.d.ts.map +1 -0
  31. package/lib/aws/oidc/oidc-provider.js +140 -0
  32. package/lib/aws/oidc/oidc-provider.js.map +1 -0
  33. package/lib/aws/queue.d.ts +24 -0
  34. package/lib/aws/queue.d.ts.map +1 -1
  35. package/lib/aws/queue.js +6 -1
  36. package/lib/aws/queue.js.map +1 -1
  37. package/lib/aws/role.d.ts.map +1 -1
  38. package/lib/aws/role.js +49 -1
  39. package/lib/aws/role.js.map +1 -1
  40. package/lib/aws/ses.d.ts.map +1 -1
  41. package/lib/aws/ses.js +20 -28
  42. package/lib/aws/ses.js.map +1 -1
  43. package/lib/aws/table.d.ts.map +1 -1
  44. package/lib/aws/table.js +95 -73
  45. package/lib/aws/table.js.map +1 -1
  46. package/lib/cloudflare/api.d.ts +4 -0
  47. package/lib/cloudflare/api.d.ts.map +1 -1
  48. package/lib/cloudflare/api.js +6 -0
  49. package/lib/cloudflare/api.js.map +1 -1
  50. package/lib/cloudflare/bindings.d.ts +19 -4
  51. package/lib/cloudflare/bindings.d.ts.map +1 -1
  52. package/lib/cloudflare/bindings.js +0 -5
  53. package/lib/cloudflare/bindings.js.map +1 -1
  54. package/lib/cloudflare/durable-object-namespace.d.ts +20 -0
  55. package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -0
  56. package/lib/cloudflare/durable-object-namespace.js +21 -0
  57. package/lib/cloudflare/durable-object-namespace.js.map +1 -0
  58. package/lib/cloudflare/index.d.ts +1 -0
  59. package/lib/cloudflare/index.d.ts.map +1 -1
  60. package/lib/cloudflare/index.js +1 -0
  61. package/lib/cloudflare/index.js.map +1 -1
  62. package/lib/cloudflare/kv-namespace.d.ts +3 -0
  63. package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
  64. package/lib/cloudflare/kv-namespace.js +5 -1
  65. package/lib/cloudflare/kv-namespace.js.map +1 -1
  66. package/lib/cloudflare/static-site-router.d.ts +11 -2
  67. package/lib/cloudflare/static-site-router.d.ts.map +1 -1
  68. package/lib/cloudflare/static-site-router.js +98 -76
  69. package/lib/cloudflare/static-site-router.js.map +1 -1
  70. package/lib/cloudflare/static-site.d.ts +15 -15
  71. package/lib/cloudflare/static-site.d.ts.map +1 -1
  72. package/lib/cloudflare/static-site.js +45 -47
  73. package/lib/cloudflare/static-site.js.map +1 -1
  74. package/lib/cloudflare/worker-metadata.d.ts +130 -0
  75. package/lib/cloudflare/worker-metadata.d.ts.map +1 -0
  76. package/lib/cloudflare/worker-metadata.js +2 -0
  77. package/lib/cloudflare/worker-metadata.js.map +1 -0
  78. package/lib/cloudflare/worker-migration.d.ts +110 -0
  79. package/lib/cloudflare/worker-migration.d.ts.map +1 -0
  80. package/lib/cloudflare/worker-migration.js +11 -0
  81. package/lib/cloudflare/worker-migration.js.map +1 -0
  82. package/lib/cloudflare/worker.d.ts +34 -13
  83. package/lib/cloudflare/worker.d.ts.map +1 -1
  84. package/lib/cloudflare/worker.js +341 -321
  85. package/lib/cloudflare/worker.js.map +1 -1
  86. package/lib/destroy.d.ts +1 -1
  87. package/lib/destroy.d.ts.map +1 -1
  88. package/lib/destroy.js +2 -1
  89. package/lib/destroy.js.map +1 -1
  90. package/lib/esbuild.d.ts +1 -1
  91. package/lib/esbuild.d.ts.map +1 -1
  92. package/lib/esbuild.js +3 -1
  93. package/lib/esbuild.js.map +1 -1
  94. package/lib/github/client.d.ts +34 -0
  95. package/lib/github/client.d.ts.map +1 -0
  96. package/lib/github/client.js +91 -0
  97. package/lib/github/client.js.map +1 -0
  98. package/lib/github/index.d.ts +2 -0
  99. package/lib/github/index.d.ts.map +1 -0
  100. package/lib/github/index.js +2 -0
  101. package/lib/github/index.js.map +1 -0
  102. package/lib/github/secret.d.ts +46 -0
  103. package/lib/github/secret.d.ts.map +1 -0
  104. package/lib/github/secret.js +103 -0
  105. package/lib/github/secret.js.map +1 -0
  106. package/lib/global.d.ts +0 -2
  107. package/lib/global.d.ts.map +1 -1
  108. package/lib/global.js +0 -2
  109. package/lib/global.js.map +1 -1
  110. package/lib/index.d.ts +2 -0
  111. package/lib/index.d.ts.map +1 -1
  112. package/lib/index.js +2 -0
  113. package/lib/index.js.map +1 -1
  114. package/lib/output.d.ts +4 -3
  115. package/lib/output.d.ts.map +1 -1
  116. package/lib/output.js +10 -3
  117. package/lib/output.js.map +1 -1
  118. package/lib/print.d.ts +7 -0
  119. package/lib/print.d.ts.map +1 -0
  120. package/lib/print.js +10 -0
  121. package/lib/print.js.map +1 -0
  122. package/lib/resource.d.ts +8 -4
  123. package/lib/resource.d.ts.map +1 -1
  124. package/lib/resource.js +125 -91
  125. package/lib/resource.js.map +1 -1
  126. package/lib/scope.d.ts +3 -0
  127. package/lib/scope.d.ts.map +1 -1
  128. package/lib/scope.js +4 -12
  129. package/lib/scope.js.map +1 -1
  130. package/lib/utils/retry.d.ts +13 -0
  131. package/lib/utils/retry.d.ts.map +1 -0
  132. package/lib/utils/retry.js +31 -0
  133. package/lib/utils/retry.js.map +1 -0
  134. package/package.json +12 -3
  135. package/src/$.ts +69 -0
  136. package/src/alchemize.ts +12 -0
  137. package/src/apply.ts +4 -4
  138. package/src/aws/account-id.ts +11 -0
  139. package/src/aws/index.ts +1 -0
  140. package/src/aws/oidc/github-oidc-provider.ts +34 -0
  141. package/src/aws/oidc/index.ts +2 -0
  142. package/src/aws/oidc/oidc-provider.ts +253 -0
  143. package/src/aws/queue.ts +23 -1
  144. package/src/aws/role.ts +69 -0
  145. package/src/aws/ses.ts +27 -31
  146. package/src/aws/table.ts +113 -82
  147. package/src/cloudflare/api.ts +6 -0
  148. package/src/cloudflare/bindings.ts +43 -26
  149. package/src/cloudflare/durable-object-namespace.ts +37 -0
  150. package/src/cloudflare/index.ts +1 -0
  151. package/src/cloudflare/kv-namespace.ts +12 -1
  152. package/src/cloudflare/static-site-router.ts +124 -82
  153. package/src/cloudflare/static-site.ts +66 -69
  154. package/src/cloudflare/worker-metadata.ts +154 -0
  155. package/src/cloudflare/worker-migration.ts +145 -0
  156. package/src/cloudflare/worker.ts +557 -429
  157. package/src/destroy.ts +2 -2
  158. package/src/esbuild.ts +3 -0
  159. package/src/github/client.ts +115 -0
  160. package/src/github/index.ts +1 -0
  161. package/src/github/secret.ts +172 -0
  162. package/src/global.ts +0 -3
  163. package/src/index.ts +2 -1
  164. package/src/output.ts +24 -8
  165. package/src/print.ts +18 -0
  166. package/src/resource.ts +156 -115
  167. package/src/scope.ts +7 -12
  168. package/src/utils/retry.ts +36 -0
@@ -1,108 +1,150 @@
1
+ import { Hono } from "hono";
2
+
1
3
  // see: https://developers.cloudflare.com/workers/runtime-apis/cache/
2
- declare var caches: any;
4
+ declare var caches: {
5
+ default: Cache;
6
+ };
3
7
 
4
8
  // injected by src/cloudflare/static-site.ts
5
9
  declare var __ASSET_MANIFEST__: Record<string, string>;
6
10
 
7
- export interface Env {
11
+ export type Env = {
8
12
  ASSETS: KVNamespace;
9
13
  INDEX_PAGE: string;
10
14
  ERROR_PAGE?: string;
11
- }
15
+ /**
16
+ * Optional backend worker bound to this static site
17
+ * Used to handle requests that don't match any static files
18
+ */
19
+ BACKEND_WORKER?: Service;
20
+ } & {
21
+ // the binding to route the fetch call to
22
+ [key in `ROUTE_${string}`]: Service;
23
+ } & {
24
+ // the route to match on, e.g. /api/*
25
+ [key in `__ROUTE_${string}`]: string;
26
+ };
27
+
28
+ let isInit = false;
29
+ const app = new Hono<{ Bindings: Env }>();
12
30
 
13
31
  export default {
14
32
  async fetch(request: Request, env: Env): Promise<Response> {
15
- const url = new URL(request.url);
16
- console.log("url", request.url);
17
- const pathname = url.pathname.replace(/^\//, "");
18
- const filePath = pathname === "" ? env.INDEX_PAGE : pathname;
19
-
20
- // Return from cache if available
21
- const cachedResponse = await lookupCache();
22
- if (cachedResponse) return cachedResponse;
23
-
24
- // Fetch from KV
25
- {
26
- const object = await env.ASSETS.getWithMetadata(filePath);
27
- if (object.value) return await respond(200, filePath, object);
33
+ if (!isInit) {
34
+ isInit = true;
35
+ for (const [key, value] of Object.entries(env)) {
36
+ if (key.startsWith("ROUTE_")) {
37
+ console.log(key, value);
38
+ const service = value as Service;
39
+ const patternKey = `__${key}`;
40
+ if (!(patternKey in env)) {
41
+ throw new Error(`Missing pattern key: ${patternKey}`);
42
+ }
43
+ const pattern = (env as any)[`__${key}`];
44
+ console.log("pattern", pattern);
45
+ // TODO(sam): we should support narrowing down METHOD
46
+ app.all(pattern, (ctx) => service.fetch(ctx.req.raw));
47
+ }
48
+ }
28
49
  }
29
- {
30
- const guess =
31
- filePath + (filePath.endsWith("/") ? "" : "/") + "index.html";
32
- const object = await env.ASSETS.getWithMetadata(guess);
33
- if (object.value) return await respond(200, guess, object);
50
+ return app.fetch(request, env);
51
+ },
52
+ };
53
+
54
+ // fall back to assuming the request is a static file
55
+ app.notFound(async (ctx) => {
56
+ console.log("not found");
57
+ const request = ctx.req;
58
+ const env = ctx.env;
59
+ const url = new URL(request.url);
60
+ const pathname = url.pathname.replace(/^\//, "");
61
+ const filePath = pathname === "" ? env.INDEX_PAGE : pathname;
62
+
63
+ // Return from cache if available
64
+ const cachedResponse = await lookupCache();
65
+ if (cachedResponse) {
66
+ return cachedResponse;
67
+ }
68
+
69
+ // Fetch from KV
70
+ {
71
+ const object = await env.ASSETS.getWithMetadata(filePath);
72
+ if (object.value) {
73
+ return await respond(200, filePath, object);
34
74
  }
35
- {
36
- const guess = filePath + ".html";
37
- const object = await env.ASSETS.getWithMetadata(guess);
38
- if (object.value) return await respond(200, guess, object);
75
+ }
76
+ {
77
+ const guess = filePath + (filePath.endsWith("/") ? "" : "/") + "index.html";
78
+ const object = await env.ASSETS.getWithMetadata(guess);
79
+ if (object.value) {
80
+ return await respond(200, guess, object);
39
81
  }
40
-
41
- // Handle error page
42
- if (env.ERROR_PAGE) {
43
- const object = await env.ASSETS.getWithMetadata(env.ERROR_PAGE);
44
- if (object.value) return await respond(404, env.ERROR_PAGE, object);
45
- } else {
46
- const object = await env.ASSETS.getWithMetadata(env.INDEX_PAGE);
47
- if (object.value) return await respond(200, env.INDEX_PAGE, object);
82
+ }
83
+ {
84
+ const guess = filePath + ".html";
85
+ const object = await env.ASSETS.getWithMetadata(guess);
86
+ if (object.value) {
87
+ return await respond(200, guess, object);
48
88
  }
89
+ }
49
90
 
50
- // Handle failed to render error page
51
- return new Response("Page Not Found", { status: 404 });
91
+ // Handle error page
92
+ if (env.ERROR_PAGE) {
93
+ const object = await env.ASSETS.getWithMetadata(env.ERROR_PAGE);
94
+ if (object.value) {
95
+ return await respond(404, env.ERROR_PAGE, object);
96
+ }
97
+ } else {
98
+ const object = await env.ASSETS.getWithMetadata(env.INDEX_PAGE);
99
+ if (object.value) {
100
+ return await respond(200, env.INDEX_PAGE, object);
101
+ }
102
+ }
52
103
 
53
- async function lookupCache() {
54
- const cache = caches.default;
55
- const r = await cache.match(request);
104
+ return new Response("Page Not Found", { status: 404 });
56
105
 
57
- // cache does not exist
58
- if (!r) return;
106
+ async function lookupCache() {
107
+ const cache = caches.default;
108
+ const r = await cache.match(request.url);
59
109
 
60
- // cache exists but etag does not match
61
- if (r.headers.get("etag") !== __ASSET_MANIFEST__[filePath]) return;
110
+ // cache does not exist
111
+ if (!r) return;
62
112
 
63
- // cache exists
64
- return r;
65
- }
113
+ // cache exists but etag does not match
114
+ if (r.headers.get("etag") !== __ASSET_MANIFEST__[filePath]) return;
66
115
 
67
- async function saveCache(response: Response) {
68
- const cache = caches.default;
69
- await cache.put(request, response.clone());
70
- }
116
+ // cache exists
117
+ return r;
118
+ }
71
119
 
72
- async function respond(
73
- status: number,
74
- filePath: string,
75
- object: KVNamespaceGetWithMetadataResult<any, any>,
76
- ) {
77
- // build response
78
- const headers = new Headers();
79
- if (__ASSET_MANIFEST__[filePath]) {
80
- headers.set("etag", __ASSET_MANIFEST__[filePath]);
81
- headers.set("content-type", object.metadata.contentType);
82
- headers.set("cache-control", object.metadata.cacheControl);
83
- }
84
- // TODO: do we need base64 encoded here?
85
- // const response = new Response(base64ToArrayBuffer(object.value), {
86
- const response = new Response(object.value, {
87
- status,
88
- headers,
89
- });
90
-
91
- if (request.method === "GET") {
92
- await saveCache(response);
93
- }
120
+ async function saveCache(response: Response) {
121
+ const cache = caches.default;
122
+ await cache.put(request.url, response.clone());
123
+ }
94
124
 
95
- return response;
125
+ async function respond(
126
+ status: number,
127
+ filePath: string,
128
+ object: KVNamespaceGetWithMetadataResult<any, any>,
129
+ ) {
130
+ // build response
131
+ const headers = new Headers();
132
+ if (__ASSET_MANIFEST__[filePath]) {
133
+ headers.set("etag", __ASSET_MANIFEST__[filePath]);
134
+ headers.set("content-type", object.metadata.contentType);
135
+ headers.set("cache-control", object.metadata.cacheControl);
136
+ }
137
+ // TODO: do we need base64 encoded here?
138
+ // const response = new Response(base64ToArrayBuffer(object.value), {
139
+ const response = new Response(object.value, {
140
+ status,
141
+ headers,
142
+ });
143
+
144
+ if (request.method === "GET") {
145
+ await saveCache(response);
96
146
  }
97
- },
98
- };
99
147
 
100
- function base64ToArrayBuffer(base64: any) {
101
- const binaryString = atob(base64);
102
- const len = binaryString.length;
103
- const bytes = new Uint8Array(len);
104
- for (let i = 0; i < len; i++) {
105
- bytes[i] = binaryString.charCodeAt(i);
148
+ return response;
106
149
  }
107
- return bytes.buffer;
108
- }
150
+ });
@@ -4,15 +4,17 @@ import path from "path";
4
4
  import { promisify } from "util";
5
5
  import { apply } from "../apply";
6
6
  import type { BundleProps } from "../esbuild";
7
+ import type { Input } from "../input";
7
8
  import { type Context, Resource } from "../resource";
8
9
  import { createCloudflareApi } from "./api";
9
- import type { WorkerBinding } from "./bindings";
10
+ import type { Bindings } from "./bindings";
10
11
  import { generateAssetManifest } from "./generate-asset-manifest";
11
12
  import { KVNamespace } from "./kv-namespace";
12
13
  import { uploadAssetManifest } from "./upload-asset-manifest";
13
- import type { WorkerProps } from "./worker";
14
14
  import { Worker } from "./worker";
15
15
 
16
+ const __dirname = import.meta.dirname;
17
+
16
18
  /**
17
19
  * Idea of using KV with timeout inspired by SST: https://github.com/sst/sst/blob/dev/platform/src/components/cloudflare/static-site.ts
18
20
  */
@@ -32,12 +34,6 @@ export interface StaticSiteProps {
32
34
  */
33
35
  dir: string;
34
36
 
35
- /**
36
- * Routes to associate with this site
37
- * Format: example.com/* or *.example.com/*
38
- */
39
- routes?: string[];
40
-
41
37
  /**
42
38
  * Custom Worker script to serve the site
43
39
  * If not provided, a default script will be used
@@ -95,11 +91,6 @@ export interface StaticSiteProps {
95
91
  }[];
96
92
  };
97
93
 
98
- /**
99
- * Additional Worker bindings to include
100
- */
101
- additionalBindings?: WorkerProps["bindings"];
102
-
103
94
  /**
104
95
  * Whether the site should be deployed to production
105
96
  * @default true
@@ -124,7 +115,17 @@ export interface StaticSiteProps {
124
115
  command?: string;
125
116
  };
126
117
 
118
+ /**
119
+ * Bundle options for the worker script
120
+ */
127
121
  bundle?: Partial<BundleProps>;
122
+
123
+ /**
124
+ * Additional workers to route requests to.
125
+ */
126
+ routes?: {
127
+ [key: string]: Worker;
128
+ };
128
129
  }
129
130
 
130
131
  /**
@@ -151,11 +152,6 @@ export interface StaticSiteOutput {
151
152
  */
152
153
  directory: string;
153
154
 
154
- /**
155
- * Routes to associate with this site
156
- */
157
- routes?: string[];
158
-
159
155
  /**
160
156
  * Worker script format
161
157
  */
@@ -205,6 +201,11 @@ export interface StaticSiteOutput {
205
201
  * The URL of the deployed site
206
202
  */
207
203
  url?: string;
204
+
205
+ /**
206
+ * Information about the backend worker if configured
207
+ */
208
+ routes?: Record<string, string>;
208
209
  }
209
210
 
210
211
  export class StaticSite extends Resource(
@@ -245,13 +246,15 @@ export class StaticSite extends Resource(
245
246
  // Run build command if provided
246
247
  if (props.build?.command) {
247
248
  try {
248
- console.log(props.build.command);
249
+ if (!ctx.quiet) {
250
+ console.log(props.build.command);
251
+ }
249
252
  const execAsync = promisify(exec);
250
253
  const { stdout, stderr } = await execAsync(props.build.command, {
251
254
  cwd: process.cwd(),
252
255
  });
253
256
 
254
- if (stdout) console.log(stdout);
257
+ if (stdout && !ctx.quiet) console.log(stdout);
255
258
  } catch (error: any) {
256
259
  // Log detailed error information
257
260
  console.error(`Build command failed with exit code ${error.code}`);
@@ -273,47 +276,36 @@ export class StaticSite extends Resource(
273
276
  const api = await createCloudflareApi();
274
277
 
275
278
  // Step 1: Create or get the KV namespace for assets
276
- const namespace = new KVNamespace("assets", {
279
+ const kv = new KVNamespace("assets", {
277
280
  title: `${siteName}-assets`,
278
281
  });
279
282
 
280
283
  const [{ id: kvNamespaceId }, assetManifest] = await Promise.all([
281
- apply(namespace),
284
+ apply(kv, {
285
+ quiet: ctx.quiet,
286
+ }),
282
287
  generateAssetManifest(props.dir),
283
288
  ]);
284
289
 
285
290
  // Step 3: Upload assets to KV
286
291
  await uploadAssetManifest(api, kvNamespaceId, assetManifest);
287
292
 
288
- // Define the worker script path
289
- const routerScriptPath = path.resolve(__dirname, "static-site-router.ts");
290
-
291
293
  // Prepare the bindings for the worker
292
- const bindings: WorkerBinding[] = [
293
- {
294
- name: "ASSETS",
295
- type: "kv_namespace",
296
- namespace_id: kvNamespaceId,
297
- },
298
- {
299
- name: "INDEX_PAGE",
300
- type: "plain_text",
301
- text: indexPage,
302
- },
303
- ];
304
-
305
- // Add error page binding if specified
306
- if (props.errorPage) {
307
- bindings.push({
308
- name: "ERROR_PAGE",
309
- type: "plain_text",
310
- text: props.errorPage,
311
- });
312
- }
294
+ const bindings: Input<Bindings> = {
295
+ ASSETS: kv,
296
+ INDEX_PAGE: indexPage,
297
+ // Add error page binding if specified
298
+ ...(props.errorPage ? { ERROR_PAGE: props.errorPage } : {}),
299
+ };
313
300
 
314
- // Add any additional bindings
315
- if (props.additionalBindings) {
316
- bindings.push(...props.additionalBindings);
301
+ const routes: Record<string, string> = {};
302
+ // Create backend worker if configured
303
+ if (props.routes) {
304
+ for (const [path, worker] of Object.entries(props.routes)) {
305
+ // @ts-ignore - TODO: need to use Resolved<Worker> to get the string ...
306
+ routes[path] = worker.id;
307
+ bindings[`ROUTE_${worker.id}`] = worker;
308
+ }
317
309
  }
318
310
 
319
311
  // Create asset manifest banner for static site router
@@ -321,48 +313,52 @@ export class StaticSite extends Resource(
321
313
  Object.fromEntries(assetManifest.map((item) => [item.key, item.hash])),
322
314
  )};\n`;
323
315
 
316
+ const bundleOptions = {
317
+ ...props.bundle,
318
+ options: {
319
+ ...props.bundle?.options,
320
+ banner: {
321
+ js: assetManifestBanner,
322
+ ...props.bundle?.options?.banner,
323
+ },
324
+ },
325
+ };
324
326
  const worker = new Worker(
325
327
  "worker",
326
328
  {
327
329
  name: siteName,
328
330
  url: true,
329
331
  format: props.format || "esm",
330
- routes: props.routes || [],
331
332
  // If a custom worker script is provided, use it, otherwise use the entrypoint from router
332
333
  ...(props.workerScript
333
334
  ? { script: props.workerScript }
334
335
  : {
335
- entrypoint: routerScriptPath,
336
- bundleOptions: {
337
- ...props.bundle,
338
- options: {
339
- ...props.bundle?.options,
340
- banner: {
341
- js: assetManifestBanner,
342
- ...props.bundle?.options?.banner,
343
- },
344
- },
345
- },
336
+ entrypoint: path.resolve(__dirname, "static-site-router.ts"),
337
+ bundle: bundleOptions,
346
338
  }),
347
339
  bindings,
340
+ env: {
341
+ ...Object.fromEntries(
342
+ Object.entries(routes).map(([key, value]) => [
343
+ `__ROUTE_${value}`,
344
+ key,
345
+ ]),
346
+ ),
347
+ },
348
348
  },
349
349
  // place a dependency on the namespace
350
- namespace.id,
350
+ kv.id,
351
351
  );
352
352
 
353
- // Step 4: Create or update the worker
354
- const { id: workerId, url } = await apply(worker);
355
-
356
353
  // Get current timestamp
357
354
  const now = Date.now();
358
355
 
359
356
  // Construct the output
360
- const output: StaticSiteOutput = {
357
+ const output: Input<StaticSiteOutput> = {
361
358
  id: siteName,
362
- workerId,
359
+ workerId: worker.id,
363
360
  name: siteName,
364
361
  directory: props.dir,
365
- routes: props.routes || [],
366
362
  format: props.format || "esm",
367
363
  errorPage: props.errorPage,
368
364
  indexPage,
@@ -371,7 +367,8 @@ export class StaticSite extends Resource(
371
367
  updatedAt: now,
372
368
  domain: props.domain,
373
369
  production: props.production !== false,
374
- url,
370
+ url: worker.url,
371
+ routes,
375
372
  };
376
373
 
377
374
  return output;
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Metadata returned by Cloudflare API for a worker script
3
+ */
4
+ export interface WorkerScriptMetadata {
5
+ /**
6
+ * Worker ID
7
+ */
8
+ id: string;
9
+
10
+ /**
11
+ * Default environment information
12
+ */
13
+ default_environment?: WorkerDefaultEnvironment;
14
+
15
+ /**
16
+ * Worker creation timestamp
17
+ */
18
+ created_on: string;
19
+
20
+ /**
21
+ * Worker last modification timestamp
22
+ */
23
+ modified_on: string;
24
+
25
+ /**
26
+ * Worker usage model
27
+ */
28
+ usage_model: string;
29
+
30
+ /**
31
+ * Worker environments
32
+ */
33
+ environments?: WorkerEnvironment[];
34
+ }
35
+
36
+ /**
37
+ * Worker script information
38
+ */
39
+ export interface WorkerScriptInfo {
40
+ /**
41
+ * Script creation timestamp
42
+ */
43
+ created_on: string;
44
+
45
+ /**
46
+ * Script last modification timestamp
47
+ */
48
+ modified_on: string;
49
+
50
+ /**
51
+ * Script ID
52
+ */
53
+ id: string;
54
+
55
+ /**
56
+ * Script tag
57
+ */
58
+ tag: string;
59
+
60
+ /**
61
+ * Script tags
62
+ */
63
+ tags: string[];
64
+
65
+ /**
66
+ * Deployment ID
67
+ */
68
+ deployment_id: string;
69
+
70
+ /**
71
+ * Tail consumers
72
+ */
73
+ tail_consumers: any;
74
+
75
+ /**
76
+ * Whether logpush is enabled
77
+ */
78
+ logpush: boolean;
79
+
80
+ /**
81
+ * Observability settings
82
+ */
83
+ observability: {
84
+ /**
85
+ * Whether observability is enabled
86
+ */
87
+ enabled: boolean;
88
+
89
+ /**
90
+ * Head sampling rate
91
+ */
92
+ head_sampling_rate: number | null;
93
+ };
94
+
95
+ /**
96
+ * Whether the script has assets
97
+ */
98
+ has_assets: boolean;
99
+
100
+ /**
101
+ * Whether the script has modules
102
+ */
103
+ has_modules: boolean;
104
+
105
+ /**
106
+ * Script etag
107
+ */
108
+ etag: string;
109
+
110
+ /**
111
+ * Script handlers
112
+ */
113
+ handlers: string[];
114
+
115
+ /**
116
+ * Where the script was last deployed from
117
+ */
118
+ last_deployed_from: string;
119
+
120
+ /**
121
+ * Script usage model
122
+ */
123
+ usage_model: string;
124
+ }
125
+
126
+ /**
127
+ * Worker environment information
128
+ */
129
+ export interface WorkerEnvironment {
130
+ /**
131
+ * Environment name
132
+ */
133
+ environment: string;
134
+
135
+ /**
136
+ * Environment creation timestamp
137
+ */
138
+ created_on: string;
139
+
140
+ /**
141
+ * Environment last modification timestamp
142
+ */
143
+ modified_on: string;
144
+ }
145
+
146
+ /**
147
+ * Default environment with script information
148
+ */
149
+ export interface WorkerDefaultEnvironment extends WorkerEnvironment {
150
+ /**
151
+ * Script information
152
+ */
153
+ script: WorkerScriptInfo;
154
+ }