alchemy 0.1.17 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/alchemy.d.ts +67 -0
- package/lib/alchemy.js +40 -0
- package/lib/apply.d.ts +3 -20
- package/lib/apply.js +86 -78
- package/lib/aws/account-id.d.ts +0 -1
- package/lib/aws/account-id.js +0 -1
- package/lib/aws/bucket.d.ts +4 -7
- package/lib/aws/bucket.js +8 -12
- package/lib/aws/function.d.ts +4 -7
- package/lib/aws/function.js +9 -30
- package/lib/aws/index.d.ts +1 -1
- package/lib/aws/index.js +1 -1
- package/lib/aws/oidc/github-oidc-provider.d.ts +2 -6
- package/lib/aws/oidc/github-oidc-provider.js +10 -15
- package/lib/aws/oidc/index.d.ts +0 -1
- package/lib/aws/oidc/index.js +0 -1
- package/lib/aws/oidc/oidc-provider.d.ts +4 -6
- package/lib/aws/oidc/oidc-provider.js +9 -11
- package/lib/aws/policy-attachment.d.ts +9 -0
- package/lib/aws/policy-attachment.js +20 -0
- package/lib/aws/policy.d.ts +4 -16
- package/lib/aws/policy.js +9 -40
- package/lib/aws/queue.d.ts +4 -34
- package/lib/aws/queue.js +10 -20
- package/lib/aws/role.d.ts +4 -7
- package/lib/aws/role.js +17 -26
- package/lib/aws/ses.d.ts +4 -10
- package/lib/aws/ses.js +118 -131
- package/lib/aws/table.d.ts +4 -7
- package/lib/aws/table.js +8 -11
- package/lib/cloudflare/api.d.ts +0 -1
- package/lib/cloudflare/api.js +0 -1
- package/lib/cloudflare/asset-manifest.d.ts +0 -1
- package/lib/cloudflare/asset-manifest.js +0 -1
- package/lib/cloudflare/auth.d.ts +0 -1
- package/lib/cloudflare/auth.js +0 -1
- package/lib/cloudflare/bindings.d.ts +4 -3
- package/lib/cloudflare/bindings.js +3 -2
- package/lib/cloudflare/bound.d.ts +7 -0
- package/lib/cloudflare/bound.js +1 -0
- package/lib/cloudflare/bucket.d.ts +7 -15
- package/lib/cloudflare/bucket.js +12 -19
- package/lib/cloudflare/durable-object-namespace.d.ts +0 -3
- package/lib/cloudflare/durable-object-namespace.js +0 -4
- package/lib/cloudflare/generate-asset-manifest.d.ts +0 -1
- package/lib/cloudflare/generate-asset-manifest.js +1 -2
- package/lib/cloudflare/index.d.ts +0 -1
- package/lib/cloudflare/index.js +0 -1
- package/lib/cloudflare/kv-namespace.d.ts +6 -9
- package/lib/cloudflare/kv-namespace.js +16 -20
- package/lib/cloudflare/state.d.ts +0 -1
- package/lib/cloudflare/state.js +0 -1
- package/lib/cloudflare/static-site-router.d.ts +0 -1
- package/lib/cloudflare/static-site-router.js +0 -4
- package/lib/cloudflare/static-site.d.ts +5 -11
- package/lib/cloudflare/static-site.js +16 -28
- package/lib/cloudflare/types.d.ts +0 -1
- package/lib/cloudflare/types.js +0 -1
- package/lib/cloudflare/upload-asset-manifest.d.ts +0 -1
- package/lib/cloudflare/upload-asset-manifest.js +0 -1
- package/lib/cloudflare/worker-metadata.d.ts +0 -1
- package/lib/cloudflare/worker-metadata.js +0 -1
- package/lib/cloudflare/worker-migration.d.ts +0 -1
- package/lib/cloudflare/worker-migration.js +0 -1
- package/lib/cloudflare/worker.d.ts +13 -13
- package/lib/cloudflare/worker.js +43 -43
- package/lib/context.d.ts +58 -0
- package/lib/context.js +36 -0
- package/lib/destroy.d.ts +10 -13
- package/lib/destroy.js +104 -43
- package/lib/{esbuild.d.ts → esbuild/bundle.d.ts} +4 -18
- package/lib/{esbuild.js → esbuild/bundle.js} +10 -24
- package/lib/esbuild/index.d.ts +1 -0
- package/lib/esbuild/index.js +1 -0
- package/lib/fs/file.d.ts +13 -0
- package/lib/fs/file.js +20 -0
- package/lib/fs/folder.d.ts +10 -0
- package/lib/fs/folder.js +16 -0
- package/lib/fs/index.d.ts +2 -0
- package/lib/fs/index.js +2 -0
- package/lib/github/client.d.ts +0 -1
- package/lib/github/client.js +0 -1
- package/lib/github/index.d.ts +0 -1
- package/lib/github/index.js +0 -1
- package/lib/github/secret.d.ts +6 -7
- package/lib/github/secret.js +30 -36
- package/lib/index.d.ts +7 -10
- package/lib/index.js +6 -9
- package/lib/resource.d.ts +34 -62
- package/lib/resource.js +29 -270
- package/lib/scope.d.ts +35 -14
- package/lib/scope.js +78 -23
- package/lib/secret.d.ts +7 -0
- package/lib/secret.js +17 -0
- package/lib/state.d.ts +14 -10
- package/lib/state.js +15 -13
- package/lib/stripe/index.d.ts +0 -1
- package/lib/stripe/index.js +0 -1
- package/lib/stripe/price.d.ts +4 -5
- package/lib/stripe/price.js +10 -20
- package/lib/stripe/product.d.ts +4 -5
- package/lib/stripe/product.js +10 -20
- package/lib/stripe/webhook.d.ts +4 -6
- package/lib/stripe/webhook.js +12 -25
- package/lib/test/bun.d.ts +19 -0
- package/lib/test/bun.js +55 -0
- package/lib/{utils → util}/content-type.d.ts +0 -1
- package/lib/{utils → util}/content-type.js +0 -1
- package/lib/util/encrypt.d.ts +16 -0
- package/lib/util/encrypt.js +44 -0
- package/lib/{error.d.ts → util/ignore.d.ts} +0 -1
- package/lib/{error.js → util/ignore.js} +0 -1
- package/lib/{utils → util}/retry.d.ts +0 -1
- package/lib/{utils → util}/retry.js +0 -1
- package/lib/util/serde.d.ts +3 -0
- package/lib/util/serde.js +46 -0
- package/lib/util/slugify.d.ts +1 -0
- package/lib/util/slugify.js +3 -0
- package/package.json +5 -7
- package/src/alchemy.ts +120 -0
- package/src/apply.ts +109 -111
- package/src/aws/bucket.ts +11 -14
- package/src/aws/function.ts +13 -33
- package/src/aws/index.ts +1 -0
- package/src/aws/oidc/github-oidc-provider.ts +14 -19
- package/src/aws/oidc/oidc-provider.ts +19 -12
- package/src/aws/policy-attachment.ts +51 -0
- package/src/aws/policy.ts +15 -60
- package/src/aws/queue.ts +17 -21
- package/src/aws/role.ts +25 -28
- package/src/aws/ses.ts +150 -164
- package/src/aws/table.ts +15 -15
- package/src/cloudflare/bindings.ts +12 -2
- package/src/cloudflare/bound.ts +18 -0
- package/src/cloudflare/bucket.ts +40 -48
- package/src/cloudflare/durable-object-namespace.ts +0 -10
- package/src/cloudflare/generate-asset-manifest.ts +1 -1
- package/src/cloudflare/kv-namespace.ts +35 -33
- package/src/cloudflare/static-site-router.ts +0 -3
- package/src/cloudflare/static-site.ts +43 -59
- package/src/cloudflare/worker.ts +76 -64
- package/src/context.ts +122 -0
- package/src/destroy.ts +124 -73
- package/src/{esbuild.ts → esbuild/bundle.ts} +16 -28
- package/src/esbuild/index.ts +1 -0
- package/src/fs/file.ts +39 -0
- package/src/fs/folder.ts +32 -0
- package/src/fs/index.ts +2 -0
- package/src/github/secret.ts +53 -49
- package/src/index.ts +8 -15
- package/src/resource.ts +101 -462
- package/src/scope.ts +101 -36
- package/src/secret.ts +18 -0
- package/src/state.ts +30 -20
- package/src/stripe/price.ts +17 -22
- package/src/stripe/product.ts +17 -22
- package/src/stripe/webhook.ts +21 -27
- package/src/test/bun.ts +105 -0
- package/src/util/encrypt.ts +79 -0
- package/src/util/serde.ts +53 -0
- package/src/util/slugify.ts +3 -0
- package/lib/$.d.ts +0 -12
- package/lib/$.d.ts.map +0 -1
- package/lib/$.js +0 -42
- package/lib/$.js.map +0 -1
- package/lib/alchemize.d.ts +0 -43
- package/lib/alchemize.d.ts.map +0 -1
- package/lib/alchemize.js +0 -112
- package/lib/alchemize.js.map +0 -1
- package/lib/apply.d.ts.map +0 -1
- package/lib/apply.js.map +0 -1
- package/lib/aws/account-id.d.ts.map +0 -1
- package/lib/aws/account-id.js.map +0 -1
- package/lib/aws/bucket.d.ts.map +0 -1
- package/lib/aws/bucket.js.map +0 -1
- package/lib/aws/function.d.ts.map +0 -1
- package/lib/aws/function.js.map +0 -1
- package/lib/aws/index.d.ts.map +0 -1
- package/lib/aws/index.js.map +0 -1
- package/lib/aws/oidc/github-oidc-provider.d.ts.map +0 -1
- package/lib/aws/oidc/github-oidc-provider.js.map +0 -1
- package/lib/aws/oidc/index.d.ts.map +0 -1
- package/lib/aws/oidc/index.js.map +0 -1
- package/lib/aws/oidc/oidc-provider.d.ts.map +0 -1
- package/lib/aws/oidc/oidc-provider.js.map +0 -1
- package/lib/aws/policy.d.ts.map +0 -1
- package/lib/aws/policy.js.map +0 -1
- package/lib/aws/queue.d.ts.map +0 -1
- package/lib/aws/queue.js.map +0 -1
- package/lib/aws/role.d.ts.map +0 -1
- package/lib/aws/role.js.map +0 -1
- package/lib/aws/ses.d.ts.map +0 -1
- package/lib/aws/ses.js.map +0 -1
- package/lib/aws/table.d.ts.map +0 -1
- package/lib/aws/table.js.map +0 -1
- package/lib/cloudflare/api.d.ts.map +0 -1
- package/lib/cloudflare/api.js.map +0 -1
- package/lib/cloudflare/asset-manifest.d.ts.map +0 -1
- package/lib/cloudflare/asset-manifest.js.map +0 -1
- package/lib/cloudflare/auth.d.ts.map +0 -1
- package/lib/cloudflare/auth.js.map +0 -1
- package/lib/cloudflare/bindings.d.ts.map +0 -1
- package/lib/cloudflare/bindings.js.map +0 -1
- package/lib/cloudflare/bucket.d.ts.map +0 -1
- package/lib/cloudflare/bucket.js.map +0 -1
- package/lib/cloudflare/durable-object-namespace.d.ts.map +0 -1
- package/lib/cloudflare/durable-object-namespace.js.map +0 -1
- package/lib/cloudflare/generate-asset-manifest.d.ts.map +0 -1
- package/lib/cloudflare/generate-asset-manifest.js.map +0 -1
- package/lib/cloudflare/index.d.ts.map +0 -1
- package/lib/cloudflare/index.js.map +0 -1
- package/lib/cloudflare/kv-namespace.d.ts.map +0 -1
- package/lib/cloudflare/kv-namespace.js.map +0 -1
- package/lib/cloudflare/state.d.ts.map +0 -1
- package/lib/cloudflare/state.js.map +0 -1
- package/lib/cloudflare/static-site-router.d.ts.map +0 -1
- package/lib/cloudflare/static-site-router.js.map +0 -1
- package/lib/cloudflare/static-site.d.ts.map +0 -1
- package/lib/cloudflare/static-site.js.map +0 -1
- package/lib/cloudflare/types.d.ts.map +0 -1
- package/lib/cloudflare/types.js.map +0 -1
- package/lib/cloudflare/upload-asset-manifest.d.ts.map +0 -1
- package/lib/cloudflare/upload-asset-manifest.js.map +0 -1
- package/lib/cloudflare/worker-metadata.d.ts.map +0 -1
- package/lib/cloudflare/worker-metadata.js.map +0 -1
- package/lib/cloudflare/worker-migration.d.ts.map +0 -1
- package/lib/cloudflare/worker-migration.js.map +0 -1
- package/lib/cloudflare/worker.d.ts.map +0 -1
- package/lib/cloudflare/worker.js.map +0 -1
- package/lib/destroy.d.ts.map +0 -1
- package/lib/destroy.js.map +0 -1
- package/lib/error.d.ts.map +0 -1
- package/lib/error.js.map +0 -1
- package/lib/esbuild.d.ts.map +0 -1
- package/lib/esbuild.js.map +0 -1
- package/lib/fs.d.ts +0 -12
- package/lib/fs.d.ts.map +0 -1
- package/lib/fs.js +0 -41
- package/lib/fs.js.map +0 -1
- package/lib/github/client.d.ts.map +0 -1
- package/lib/github/client.js.map +0 -1
- package/lib/github/index.d.ts.map +0 -1
- package/lib/github/index.js.map +0 -1
- package/lib/github/secret.d.ts.map +0 -1
- package/lib/github/secret.js.map +0 -1
- package/lib/global.d.ts +0 -16
- package/lib/global.d.ts.map +0 -1
- package/lib/global.js +0 -42
- package/lib/global.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/input.d.ts +0 -6
- package/lib/input.d.ts.map +0 -1
- package/lib/input.js +0 -2
- package/lib/input.js.map +0 -1
- package/lib/main.d.ts +0 -3
- package/lib/main.d.ts.map +0 -1
- package/lib/main.js +0 -32
- package/lib/main.js.map +0 -1
- package/lib/output.d.ts +0 -24
- package/lib/output.d.ts.map +0 -1
- package/lib/output.js +0 -23
- package/lib/output.js.map +0 -1
- package/lib/print.d.ts +0 -7
- package/lib/print.d.ts.map +0 -1
- package/lib/print.js +0 -10
- package/lib/print.js.map +0 -1
- package/lib/resource.d.ts.map +0 -1
- package/lib/resource.js.map +0 -1
- package/lib/scope.d.ts.map +0 -1
- package/lib/scope.js.map +0 -1
- package/lib/slug.d.ts +0 -2
- package/lib/slug.d.ts.map +0 -1
- package/lib/slug.js +0 -4
- package/lib/slug.js.map +0 -1
- package/lib/state.d.ts.map +0 -1
- package/lib/state.js.map +0 -1
- package/lib/stripe/index.d.ts.map +0 -1
- package/lib/stripe/index.js.map +0 -1
- package/lib/stripe/price.d.ts.map +0 -1
- package/lib/stripe/price.js.map +0 -1
- package/lib/stripe/product.d.ts.map +0 -1
- package/lib/stripe/product.js.map +0 -1
- package/lib/stripe/webhook.d.ts.map +0 -1
- package/lib/stripe/webhook.js.map +0 -1
- package/lib/utils/content-type.d.ts.map +0 -1
- package/lib/utils/content-type.js.map +0 -1
- package/lib/utils/retry.d.ts.map +0 -1
- package/lib/utils/retry.js.map +0 -1
- package/src/$.ts +0 -69
- package/src/alchemize.ts +0 -186
- package/src/fs.ts +0 -47
- package/src/global.ts +0 -63
- package/src/input.ts +0 -16
- package/src/main.ts +0 -34
- package/src/output.ts +0 -71
- package/src/print.ts +0 -18
- package/src/slug.ts +0 -3
- /package/src/{utils → util}/content-type.ts +0 -0
- /package/src/{error.ts → util/ignore.ts} +0 -0
- /package/src/{utils → util}/retry.ts +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Context } from "../context";
|
|
2
|
+
import { Resource } from "../resource";
|
|
3
|
+
export declare function isKVNamespace(resource: any): resource is KVNamespace;
|
|
2
4
|
/**
|
|
3
5
|
* Properties for creating or updating a KV Namespace
|
|
4
6
|
*/
|
|
@@ -41,12 +43,12 @@ export interface KVPair {
|
|
|
41
43
|
/**
|
|
42
44
|
* Output returned after KV Namespace creation/update
|
|
43
45
|
*/
|
|
44
|
-
export interface
|
|
46
|
+
export interface KVNamespace extends Resource<"cloudflare::KVNamespace">, KVNamespaceProps {
|
|
45
47
|
type: "kv_namespace";
|
|
46
48
|
/**
|
|
47
49
|
* The ID of the namespace
|
|
48
50
|
*/
|
|
49
|
-
|
|
51
|
+
namespaceId: string;
|
|
50
52
|
/**
|
|
51
53
|
* Time at which the namespace was created
|
|
52
54
|
*/
|
|
@@ -56,9 +58,4 @@ export interface KVNamespaceOutput extends KVNamespaceProps {
|
|
|
56
58
|
*/
|
|
57
59
|
modifiedAt: number;
|
|
58
60
|
}
|
|
59
|
-
export declare
|
|
60
|
-
declare const KVNamespace_base: import("../resource").Provider<"cloudflare::KVNamespace", [props: KVNamespaceProps], KVNamespaceOutput>;
|
|
61
|
-
export declare class KVNamespace extends KVNamespace_base {
|
|
62
|
-
}
|
|
63
|
-
export {};
|
|
64
|
-
//# sourceMappingURL=kv-namespace.d.ts.map
|
|
61
|
+
export declare const KVNamespace: ((this: Context<KVNamespace>, id: string, props: KVNamespaceProps) => Promise<KVNamespace>) | (((this: any, id: string, props: KVNamespaceProps) => never) & (new (_: never) => never));
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Resource } from "../resource";
|
|
2
|
-
import { withExponentialBackoff } from "../
|
|
2
|
+
import { withExponentialBackoff } from "../util/retry";
|
|
3
3
|
import { createCloudflareApi } from "./api";
|
|
4
4
|
export function isKVNamespace(resource) {
|
|
5
5
|
return (resource && typeof resource === "object" && resource.type === "kv_namespace");
|
|
6
6
|
}
|
|
7
|
-
export
|
|
7
|
+
export const KVNamespace = Resource("cloudflare::KVNamespace", async function (id, props) {
|
|
8
8
|
// Create Cloudflare API client with automatic account discovery
|
|
9
9
|
const api = await createCloudflareApi();
|
|
10
|
-
if (
|
|
10
|
+
if (this.phase === "delete") {
|
|
11
11
|
// For delete operations, we need to check if the namespace ID exists in the output
|
|
12
|
-
const namespaceId =
|
|
12
|
+
const namespaceId = this.output?.namespaceId;
|
|
13
13
|
if (namespaceId) {
|
|
14
14
|
// Delete KV namespace
|
|
15
15
|
const deleteResponse = await api.delete(`/accounts/${api.accountId}/storage/kv/namespaces/${namespaceId}`);
|
|
@@ -21,19 +21,20 @@ export class KVNamespace extends Resource("cloudflare::KVNamespace", async (ctx,
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
// Return minimal output for deleted state
|
|
24
|
-
return;
|
|
24
|
+
return this.destroy();
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
27
27
|
// For create or update operations
|
|
28
|
-
// If
|
|
29
|
-
let namespaceId =
|
|
30
|
-
let createdAt =
|
|
31
|
-
?
|
|
28
|
+
// If this.phase is "update", we expect this.output to exist
|
|
29
|
+
let namespaceId = this.phase === "update" ? this.output?.namespaceId || "" : "";
|
|
30
|
+
let createdAt = this.phase === "update"
|
|
31
|
+
? this.output?.createdAt || Date.now()
|
|
32
32
|
: Date.now();
|
|
33
|
-
if (
|
|
33
|
+
if (this.phase === "update" && namespaceId) {
|
|
34
34
|
// Can't update a KV namespace title directly, just work with existing ID
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
+
// TODO: if it already exists, then check the tags to see if we own it and continue
|
|
37
38
|
// Create new KV namespace
|
|
38
39
|
const createResponse = await api.post(`/accounts/${api.accountId}/storage/kv/namespaces`, {
|
|
39
40
|
title: props.title,
|
|
@@ -97,18 +98,13 @@ export class KVNamespace extends Resource("cloudflare::KVNamespace", async (ctx,
|
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
|
-
|
|
101
|
-
// Construct the output
|
|
102
|
-
const output = {
|
|
101
|
+
return this({
|
|
103
102
|
type: "kv_namespace",
|
|
104
|
-
|
|
103
|
+
namespaceId: namespaceId,
|
|
105
104
|
title: props.title,
|
|
106
105
|
values: props.values,
|
|
107
106
|
createdAt: createdAt,
|
|
108
|
-
modifiedAt: now,
|
|
109
|
-
};
|
|
110
|
-
return output;
|
|
107
|
+
modifiedAt: Date.now(),
|
|
108
|
+
});
|
|
111
109
|
}
|
|
112
|
-
})
|
|
113
|
-
}
|
|
114
|
-
//# sourceMappingURL=kv-namespace.js.map
|
|
110
|
+
});
|
package/lib/cloudflare/state.js
CHANGED
|
@@ -7,14 +7,12 @@ export default {
|
|
|
7
7
|
isInit = true;
|
|
8
8
|
for (const [key, value] of Object.entries(env)) {
|
|
9
9
|
if (key.startsWith("ROUTE_")) {
|
|
10
|
-
console.log(key, value);
|
|
11
10
|
const service = value;
|
|
12
11
|
const patternKey = `__${key}`;
|
|
13
12
|
if (!(patternKey in env)) {
|
|
14
13
|
throw new Error(`Missing pattern key: ${patternKey}`);
|
|
15
14
|
}
|
|
16
15
|
const pattern = env[`__${key}`];
|
|
17
|
-
console.log("pattern", pattern);
|
|
18
16
|
// TODO(sam): we should support narrowing down METHOD
|
|
19
17
|
app.all(pattern, (ctx) => service.fetch(ctx.req.raw));
|
|
20
18
|
}
|
|
@@ -25,7 +23,6 @@ export default {
|
|
|
25
23
|
};
|
|
26
24
|
// fall back to assuming the request is a static file
|
|
27
25
|
app.notFound(async (ctx) => {
|
|
28
|
-
console.log("not found");
|
|
29
26
|
const request = ctx.req;
|
|
30
27
|
const env = ctx.env;
|
|
31
28
|
const url = new URL(request.url);
|
|
@@ -107,4 +104,3 @@ app.notFound(async (ctx) => {
|
|
|
107
104
|
return response;
|
|
108
105
|
}
|
|
109
106
|
});
|
|
110
|
-
//# sourceMappingURL=static-site-router.js.map
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Context } from "../context";
|
|
2
|
+
import type { BundleProps } from "../esbuild/bundle";
|
|
3
|
+
import { Resource } from "../resource";
|
|
2
4
|
import { Worker } from "./worker";
|
|
3
5
|
/**
|
|
4
6
|
* Idea of using KV with timeout inspired by SST: https://github.com/sst/sst/blob/dev/platform/src/components/cloudflare/static-site.ts
|
|
@@ -98,11 +100,7 @@ export interface StaticSiteProps {
|
|
|
98
100
|
/**
|
|
99
101
|
* Output returned after StaticSite creation/update
|
|
100
102
|
*/
|
|
101
|
-
export interface
|
|
102
|
-
/**
|
|
103
|
-
* The ID of the site
|
|
104
|
-
*/
|
|
105
|
-
id: string;
|
|
103
|
+
export interface StaticSite extends Resource<"cloudflare::StaticSite"> {
|
|
106
104
|
/**
|
|
107
105
|
* The ID of the worker
|
|
108
106
|
*/
|
|
@@ -159,8 +157,4 @@ export interface StaticSiteOutput {
|
|
|
159
157
|
*/
|
|
160
158
|
routes?: Record<string, string>;
|
|
161
159
|
}
|
|
162
|
-
declare const
|
|
163
|
-
export declare class StaticSite extends StaticSite_base {
|
|
164
|
-
}
|
|
165
|
-
export {};
|
|
166
|
-
//# sourceMappingURL=static-site.d.ts.map
|
|
160
|
+
export declare const StaticSite: ((this: Context<StaticSite>, id: string, props: StaticSiteProps) => Promise<StaticSite>) | (((this: any, id: string, props: StaticSiteProps) => never) & (new (_: never) => never));
|
|
@@ -2,7 +2,6 @@ import { exec } from "child_process";
|
|
|
2
2
|
import { promises as fs } from "fs";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { promisify } from "util";
|
|
5
|
-
import { apply } from "../apply";
|
|
6
5
|
import { Resource } from "../resource";
|
|
7
6
|
import { createCloudflareApi } from "./api";
|
|
8
7
|
import { generateAssetManifest } from "./generate-asset-manifest";
|
|
@@ -10,13 +9,13 @@ import { KVNamespace } from "./kv-namespace";
|
|
|
10
9
|
import { uploadAssetManifest } from "./upload-asset-manifest";
|
|
11
10
|
import { Worker } from "./worker";
|
|
12
11
|
const __dirname = import.meta.dirname;
|
|
13
|
-
export
|
|
12
|
+
export const StaticSite = Resource("cloudflare::StaticSite", {
|
|
14
13
|
alwaysUpdate: true,
|
|
15
|
-
}, async (
|
|
16
|
-
if (
|
|
14
|
+
}, async function (id, props) {
|
|
15
|
+
if (this.phase === "delete") {
|
|
17
16
|
// For delete operations, we'll rely on the Worker delete to clean up
|
|
18
17
|
// Return empty output for deleted state
|
|
19
|
-
return;
|
|
18
|
+
return this.destroy();
|
|
20
19
|
}
|
|
21
20
|
// Validate that a name is provided
|
|
22
21
|
if (!props.name) {
|
|
@@ -38,14 +37,14 @@ export class StaticSite extends Resource("cloudflare::StaticSite", {
|
|
|
38
37
|
// Run build command if provided
|
|
39
38
|
if (props.build?.command) {
|
|
40
39
|
try {
|
|
41
|
-
if (!
|
|
40
|
+
if (!this.quiet) {
|
|
42
41
|
console.log(props.build.command);
|
|
43
42
|
}
|
|
44
43
|
const execAsync = promisify(exec);
|
|
45
44
|
const { stdout, stderr } = await execAsync(props.build.command, {
|
|
46
45
|
cwd: process.cwd(),
|
|
47
46
|
});
|
|
48
|
-
if (stdout && !
|
|
47
|
+
if (stdout && !this.quiet)
|
|
49
48
|
console.log(stdout);
|
|
50
49
|
}
|
|
51
50
|
catch (error) {
|
|
@@ -65,17 +64,14 @@ export class StaticSite extends Resource("cloudflare::StaticSite", {
|
|
|
65
64
|
// Create Cloudflare API client with automatic account discovery
|
|
66
65
|
const api = await createCloudflareApi();
|
|
67
66
|
// Step 1: Create or get the KV namespace for assets
|
|
68
|
-
const kv =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const [{ id: kvNamespaceId }, assetManifest] = await Promise.all([
|
|
72
|
-
apply(kv, {
|
|
73
|
-
quiet: ctx.quiet,
|
|
67
|
+
const [kv, assetManifest] = await Promise.all([
|
|
68
|
+
KVNamespace("assets", {
|
|
69
|
+
title: `${siteName}-assets`,
|
|
74
70
|
}),
|
|
75
71
|
generateAssetManifest(props.dir),
|
|
76
72
|
]);
|
|
77
73
|
// Step 3: Upload assets to KV
|
|
78
|
-
await uploadAssetManifest(api,
|
|
74
|
+
await uploadAssetManifest(api, kv.namespaceId, assetManifest);
|
|
79
75
|
// Prepare the bindings for the worker
|
|
80
76
|
const bindings = {
|
|
81
77
|
ASSETS: kv,
|
|
@@ -115,7 +111,7 @@ export class StaticSite extends Resource("cloudflare::StaticSite", {
|
|
|
115
111
|
catch (error) {
|
|
116
112
|
// TypeScript file doesn't exist, use JavaScript (default)
|
|
117
113
|
}
|
|
118
|
-
const worker =
|
|
114
|
+
const worker = await Worker("worker", {
|
|
119
115
|
name: siteName,
|
|
120
116
|
url: true,
|
|
121
117
|
format: props.format || "esm",
|
|
@@ -133,14 +129,9 @@ export class StaticSite extends Resource("cloudflare::StaticSite", {
|
|
|
133
129
|
key,
|
|
134
130
|
])),
|
|
135
131
|
},
|
|
136
|
-
}
|
|
137
|
-
// place a dependency on the namespace
|
|
138
|
-
kv.id);
|
|
139
|
-
// Get current timestamp
|
|
132
|
+
});
|
|
140
133
|
const now = Date.now();
|
|
141
|
-
|
|
142
|
-
const output = {
|
|
143
|
-
id: siteName,
|
|
134
|
+
return this({
|
|
144
135
|
workerId: worker.id,
|
|
145
136
|
name: siteName,
|
|
146
137
|
directory: props.dir,
|
|
@@ -148,14 +139,11 @@ export class StaticSite extends Resource("cloudflare::StaticSite", {
|
|
|
148
139
|
errorPage: props.errorPage,
|
|
149
140
|
indexPage,
|
|
150
141
|
assets: assetManifest.map((item) => item.key),
|
|
151
|
-
createdAt:
|
|
142
|
+
createdAt: this.output?.createdAt || now,
|
|
152
143
|
updatedAt: now,
|
|
153
144
|
domain: props.domain,
|
|
154
145
|
production: props.production !== false,
|
|
155
146
|
url: worker.url,
|
|
156
147
|
routes,
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
}) {
|
|
160
|
-
}
|
|
161
|
-
//# sourceMappingURL=static-site.js.map
|
|
148
|
+
});
|
|
149
|
+
});
|
package/lib/cloudflare/types.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
3
|
-
import
|
|
1
|
+
import type { Context } from "../context";
|
|
2
|
+
import { type BundleProps } from "../esbuild/bundle";
|
|
3
|
+
import { Resource } from "../resource";
|
|
4
|
+
import { type Bindings } from "./bindings";
|
|
5
|
+
import type { Bound } from "./bound";
|
|
4
6
|
import type { SingleStepMigration } from "./worker-migration";
|
|
5
7
|
/**
|
|
6
8
|
* Properties for creating or updating a Worker
|
|
7
9
|
*/
|
|
8
|
-
export interface WorkerProps {
|
|
10
|
+
export interface WorkerProps<B extends Bindings = Bindings> {
|
|
9
11
|
/**
|
|
10
12
|
* The worker script content (JavaScript or WASM)
|
|
11
13
|
* One of script, entryPoint, or bundle must be provided
|
|
@@ -42,7 +44,7 @@ export interface WorkerProps {
|
|
|
42
44
|
/**
|
|
43
45
|
* Bindings to attach to the worker
|
|
44
46
|
*/
|
|
45
|
-
bindings?:
|
|
47
|
+
bindings?: B;
|
|
46
48
|
/**
|
|
47
49
|
* Environment variables to attach to the worker
|
|
48
50
|
* These will be converted to plain_text bindings
|
|
@@ -76,7 +78,7 @@ export interface WorkerProps {
|
|
|
76
78
|
/**
|
|
77
79
|
* Output returned after Worker creation/update
|
|
78
80
|
*/
|
|
79
|
-
export interface
|
|
81
|
+
export interface Worker<B extends Bindings = Bindings> extends Resource<"cloudflare::Worker">, Omit<WorkerProps<B>, "url"> {
|
|
80
82
|
type: "service";
|
|
81
83
|
/**
|
|
82
84
|
* The ID of the worker
|
|
@@ -98,11 +100,9 @@ export interface WorkerOutput extends Omit<WorkerProps, "url"> {
|
|
|
98
100
|
/**
|
|
99
101
|
* The bindings that were created
|
|
100
102
|
*/
|
|
101
|
-
bindings:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
export declare class Worker extends Worker_base {
|
|
103
|
+
bindings: B | undefined;
|
|
104
|
+
Env: {
|
|
105
|
+
[bindingName in keyof B]: Bound<B[bindingName]>;
|
|
106
|
+
};
|
|
106
107
|
}
|
|
107
|
-
export
|
|
108
|
-
//# sourceMappingURL=worker.d.ts.map
|
|
108
|
+
export declare const Worker: (<const B extends Bindings>(this: Context<Worker<NoInfer<B>>>, id: string, props: WorkerProps<B>) => Promise<Worker<B>>) | (((this: any, id: string, props: WorkerProps<Bindings>) => never) & (new (_: never) => never));
|
package/lib/cloudflare/worker.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import * as fs from "fs/promises";
|
|
2
|
-
import {
|
|
3
|
-
import { Bundle } from "../esbuild";
|
|
2
|
+
import { Bundle } from "../esbuild/bundle";
|
|
4
3
|
import { Resource } from "../resource";
|
|
5
|
-
import {
|
|
4
|
+
import { isSecret } from "../secret";
|
|
5
|
+
import { withExponentialBackoff } from "../util/retry";
|
|
6
|
+
import { slugify } from "../util/slugify";
|
|
6
7
|
import { createCloudflareApi } from "./api";
|
|
7
|
-
import {
|
|
8
|
-
import { isDurableObjectNamespace } from "./durable-object-namespace";
|
|
8
|
+
import { isDurableObjectNamespace, } from "./bindings";
|
|
9
9
|
import { isKVNamespace } from "./kv-namespace";
|
|
10
|
-
export
|
|
11
|
-
return resource && typeof resource === "object" && resource.type === "worker";
|
|
12
|
-
}
|
|
13
|
-
export class Worker extends Resource("cloudflare::Worker", {
|
|
10
|
+
export const Worker = Resource("cloudflare::Worker", {
|
|
14
11
|
alwaysUpdate: true,
|
|
15
|
-
}, async (
|
|
12
|
+
}, async function (id, props) {
|
|
16
13
|
// Create Cloudflare API client with automatic account discovery
|
|
17
14
|
const api = await createCloudflareApi();
|
|
18
15
|
// Use the provided name
|
|
@@ -21,30 +18,31 @@ export class Worker extends Resource("cloudflare::Worker", {
|
|
|
21
18
|
if (!props.script && !props.entrypoint) {
|
|
22
19
|
throw new Error("One of script or entryPoint must be provided");
|
|
23
20
|
}
|
|
24
|
-
if (
|
|
25
|
-
|
|
21
|
+
if (this.phase === "delete") {
|
|
22
|
+
await deleteWorker(this, api, workerName);
|
|
23
|
+
return this.destroy();
|
|
26
24
|
}
|
|
27
|
-
else if (
|
|
28
|
-
await assertWorkerDoesNotExist(
|
|
25
|
+
else if (this.phase === "create") {
|
|
26
|
+
await assertWorkerDoesNotExist(this, api, workerName);
|
|
29
27
|
}
|
|
30
|
-
const oldBindings = await
|
|
31
|
-
const scriptMetadata = await prepareWorkerMetadata(
|
|
28
|
+
const oldBindings = await this.get("bindings");
|
|
29
|
+
const scriptMetadata = await prepareWorkerMetadata(this, oldBindings, props);
|
|
32
30
|
// Get the script content - either from props.script, or by bundling
|
|
33
|
-
const scriptContent = props.script ?? (await bundleWorkerScript(
|
|
31
|
+
const scriptContent = props.script ?? (await bundleWorkerScript(props));
|
|
34
32
|
// Upload the worker script
|
|
35
|
-
await putWorker(
|
|
33
|
+
await putWorker(api, workerName, scriptContent, scriptMetadata);
|
|
36
34
|
// TODO: it is less than ideal that this can fail, resulting in state problem
|
|
37
|
-
await
|
|
35
|
+
await this.set("bindings", props.bindings);
|
|
38
36
|
// Handle routes if requested
|
|
39
37
|
await setupRoutes(api, workerName, props.routes || []);
|
|
40
38
|
// Handle worker URL if requested
|
|
41
|
-
const workerUrl = await configureURL(
|
|
39
|
+
const workerUrl = await configureURL(this, api, workerName, props.url ?? false);
|
|
42
40
|
// Get current timestamp
|
|
43
41
|
const now = Date.now();
|
|
44
42
|
// Construct the output
|
|
45
|
-
|
|
43
|
+
return this({
|
|
46
44
|
type: "service",
|
|
47
|
-
id
|
|
45
|
+
id,
|
|
48
46
|
name: workerName,
|
|
49
47
|
script: scriptContent,
|
|
50
48
|
format: props.format || "esm", // Include format in the output
|
|
@@ -55,10 +53,10 @@ export class Worker extends Resource("cloudflare::Worker", {
|
|
|
55
53
|
createdAt: now,
|
|
56
54
|
updatedAt: now,
|
|
57
55
|
url: workerUrl,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
})
|
|
61
|
-
}
|
|
56
|
+
// phantom property
|
|
57
|
+
Env: undefined,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
62
60
|
async function deleteWorker(ctx, api, workerName) {
|
|
63
61
|
// Delete worker
|
|
64
62
|
const deleteResponse = await api.delete(`/accounts/${api.accountId}/workers/scripts/${workerName}`);
|
|
@@ -102,7 +100,7 @@ async function deleteWorker(ctx, api, workerName) {
|
|
|
102
100
|
// Return minimal output for deleted state
|
|
103
101
|
return;
|
|
104
102
|
}
|
|
105
|
-
async function putWorker(
|
|
103
|
+
async function putWorker(api, workerName, scriptContent, scriptMetadata) {
|
|
106
104
|
return withExponentialBackoff(async () => {
|
|
107
105
|
const scriptName = scriptMetadata.main_module ?? scriptMetadata.body_part;
|
|
108
106
|
// Create FormData for the upload
|
|
@@ -113,7 +111,6 @@ async function putWorker(ctx, api, workerName, scriptContent, scriptMetadata) {
|
|
|
113
111
|
? "application/javascript+module"
|
|
114
112
|
: "application/javascript",
|
|
115
113
|
}), scriptName);
|
|
116
|
-
// console.log("Script Metadata:", JSON.stringify(scriptMetadata, null, 2));
|
|
117
114
|
// Add metadata as JSON
|
|
118
115
|
formData.append("metadata", new Blob([JSON.stringify(scriptMetadata)], {
|
|
119
116
|
type: "application/json",
|
|
@@ -153,7 +150,8 @@ async function prepareWorkerMetadata(ctx, oldBindings, props) {
|
|
|
153
150
|
observability: {
|
|
154
151
|
enabled: props.observability?.enabled !== false,
|
|
155
152
|
},
|
|
156
|
-
|
|
153
|
+
// TODO(sam): base64 encode instead? 0 collision risk vs readability.
|
|
154
|
+
tags: [`alchemy:id:${slugify(ctx.fqn)}`],
|
|
157
155
|
migrations: {
|
|
158
156
|
new_classes: props.migrations?.new_classes ?? [],
|
|
159
157
|
deleted_classes: props.migrations?.deleted_classes ?? [],
|
|
@@ -170,7 +168,7 @@ async function prepareWorkerMetadata(ctx, oldBindings, props) {
|
|
|
170
168
|
meta.bindings.push({
|
|
171
169
|
type: "kv_namespace",
|
|
172
170
|
name: bindingName,
|
|
173
|
-
namespace_id: binding.
|
|
171
|
+
namespace_id: binding.namespaceId,
|
|
174
172
|
});
|
|
175
173
|
}
|
|
176
174
|
else if (typeof binding === "string") {
|
|
@@ -187,7 +185,7 @@ async function prepareWorkerMetadata(ctx, oldBindings, props) {
|
|
|
187
185
|
service: binding.id,
|
|
188
186
|
});
|
|
189
187
|
}
|
|
190
|
-
else if (
|
|
188
|
+
else if (binding.type === "durable_object_namespace") {
|
|
191
189
|
const stableId = binding.id;
|
|
192
190
|
const className = binding.className;
|
|
193
191
|
meta.bindings.push({
|
|
@@ -216,11 +214,18 @@ async function prepareWorkerMetadata(ctx, oldBindings, props) {
|
|
|
216
214
|
});
|
|
217
215
|
}
|
|
218
216
|
}
|
|
219
|
-
else if (
|
|
217
|
+
else if (binding.type === "r2_bucket") {
|
|
220
218
|
meta.bindings.push({
|
|
221
219
|
type: "r2_bucket",
|
|
222
220
|
name: bindingName,
|
|
223
|
-
bucket_name: binding.name
|
|
221
|
+
bucket_name: binding.name,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
else if (isSecret(binding)) {
|
|
225
|
+
meta.bindings.push({
|
|
226
|
+
type: "secret_text",
|
|
227
|
+
name: bindingName,
|
|
228
|
+
text: binding.unencrypted,
|
|
224
229
|
});
|
|
225
230
|
}
|
|
226
231
|
else {
|
|
@@ -261,7 +266,7 @@ async function assertWorkerDoesNotExist(ctx, api, workerName) {
|
|
|
261
266
|
if (!metadata) {
|
|
262
267
|
throw new Error(`Worker exists but failed to fetch metadata: ${response.status} ${response.statusText}`);
|
|
263
268
|
}
|
|
264
|
-
if (metadata.default_environment?.script.tags.includes(`alchemy:id:${ctx.
|
|
269
|
+
if (metadata.default_environment?.script.tags.includes(`alchemy:id:${slugify(ctx.fqn)}`)) {
|
|
265
270
|
return true;
|
|
266
271
|
}
|
|
267
272
|
throw new Error(`Worker with name '${workerName}' already exists. Please use a unique name.`);
|
|
@@ -270,7 +275,7 @@ async function assertWorkerDoesNotExist(ctx, api, workerName) {
|
|
|
270
275
|
throw new Error(`Error checking if worker exists: ${response.status} ${response.statusText}`);
|
|
271
276
|
}
|
|
272
277
|
}
|
|
273
|
-
async function bundleWorkerScript(
|
|
278
|
+
async function bundleWorkerScript(props) {
|
|
274
279
|
// Get the script content - either from props.script, or by bundling
|
|
275
280
|
// Create and use a Bundle resource with worker-optimized configuration
|
|
276
281
|
const defaultBundleOptions = {
|
|
@@ -288,17 +293,13 @@ async function bundleWorkerScript(ctx, props) {
|
|
|
288
293
|
...(props.bundle || {}),
|
|
289
294
|
};
|
|
290
295
|
// Create the bundle
|
|
291
|
-
const bundle =
|
|
296
|
+
const bundle = await Bundle("bundle", {
|
|
292
297
|
entryPoint: props.entrypoint,
|
|
293
298
|
...bundleOptions,
|
|
294
299
|
external: [...(bundleOptions.external ?? []), "cloudflare:workers"],
|
|
295
300
|
});
|
|
296
|
-
// Get the bundled content
|
|
297
|
-
const bundleOutput = await apply(bundle, {
|
|
298
|
-
quiet: ctx.quiet,
|
|
299
|
-
});
|
|
300
301
|
try {
|
|
301
|
-
return await fs.readFile(
|
|
302
|
+
return await fs.readFile(bundle.path, "utf-8");
|
|
302
303
|
}
|
|
303
304
|
catch (error) {
|
|
304
305
|
console.error("Error reading bundle:", error);
|
|
@@ -362,7 +363,7 @@ async function configureURL(ctx, api, workerName, url) {
|
|
|
362
363
|
// Add a delay when the subdomain is first created.
|
|
363
364
|
// This is to prevent an issue where a negative cache-hit
|
|
364
365
|
// causes the subdomain to be unavailable for 30 seconds.
|
|
365
|
-
if (ctx.
|
|
366
|
+
if (ctx.phase === "create" || !ctx.output?.url) {
|
|
366
367
|
await new Promise((resolve) => setTimeout(resolve, 3000));
|
|
367
368
|
}
|
|
368
369
|
}
|
|
@@ -404,4 +405,3 @@ async function getWorkerBindings(api, workerName, environment = "production") {
|
|
|
404
405
|
const data = await response.json();
|
|
405
406
|
return data.result;
|
|
406
407
|
}
|
|
407
|
-
//# sourceMappingURL=worker.js.map
|
package/lib/context.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Resource, ResourceFQN, ResourceID, ResourceKind, ResourceProps } from "./resource";
|
|
2
|
+
import type { Scope } from "./scope";
|
|
3
|
+
import type { State } from "./state";
|
|
4
|
+
export type Context<Out extends Resource> = CreateContext<Out> | UpdateContext<Out> | DeleteContext<Out>;
|
|
5
|
+
export interface CreateContext<Out extends Resource> extends BaseContext<Out> {
|
|
6
|
+
phase: "create";
|
|
7
|
+
output?: undefined;
|
|
8
|
+
}
|
|
9
|
+
export interface UpdateContext<Out extends Resource> extends BaseContext<Out> {
|
|
10
|
+
phase: "update";
|
|
11
|
+
output: Out;
|
|
12
|
+
}
|
|
13
|
+
export interface DeleteContext<Out extends Resource> extends BaseContext<Out> {
|
|
14
|
+
phase: "delete";
|
|
15
|
+
output: Out;
|
|
16
|
+
}
|
|
17
|
+
export interface BaseContext<Out extends Resource> {
|
|
18
|
+
quiet: boolean;
|
|
19
|
+
stage: string;
|
|
20
|
+
id: ResourceID;
|
|
21
|
+
fqn: ResourceFQN;
|
|
22
|
+
scope: Scope;
|
|
23
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
24
|
+
set<T>(key: string, value: T): Promise<void>;
|
|
25
|
+
delete<T>(key: string): Promise<T | undefined>;
|
|
26
|
+
/**
|
|
27
|
+
* Indicate that this resource is being replaced.
|
|
28
|
+
* This will cause the resource to be deleted at the end of the stack's CREATE phase.
|
|
29
|
+
*/
|
|
30
|
+
replace(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Terminate the resource lifecycle handler and destroy the resource.
|
|
33
|
+
*
|
|
34
|
+
* This is the final operation performed during a delete operation.
|
|
35
|
+
*
|
|
36
|
+
* It is so that the resource lifecycle handler can "return never" instead of
|
|
37
|
+
* "return undefined" so that `await MyResource()` always returns a value.
|
|
38
|
+
*/
|
|
39
|
+
destroy(): never;
|
|
40
|
+
/**
|
|
41
|
+
* Create the Resource envelope (with Alchemy + User properties)
|
|
42
|
+
*/
|
|
43
|
+
create(props: Omit<Out, keyof Resource>): Out;
|
|
44
|
+
/**
|
|
45
|
+
* Create the Resource envelope (with Alchemy + User properties)
|
|
46
|
+
*/
|
|
47
|
+
(props: Omit<Out, keyof Resource>): Out;
|
|
48
|
+
}
|
|
49
|
+
export declare function context<Kind extends string, Props extends ResourceProps, Out extends Resource>({ scope, phase, kind, id, fqn, seq, state, replace, }: {
|
|
50
|
+
scope: Scope;
|
|
51
|
+
phase: "create" | "update" | "delete";
|
|
52
|
+
kind: ResourceKind;
|
|
53
|
+
id: ResourceID;
|
|
54
|
+
fqn: ResourceFQN;
|
|
55
|
+
seq: number;
|
|
56
|
+
state: State<Kind, Props, Out>;
|
|
57
|
+
replace: () => void;
|
|
58
|
+
}): Context<Out>;
|