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.
- package/README.md +12 -2
- package/lib/$.d.ts +12 -0
- package/lib/$.d.ts.map +1 -0
- package/lib/$.js +42 -0
- package/lib/$.js.map +1 -0
- package/lib/alchemize.d.ts.map +1 -1
- package/lib/alchemize.js +7 -0
- package/lib/alchemize.js.map +1 -1
- package/lib/apply.d.ts +2 -2
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +1 -1
- package/lib/apply.js.map +1 -1
- package/lib/aws/account-id.d.ts +5 -0
- package/lib/aws/account-id.d.ts.map +1 -0
- package/lib/aws/account-id.js +10 -0
- package/lib/aws/account-id.js.map +1 -0
- package/lib/aws/index.d.ts +1 -0
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +1 -0
- package/lib/aws/index.js.map +1 -1
- package/lib/aws/oidc/github-oidc-provider.d.ts +11 -0
- package/lib/aws/oidc/github-oidc-provider.d.ts.map +1 -0
- package/lib/aws/oidc/github-oidc-provider.js +22 -0
- package/lib/aws/oidc/github-oidc-provider.js.map +1 -0
- package/lib/aws/oidc/index.d.ts +3 -0
- package/lib/aws/oidc/index.d.ts.map +1 -0
- package/lib/aws/oidc/index.js +3 -0
- package/lib/aws/oidc/index.js.map +1 -0
- package/lib/aws/oidc/oidc-provider.d.ts +60 -0
- package/lib/aws/oidc/oidc-provider.d.ts.map +1 -0
- package/lib/aws/oidc/oidc-provider.js +140 -0
- package/lib/aws/oidc/oidc-provider.js.map +1 -0
- package/lib/aws/queue.d.ts +24 -0
- package/lib/aws/queue.d.ts.map +1 -1
- package/lib/aws/queue.js +6 -1
- package/lib/aws/queue.js.map +1 -1
- package/lib/aws/role.d.ts.map +1 -1
- package/lib/aws/role.js +49 -1
- package/lib/aws/role.js.map +1 -1
- package/lib/aws/ses.d.ts.map +1 -1
- package/lib/aws/ses.js +20 -28
- package/lib/aws/ses.js.map +1 -1
- package/lib/aws/table.d.ts.map +1 -1
- package/lib/aws/table.js +95 -73
- package/lib/aws/table.js.map +1 -1
- package/lib/cloudflare/api.d.ts +4 -0
- package/lib/cloudflare/api.d.ts.map +1 -1
- package/lib/cloudflare/api.js +6 -0
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/bindings.d.ts +19 -4
- package/lib/cloudflare/bindings.d.ts.map +1 -1
- package/lib/cloudflare/bindings.js +0 -5
- package/lib/cloudflare/bindings.js.map +1 -1
- package/lib/cloudflare/durable-object-namespace.d.ts +20 -0
- package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -0
- package/lib/cloudflare/durable-object-namespace.js +21 -0
- package/lib/cloudflare/durable-object-namespace.js.map +1 -0
- package/lib/cloudflare/index.d.ts +1 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +1 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/kv-namespace.d.ts +3 -0
- package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
- package/lib/cloudflare/kv-namespace.js +5 -1
- package/lib/cloudflare/kv-namespace.js.map +1 -1
- package/lib/cloudflare/static-site-router.d.ts +11 -2
- package/lib/cloudflare/static-site-router.d.ts.map +1 -1
- package/lib/cloudflare/static-site-router.js +98 -76
- package/lib/cloudflare/static-site-router.js.map +1 -1
- package/lib/cloudflare/static-site.d.ts +15 -15
- package/lib/cloudflare/static-site.d.ts.map +1 -1
- package/lib/cloudflare/static-site.js +45 -47
- package/lib/cloudflare/static-site.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +130 -0
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -0
- package/lib/cloudflare/worker-metadata.js +2 -0
- package/lib/cloudflare/worker-metadata.js.map +1 -0
- package/lib/cloudflare/worker-migration.d.ts +110 -0
- package/lib/cloudflare/worker-migration.d.ts.map +1 -0
- package/lib/cloudflare/worker-migration.js +11 -0
- package/lib/cloudflare/worker-migration.js.map +1 -0
- package/lib/cloudflare/worker.d.ts +34 -13
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +341 -321
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/destroy.d.ts +1 -1
- package/lib/destroy.d.ts.map +1 -1
- package/lib/destroy.js +2 -1
- package/lib/destroy.js.map +1 -1
- package/lib/esbuild.d.ts +1 -1
- package/lib/esbuild.d.ts.map +1 -1
- package/lib/esbuild.js +3 -1
- package/lib/esbuild.js.map +1 -1
- package/lib/github/client.d.ts +34 -0
- package/lib/github/client.d.ts.map +1 -0
- package/lib/github/client.js +91 -0
- package/lib/github/client.js.map +1 -0
- package/lib/github/index.d.ts +2 -0
- package/lib/github/index.d.ts.map +1 -0
- package/lib/github/index.js +2 -0
- package/lib/github/index.js.map +1 -0
- package/lib/github/secret.d.ts +46 -0
- package/lib/github/secret.d.ts.map +1 -0
- package/lib/github/secret.js +103 -0
- package/lib/github/secret.js.map +1 -0
- package/lib/global.d.ts +0 -2
- package/lib/global.d.ts.map +1 -1
- package/lib/global.js +0 -2
- package/lib/global.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/output.d.ts +4 -3
- package/lib/output.d.ts.map +1 -1
- package/lib/output.js +10 -3
- package/lib/output.js.map +1 -1
- package/lib/print.d.ts +7 -0
- package/lib/print.d.ts.map +1 -0
- package/lib/print.js +10 -0
- package/lib/print.js.map +1 -0
- package/lib/resource.d.ts +8 -4
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js +125 -91
- package/lib/resource.js.map +1 -1
- package/lib/scope.d.ts +3 -0
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +4 -12
- package/lib/scope.js.map +1 -1
- package/lib/utils/retry.d.ts +13 -0
- package/lib/utils/retry.d.ts.map +1 -0
- package/lib/utils/retry.js +31 -0
- package/lib/utils/retry.js.map +1 -0
- package/package.json +12 -3
- package/src/$.ts +69 -0
- package/src/alchemize.ts +12 -0
- package/src/apply.ts +4 -4
- package/src/aws/account-id.ts +11 -0
- package/src/aws/index.ts +1 -0
- package/src/aws/oidc/github-oidc-provider.ts +34 -0
- package/src/aws/oidc/index.ts +2 -0
- package/src/aws/oidc/oidc-provider.ts +253 -0
- package/src/aws/queue.ts +23 -1
- package/src/aws/role.ts +69 -0
- package/src/aws/ses.ts +27 -31
- package/src/aws/table.ts +113 -82
- package/src/cloudflare/api.ts +6 -0
- package/src/cloudflare/bindings.ts +43 -26
- package/src/cloudflare/durable-object-namespace.ts +37 -0
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/kv-namespace.ts +12 -1
- package/src/cloudflare/static-site-router.ts +124 -82
- package/src/cloudflare/static-site.ts +66 -69
- package/src/cloudflare/worker-metadata.ts +154 -0
- package/src/cloudflare/worker-migration.ts +145 -0
- package/src/cloudflare/worker.ts +557 -429
- package/src/destroy.ts +2 -2
- package/src/esbuild.ts +3 -0
- package/src/github/client.ts +115 -0
- package/src/github/index.ts +1 -0
- package/src/github/secret.ts +172 -0
- package/src/global.ts +0 -3
- package/src/index.ts +2 -1
- package/src/output.ts +24 -8
- package/src/print.ts +18 -0
- package/src/resource.ts +156 -115
- package/src/scope.ts +7 -12
- 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:
|
|
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
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
54
|
-
const cache = caches.default;
|
|
55
|
-
const r = await cache.match(request);
|
|
104
|
+
return new Response("Page Not Found", { status: 404 });
|
|
56
105
|
|
|
57
|
-
|
|
58
|
-
|
|
106
|
+
async function lookupCache() {
|
|
107
|
+
const cache = caches.default;
|
|
108
|
+
const r = await cache.match(request.url);
|
|
59
109
|
|
|
60
|
-
|
|
61
|
-
|
|
110
|
+
// cache does not exist
|
|
111
|
+
if (!r) return;
|
|
62
112
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
113
|
+
// cache exists but etag does not match
|
|
114
|
+
if (r.headers.get("etag") !== __ASSET_MANIFEST__[filePath]) return;
|
|
66
115
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
116
|
+
// cache exists
|
|
117
|
+
return r;
|
|
118
|
+
}
|
|
71
119
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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(
|
|
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:
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
|
|
315
|
-
if
|
|
316
|
-
|
|
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:
|
|
336
|
-
|
|
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
|
-
|
|
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
|
+
}
|