alchemy 0.1.18 → 0.2.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.
Files changed (330) hide show
  1. package/README.md +506 -0
  2. package/lib/alchemy.d.ts +67 -0
  3. package/lib/alchemy.js +48 -0
  4. package/lib/apply.d.ts +3 -20
  5. package/lib/apply.js +95 -82
  6. package/lib/aws/account-id.d.ts +0 -1
  7. package/lib/aws/account-id.js +0 -1
  8. package/lib/aws/bucket.d.ts +4 -7
  9. package/lib/aws/bucket.js +8 -12
  10. package/lib/aws/function.d.ts +4 -7
  11. package/lib/aws/function.js +9 -30
  12. package/lib/aws/index.d.ts +1 -1
  13. package/lib/aws/index.js +1 -1
  14. package/lib/aws/oidc/github-oidc-provider.d.ts +2 -6
  15. package/lib/aws/oidc/github-oidc-provider.js +10 -15
  16. package/lib/aws/oidc/index.d.ts +0 -1
  17. package/lib/aws/oidc/index.js +0 -1
  18. package/lib/aws/oidc/oidc-provider.d.ts +4 -6
  19. package/lib/aws/oidc/oidc-provider.js +9 -11
  20. package/lib/aws/policy-attachment.d.ts +9 -0
  21. package/lib/aws/policy-attachment.js +20 -0
  22. package/lib/aws/policy.d.ts +4 -16
  23. package/lib/aws/policy.js +9 -40
  24. package/lib/aws/queue.d.ts +4 -34
  25. package/lib/aws/queue.js +10 -20
  26. package/lib/aws/role.d.ts +4 -7
  27. package/lib/aws/role.js +17 -26
  28. package/lib/aws/ses.d.ts +4 -10
  29. package/lib/aws/ses.js +118 -131
  30. package/lib/aws/table.d.ts +4 -7
  31. package/lib/aws/table.js +8 -11
  32. package/lib/cloudflare/api.d.ts +0 -1
  33. package/lib/cloudflare/api.js +0 -1
  34. package/lib/cloudflare/asset-manifest.d.ts +0 -1
  35. package/lib/cloudflare/asset-manifest.js +0 -1
  36. package/lib/cloudflare/auth.d.ts +0 -1
  37. package/lib/cloudflare/auth.js +0 -1
  38. package/lib/cloudflare/bindings.d.ts +1 -1
  39. package/lib/cloudflare/bindings.js +3 -2
  40. package/lib/cloudflare/bound.d.ts +0 -1
  41. package/lib/cloudflare/bound.js +0 -1
  42. package/lib/cloudflare/bucket.d.ts +7 -15
  43. package/lib/cloudflare/bucket.js +12 -19
  44. package/lib/cloudflare/durable-object-namespace.d.ts +0 -3
  45. package/lib/cloudflare/durable-object-namespace.js +0 -4
  46. package/lib/cloudflare/generate-asset-manifest.d.ts +0 -1
  47. package/lib/cloudflare/generate-asset-manifest.js +1 -2
  48. package/lib/cloudflare/index.d.ts +2 -1
  49. package/lib/cloudflare/index.js +2 -1
  50. package/lib/cloudflare/kv-namespace.d.ts +6 -9
  51. package/lib/cloudflare/kv-namespace.js +16 -20
  52. package/lib/cloudflare/state.d.ts +0 -1
  53. package/lib/cloudflare/state.js +0 -1
  54. package/lib/cloudflare/static-site-router.d.ts +0 -1
  55. package/lib/cloudflare/static-site-router.js +0 -4
  56. package/lib/cloudflare/static-site.d.ts +5 -11
  57. package/lib/cloudflare/static-site.js +25 -37
  58. package/lib/cloudflare/types.d.ts +0 -1
  59. package/lib/cloudflare/types.js +0 -1
  60. package/lib/cloudflare/upload-asset-manifest.d.ts +0 -1
  61. package/lib/cloudflare/upload-asset-manifest.js +0 -1
  62. package/lib/cloudflare/worker-metadata.d.ts +0 -1
  63. package/lib/cloudflare/worker-metadata.js +0 -1
  64. package/lib/cloudflare/worker-migration.d.ts +0 -1
  65. package/lib/cloudflare/worker-migration.js +0 -1
  66. package/lib/cloudflare/worker.d.ts +8 -14
  67. package/lib/cloudflare/worker.js +38 -50
  68. package/lib/cloudflare/wrangler.json.d.ts +243 -0
  69. package/lib/cloudflare/wrangler.json.js +35 -0
  70. package/lib/cloudflare/zone-settings.d.ts +301 -0
  71. package/lib/cloudflare/zone-settings.js +1 -0
  72. package/lib/cloudflare/zone.d.ts +196 -0
  73. package/lib/cloudflare/zone.js +175 -0
  74. package/lib/context.d.ts +58 -0
  75. package/lib/context.js +36 -0
  76. package/lib/destroy.d.ts +10 -13
  77. package/lib/destroy.js +104 -43
  78. package/lib/{esbuild.d.ts → esbuild/bundle.d.ts} +4 -18
  79. package/lib/{esbuild.js → esbuild/bundle.js} +10 -24
  80. package/lib/esbuild/index.d.ts +1 -0
  81. package/lib/esbuild/index.js +1 -0
  82. package/lib/fs/file.d.ts +13 -0
  83. package/lib/fs/file.js +20 -0
  84. package/lib/fs/folder.d.ts +10 -0
  85. package/lib/fs/folder.js +16 -0
  86. package/lib/fs/index.d.ts +2 -0
  87. package/lib/fs/index.js +2 -0
  88. package/lib/github/client.d.ts +0 -1
  89. package/lib/github/client.js +0 -1
  90. package/lib/github/index.d.ts +0 -1
  91. package/lib/github/index.js +0 -1
  92. package/lib/github/secret.d.ts +4 -6
  93. package/lib/github/secret.js +10 -12
  94. package/lib/index.d.ts +6 -10
  95. package/lib/index.js +5 -9
  96. package/lib/project/index.d.ts +1 -0
  97. package/lib/project/index.js +1 -0
  98. package/lib/project/vite.d.ts +39 -0
  99. package/lib/project/vite.js +68 -0
  100. package/lib/resource.d.ts +34 -62
  101. package/lib/resource.js +29 -270
  102. package/lib/scope.d.ts +37 -14
  103. package/lib/scope.js +97 -23
  104. package/lib/secret.d.ts +2 -7
  105. package/lib/secret.js +7 -20
  106. package/lib/state.d.ts +14 -10
  107. package/lib/state.js +20 -14
  108. package/lib/stripe/index.d.ts +0 -1
  109. package/lib/stripe/index.js +0 -1
  110. package/lib/stripe/price.d.ts +4 -5
  111. package/lib/stripe/price.js +10 -20
  112. package/lib/stripe/product.d.ts +4 -5
  113. package/lib/stripe/product.js +10 -20
  114. package/lib/stripe/webhook.d.ts +4 -6
  115. package/lib/stripe/webhook.js +12 -25
  116. package/lib/test/bun.d.ts +19 -0
  117. package/lib/test/bun.js +55 -0
  118. package/lib/{utils → util}/content-type.d.ts +0 -1
  119. package/lib/{utils → util}/content-type.js +0 -1
  120. package/lib/{encrypt.d.ts → util/encrypt.d.ts} +0 -1
  121. package/lib/{encrypt.js → util/encrypt.js} +0 -1
  122. package/lib/{error.d.ts → util/ignore.d.ts} +0 -1
  123. package/lib/{error.js → util/ignore.js} +0 -1
  124. package/lib/{utils → util}/retry.d.ts +0 -1
  125. package/lib/{utils → util}/retry.js +0 -1
  126. package/lib/util/rm.d.ts +1 -0
  127. package/lib/util/rm.js +11 -0
  128. package/lib/util/serde.d.ts +3 -0
  129. package/lib/{serde.js → util/serde.js} +19 -10
  130. package/lib/util/slugify.d.ts +1 -0
  131. package/lib/util/slugify.js +3 -0
  132. package/package.json +7 -5
  133. package/src/alchemy.ts +127 -0
  134. package/src/apply.ts +116 -115
  135. package/src/aws/bucket.ts +11 -14
  136. package/src/aws/function.ts +13 -33
  137. package/src/aws/index.ts +1 -0
  138. package/src/aws/oidc/github-oidc-provider.ts +14 -19
  139. package/src/aws/oidc/oidc-provider.ts +19 -12
  140. package/src/aws/policy-attachment.ts +51 -0
  141. package/src/aws/policy.ts +15 -60
  142. package/src/aws/queue.ts +17 -21
  143. package/src/aws/role.ts +25 -28
  144. package/src/aws/ses.ts +150 -164
  145. package/src/aws/table.ts +15 -15
  146. package/src/cloudflare/bindings.ts +8 -0
  147. package/src/cloudflare/bucket.ts +39 -47
  148. package/src/cloudflare/durable-object-namespace.ts +0 -10
  149. package/src/cloudflare/generate-asset-manifest.ts +1 -1
  150. package/src/cloudflare/index.ts +2 -0
  151. package/src/cloudflare/kv-namespace.ts +35 -33
  152. package/src/cloudflare/static-site-router.ts +0 -3
  153. package/src/cloudflare/static-site.ts +55 -71
  154. package/src/cloudflare/worker.ts +106 -112
  155. package/src/cloudflare/wrangler.json.ts +309 -0
  156. package/src/cloudflare/zone-settings.ts +368 -0
  157. package/src/cloudflare/zone.ts +491 -0
  158. package/src/context.ts +122 -0
  159. package/src/destroy.ts +124 -73
  160. package/src/{esbuild.ts → esbuild/bundle.ts} +16 -28
  161. package/src/esbuild/index.ts +1 -0
  162. package/src/fs/file.ts +39 -0
  163. package/src/fs/folder.ts +32 -0
  164. package/src/fs/index.ts +2 -0
  165. package/src/github/secret.ts +19 -16
  166. package/src/index.ts +7 -15
  167. package/src/project/index.ts +1 -0
  168. package/src/project/vite.ts +152 -0
  169. package/src/resource.ts +101 -462
  170. package/src/scope.ts +125 -36
  171. package/src/secret.ts +9 -32
  172. package/src/state.ts +38 -21
  173. package/src/stripe/price.ts +17 -22
  174. package/src/stripe/product.ts +17 -22
  175. package/src/stripe/webhook.ts +21 -27
  176. package/src/test/bun.ts +105 -0
  177. package/src/util/rm.ts +11 -0
  178. package/src/util/serde.ts +53 -0
  179. package/src/util/slugify.ts +3 -0
  180. package/lib/$.d.ts +0 -12
  181. package/lib/$.d.ts.map +0 -1
  182. package/lib/$.js +0 -42
  183. package/lib/$.js.map +0 -1
  184. package/lib/alchemize.d.ts +0 -47
  185. package/lib/alchemize.d.ts.map +0 -1
  186. package/lib/alchemize.js +0 -116
  187. package/lib/alchemize.js.map +0 -1
  188. package/lib/apply.d.ts.map +0 -1
  189. package/lib/apply.js.map +0 -1
  190. package/lib/aws/account-id.d.ts.map +0 -1
  191. package/lib/aws/account-id.js.map +0 -1
  192. package/lib/aws/bucket.d.ts.map +0 -1
  193. package/lib/aws/bucket.js.map +0 -1
  194. package/lib/aws/function.d.ts.map +0 -1
  195. package/lib/aws/function.js.map +0 -1
  196. package/lib/aws/index.d.ts.map +0 -1
  197. package/lib/aws/index.js.map +0 -1
  198. package/lib/aws/oidc/github-oidc-provider.d.ts.map +0 -1
  199. package/lib/aws/oidc/github-oidc-provider.js.map +0 -1
  200. package/lib/aws/oidc/index.d.ts.map +0 -1
  201. package/lib/aws/oidc/index.js.map +0 -1
  202. package/lib/aws/oidc/oidc-provider.d.ts.map +0 -1
  203. package/lib/aws/oidc/oidc-provider.js.map +0 -1
  204. package/lib/aws/policy.d.ts.map +0 -1
  205. package/lib/aws/policy.js.map +0 -1
  206. package/lib/aws/queue.d.ts.map +0 -1
  207. package/lib/aws/queue.js.map +0 -1
  208. package/lib/aws/role.d.ts.map +0 -1
  209. package/lib/aws/role.js.map +0 -1
  210. package/lib/aws/ses.d.ts.map +0 -1
  211. package/lib/aws/ses.js.map +0 -1
  212. package/lib/aws/table.d.ts.map +0 -1
  213. package/lib/aws/table.js.map +0 -1
  214. package/lib/cloudflare/api.d.ts.map +0 -1
  215. package/lib/cloudflare/api.js.map +0 -1
  216. package/lib/cloudflare/asset-manifest.d.ts.map +0 -1
  217. package/lib/cloudflare/asset-manifest.js.map +0 -1
  218. package/lib/cloudflare/auth.d.ts.map +0 -1
  219. package/lib/cloudflare/auth.js.map +0 -1
  220. package/lib/cloudflare/bindings.d.ts.map +0 -1
  221. package/lib/cloudflare/bindings.js.map +0 -1
  222. package/lib/cloudflare/bound.d.ts.map +0 -1
  223. package/lib/cloudflare/bound.js.map +0 -1
  224. package/lib/cloudflare/bucket.d.ts.map +0 -1
  225. package/lib/cloudflare/bucket.js.map +0 -1
  226. package/lib/cloudflare/durable-object-namespace.d.ts.map +0 -1
  227. package/lib/cloudflare/durable-object-namespace.js.map +0 -1
  228. package/lib/cloudflare/generate-asset-manifest.d.ts.map +0 -1
  229. package/lib/cloudflare/generate-asset-manifest.js.map +0 -1
  230. package/lib/cloudflare/index.d.ts.map +0 -1
  231. package/lib/cloudflare/index.js.map +0 -1
  232. package/lib/cloudflare/kv-namespace.d.ts.map +0 -1
  233. package/lib/cloudflare/kv-namespace.js.map +0 -1
  234. package/lib/cloudflare/state.d.ts.map +0 -1
  235. package/lib/cloudflare/state.js.map +0 -1
  236. package/lib/cloudflare/static-site-router.d.ts.map +0 -1
  237. package/lib/cloudflare/static-site-router.js.map +0 -1
  238. package/lib/cloudflare/static-site.d.ts.map +0 -1
  239. package/lib/cloudflare/static-site.js.map +0 -1
  240. package/lib/cloudflare/types.d.ts.map +0 -1
  241. package/lib/cloudflare/types.js.map +0 -1
  242. package/lib/cloudflare/upload-asset-manifest.d.ts.map +0 -1
  243. package/lib/cloudflare/upload-asset-manifest.js.map +0 -1
  244. package/lib/cloudflare/worker-metadata.d.ts.map +0 -1
  245. package/lib/cloudflare/worker-metadata.js.map +0 -1
  246. package/lib/cloudflare/worker-migration.d.ts.map +0 -1
  247. package/lib/cloudflare/worker-migration.js.map +0 -1
  248. package/lib/cloudflare/worker.d.ts.map +0 -1
  249. package/lib/cloudflare/worker.js.map +0 -1
  250. package/lib/destroy.d.ts.map +0 -1
  251. package/lib/destroy.js.map +0 -1
  252. package/lib/encrypt.d.ts.map +0 -1
  253. package/lib/encrypt.js.map +0 -1
  254. package/lib/error.d.ts.map +0 -1
  255. package/lib/error.js.map +0 -1
  256. package/lib/esbuild.d.ts.map +0 -1
  257. package/lib/esbuild.js.map +0 -1
  258. package/lib/fs.d.ts +0 -12
  259. package/lib/fs.d.ts.map +0 -1
  260. package/lib/fs.js +0 -41
  261. package/lib/fs.js.map +0 -1
  262. package/lib/github/client.d.ts.map +0 -1
  263. package/lib/github/client.js.map +0 -1
  264. package/lib/github/index.d.ts.map +0 -1
  265. package/lib/github/index.js.map +0 -1
  266. package/lib/github/secret.d.ts.map +0 -1
  267. package/lib/github/secret.js.map +0 -1
  268. package/lib/global.d.ts +0 -16
  269. package/lib/global.d.ts.map +0 -1
  270. package/lib/global.js +0 -42
  271. package/lib/global.js.map +0 -1
  272. package/lib/index.d.ts.map +0 -1
  273. package/lib/index.js.map +0 -1
  274. package/lib/input.d.ts +0 -7
  275. package/lib/input.d.ts.map +0 -1
  276. package/lib/input.js +0 -2
  277. package/lib/input.js.map +0 -1
  278. package/lib/main.d.ts +0 -3
  279. package/lib/main.d.ts.map +0 -1
  280. package/lib/main.js +0 -32
  281. package/lib/main.js.map +0 -1
  282. package/lib/output.d.ts +0 -25
  283. package/lib/output.d.ts.map +0 -1
  284. package/lib/output.js +0 -23
  285. package/lib/output.js.map +0 -1
  286. package/lib/print.d.ts +0 -7
  287. package/lib/print.d.ts.map +0 -1
  288. package/lib/print.js +0 -10
  289. package/lib/print.js.map +0 -1
  290. package/lib/resource.d.ts.map +0 -1
  291. package/lib/resource.js.map +0 -1
  292. package/lib/scope.d.ts.map +0 -1
  293. package/lib/scope.js.map +0 -1
  294. package/lib/secret.d.ts.map +0 -1
  295. package/lib/secret.js.map +0 -1
  296. package/lib/serde.d.ts +0 -3
  297. package/lib/serde.d.ts.map +0 -1
  298. package/lib/serde.js.map +0 -1
  299. package/lib/slug.d.ts +0 -2
  300. package/lib/slug.d.ts.map +0 -1
  301. package/lib/slug.js +0 -4
  302. package/lib/slug.js.map +0 -1
  303. package/lib/state.d.ts.map +0 -1
  304. package/lib/state.js.map +0 -1
  305. package/lib/stripe/index.d.ts.map +0 -1
  306. package/lib/stripe/index.js.map +0 -1
  307. package/lib/stripe/price.d.ts.map +0 -1
  308. package/lib/stripe/price.js.map +0 -1
  309. package/lib/stripe/product.d.ts.map +0 -1
  310. package/lib/stripe/product.js.map +0 -1
  311. package/lib/stripe/webhook.d.ts.map +0 -1
  312. package/lib/stripe/webhook.js.map +0 -1
  313. package/lib/utils/content-type.d.ts.map +0 -1
  314. package/lib/utils/content-type.js.map +0 -1
  315. package/lib/utils/retry.d.ts.map +0 -1
  316. package/lib/utils/retry.js.map +0 -1
  317. package/src/$.ts +0 -69
  318. package/src/alchemize.ts +0 -195
  319. package/src/fs.ts +0 -47
  320. package/src/global.ts +0 -63
  321. package/src/input.ts +0 -19
  322. package/src/main.ts +0 -34
  323. package/src/output.ts +0 -75
  324. package/src/print.ts +0 -18
  325. package/src/serde.ts +0 -46
  326. package/src/slug.ts +0 -3
  327. /package/src/{utils → util}/content-type.ts +0 -0
  328. /package/src/{encrypt.ts → util/encrypt.ts} +0 -0
  329. /package/src/{error.ts → util/ignore.ts} +0 -0
  330. /package/src/{utils → util}/retry.ts +0 -0
@@ -1,8 +1,14 @@
1
- import type { Resolved } from "../output";
2
- import { type Context, Resource } from "../resource";
3
- import { withExponentialBackoff } from "../utils/retry";
1
+ import type { Context } from "../context";
2
+ import { Resource } from "../resource";
3
+ import { withExponentialBackoff } from "../util/retry";
4
4
  import { createCloudflareApi } from "./api";
5
5
 
6
+ export function isKVNamespace(resource: any): resource is KVNamespace {
7
+ return (
8
+ resource && typeof resource === "object" && resource.type === "kv_namespace"
9
+ );
10
+ }
11
+
6
12
  /**
7
13
  * Properties for creating or updating a KV Namespace
8
14
  */
@@ -52,12 +58,14 @@ export interface KVPair {
52
58
  /**
53
59
  * Output returned after KV Namespace creation/update
54
60
  */
55
- export interface KVNamespaceOutput extends KVNamespaceProps {
61
+ export interface KVNamespace
62
+ extends Resource<"cloudflare::KVNamespace">,
63
+ KVNamespaceProps {
56
64
  type: "kv_namespace";
57
65
  /**
58
66
  * The ID of the namespace
59
67
  */
60
- id: string;
68
+ namespaceId: string;
61
69
 
62
70
  /**
63
71
  * Time at which the namespace was created
@@ -70,23 +78,19 @@ export interface KVNamespaceOutput extends KVNamespaceProps {
70
78
  modifiedAt: number;
71
79
  }
72
80
 
73
- export function isKVNamespace(
74
- resource: any,
75
- ): resource is Resolved<KVNamespace> {
76
- return (
77
- resource && typeof resource === "object" && resource.type === "kv_namespace"
78
- );
79
- }
80
-
81
- export class KVNamespace extends Resource(
81
+ export const KVNamespace = Resource(
82
82
  "cloudflare::KVNamespace",
83
- async (ctx: Context<KVNamespaceOutput>, props: KVNamespaceProps) => {
83
+ async function (
84
+ this: Context<KVNamespace>,
85
+ id: string,
86
+ props: KVNamespaceProps,
87
+ ) {
84
88
  // Create Cloudflare API client with automatic account discovery
85
89
  const api = await createCloudflareApi();
86
90
 
87
- if (ctx.event === "delete") {
91
+ if (this.phase === "delete") {
88
92
  // For delete operations, we need to check if the namespace ID exists in the output
89
- const namespaceId = ctx.output?.id;
93
+ const namespaceId = this.output?.namespaceId;
90
94
  if (namespaceId) {
91
95
  // Delete KV namespace
92
96
  const deleteResponse = await api.delete(
@@ -104,19 +108,22 @@ export class KVNamespace extends Resource(
104
108
  }
105
109
 
106
110
  // Return minimal output for deleted state
107
- return;
111
+ return this.destroy();
108
112
  } else {
109
113
  // For create or update operations
110
- // If ctx.event is "update", we expect ctx.output to exist
111
- let namespaceId = ctx.event === "update" ? ctx.output?.id || "" : "";
114
+ // If this.phase is "update", we expect this.output to exist
115
+ let namespaceId =
116
+ this.phase === "update" ? this.output?.namespaceId || "" : "";
112
117
  let createdAt =
113
- ctx.event === "update"
114
- ? ctx.output?.createdAt || Date.now()
118
+ this.phase === "update"
119
+ ? this.output?.createdAt || Date.now()
115
120
  : Date.now();
116
121
 
117
- if (ctx.event === "update" && namespaceId) {
122
+ if (this.phase === "update" && namespaceId) {
118
123
  // Can't update a KV namespace title directly, just work with existing ID
119
124
  } else {
125
+ // TODO: if it already exists, then check the tags to see if we own it and continue
126
+
120
127
  // Create new KV namespace
121
128
  const createResponse = await api.post(
122
129
  `/accounts/${api.accountId}/storage/kv/namespaces`,
@@ -207,19 +214,14 @@ export class KVNamespace extends Resource(
207
214
  }
208
215
  }
209
216
 
210
- const now = Date.now();
211
-
212
- // Construct the output
213
- const output: KVNamespaceOutput = {
217
+ return this({
214
218
  type: "kv_namespace",
215
- id: namespaceId,
219
+ namespaceId: namespaceId,
216
220
  title: props.title,
217
221
  values: props.values,
218
222
  createdAt: createdAt,
219
- modifiedAt: now,
220
- };
221
-
222
- return output;
223
+ modifiedAt: Date.now(),
224
+ });
223
225
  }
224
226
  },
225
- ) {}
227
+ );
@@ -34,14 +34,12 @@ export default {
34
34
  isInit = true;
35
35
  for (const [key, value] of Object.entries(env)) {
36
36
  if (key.startsWith("ROUTE_")) {
37
- console.log(key, value);
38
37
  const service = value as Service;
39
38
  const patternKey = `__${key}`;
40
39
  if (!(patternKey in env)) {
41
40
  throw new Error(`Missing pattern key: ${patternKey}`);
42
41
  }
43
42
  const pattern = (env as any)[`__${key}`];
44
- console.log("pattern", pattern);
45
43
  // TODO(sam): we should support narrowing down METHOD
46
44
  app.all(pattern, (ctx) => service.fetch(ctx.req.raw));
47
45
  }
@@ -53,7 +51,6 @@ export default {
53
51
 
54
52
  // fall back to assuming the request is a static file
55
53
  app.notFound(async (ctx) => {
56
- console.log("not found");
57
54
  const request = ctx.req;
58
55
  const env = ctx.env;
59
56
  const url = new URL(request.url);
@@ -2,10 +2,9 @@ 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
- import type { BundleProps } from "../esbuild";
7
- import type { Input } from "../input";
8
- import { type Context, Resource } from "../resource";
5
+ import type { Context } from "../context";
6
+ import type { BundleProps } from "../esbuild/bundle";
7
+ import { Resource } from "../resource";
9
8
  import { createCloudflareApi } from "./api";
10
9
  import type { Bindings } from "./bindings";
11
10
  import { generateAssetManifest } from "./generate-asset-manifest";
@@ -131,12 +130,7 @@ export interface StaticSiteProps {
131
130
  /**
132
131
  * Output returned after StaticSite creation/update
133
132
  */
134
- export interface StaticSiteOutput {
135
- /**
136
- * The ID of the site
137
- */
138
- id: string;
139
-
133
+ export interface StaticSite extends Resource<"cloudflare::StaticSite"> {
140
134
  /**
141
135
  * The ID of the worker
142
136
  */
@@ -208,16 +202,20 @@ export interface StaticSiteOutput {
208
202
  routes?: Record<string, string>;
209
203
  }
210
204
 
211
- export class StaticSite extends Resource(
205
+ export const StaticSite = Resource(
212
206
  "cloudflare::StaticSite",
213
207
  {
214
208
  alwaysUpdate: true,
215
209
  },
216
- async (ctx: Context<StaticSiteOutput>, props: StaticSiteProps) => {
217
- if (ctx.event === "delete") {
210
+ async function (
211
+ this: Context<StaticSite>,
212
+ id: string,
213
+ props: StaticSiteProps,
214
+ ) {
215
+ if (this.phase === "delete") {
218
216
  // For delete operations, we'll rely on the Worker delete to clean up
219
217
  // Return empty output for deleted state
220
- return;
218
+ return this.destroy();
221
219
  }
222
220
 
223
221
  // Validate that a name is provided
@@ -232,21 +230,10 @@ export class StaticSite extends Resource(
232
230
  throw new Error("Directory is required for StaticSite");
233
231
  }
234
232
 
235
- try {
236
- const dirStat = await fs.stat(props.dir);
237
- if (!dirStat.isDirectory()) {
238
- throw new Error(`"${props.dir}" is not a directory`);
239
- }
240
- } catch (error: any) {
241
- throw new Error(
242
- `Directory "${props.dir}" does not exist: ${error.message}`,
243
- );
244
- }
245
-
246
233
  // Run build command if provided
247
234
  if (props.build?.command) {
248
235
  try {
249
- if (!ctx.quiet) {
236
+ if (!this.quiet) {
250
237
  console.log(props.build.command);
251
238
  }
252
239
  const execAsync = promisify(exec);
@@ -254,7 +241,7 @@ export class StaticSite extends Resource(
254
241
  cwd: process.cwd(),
255
242
  });
256
243
 
257
- if (stdout && !ctx.quiet) console.log(stdout);
244
+ if (stdout && !this.quiet) console.log(stdout);
258
245
  } catch (error: any) {
259
246
  // Log detailed error information
260
247
  console.error(`Build command failed with exit code ${error.code}`);
@@ -268,6 +255,17 @@ export class StaticSite extends Resource(
268
255
  }
269
256
  }
270
257
 
258
+ try {
259
+ const dirStat = await fs.stat(props.dir);
260
+ if (!dirStat.isDirectory()) {
261
+ throw new Error(`"${props.dir}" is not a directory`);
262
+ }
263
+ } catch (error: any) {
264
+ throw new Error(
265
+ `Directory "${props.dir}" does not exist: ${error.message}`,
266
+ );
267
+ }
268
+
271
269
  // Use the provided name
272
270
  const siteName = props.name;
273
271
  const indexPage = props.indexPage || "index.html";
@@ -276,22 +274,18 @@ export class StaticSite extends Resource(
276
274
  const api = await createCloudflareApi();
277
275
 
278
276
  // Step 1: Create or get the KV namespace for assets
279
- const kv = new KVNamespace("assets", {
280
- title: `${siteName}-assets`,
281
- });
282
-
283
- const [{ id: kvNamespaceId }, assetManifest] = await Promise.all([
284
- apply(kv, {
285
- quiet: ctx.quiet,
277
+ const [kv, assetManifest] = await Promise.all([
278
+ KVNamespace("assets", {
279
+ title: `${siteName}-assets`,
286
280
  }),
287
281
  generateAssetManifest(props.dir),
288
282
  ]);
289
283
 
290
284
  // Step 3: Upload assets to KV
291
- await uploadAssetManifest(api, kvNamespaceId, assetManifest);
285
+ await uploadAssetManifest(api, kv.namespaceId, assetManifest);
292
286
 
293
287
  // Prepare the bindings for the worker
294
- const bindings: Input<Bindings> = {
288
+ const bindings: Bindings = {
295
289
  ASSETS: kv,
296
290
  INDEX_PAGE: indexPage,
297
291
  // Add error page binding if specified
@@ -335,39 +329,31 @@ export class StaticSite extends Resource(
335
329
  // TypeScript file doesn't exist, use JavaScript (default)
336
330
  }
337
331
 
338
- const worker = new Worker(
339
- "worker",
340
- {
341
- name: siteName,
342
- url: true,
343
- format: props.format || "esm",
344
- // If a custom worker script is provided, use it, otherwise use the entrypoint from router
345
- ...(props.workerScript
346
- ? { script: props.workerScript }
347
- : {
348
- entrypoint: path.resolve(__dirname, entrypointFile),
349
- bundle: bundleOptions,
350
- }),
351
- bindings,
352
- env: {
353
- ...Object.fromEntries(
354
- Object.entries(routes).map(([key, value]) => [
355
- `__ROUTE_${value}`,
356
- key,
357
- ]),
358
- ),
359
- },
332
+ const worker = await Worker("worker", {
333
+ name: siteName,
334
+ url: true,
335
+ format: props.format || "esm",
336
+ // If a custom worker script is provided, use it, otherwise use the entrypoint from router
337
+ ...(props.workerScript
338
+ ? { script: props.workerScript }
339
+ : {
340
+ entrypoint: path.resolve(__dirname, entrypointFile),
341
+ bundle: bundleOptions as any,
342
+ }),
343
+ bindings,
344
+ env: {
345
+ ...Object.fromEntries(
346
+ Object.entries(routes).map(([key, value]) => [
347
+ `__ROUTE_${value}`,
348
+ key,
349
+ ]),
350
+ ),
360
351
  },
361
- // place a dependency on the namespace
362
- kv.id,
363
- );
352
+ });
364
353
 
365
- // Get current timestamp
366
354
  const now = Date.now();
367
355
 
368
- // Construct the output
369
- const output: Input<StaticSiteOutput> = {
370
- id: siteName,
356
+ return this({
371
357
  workerId: worker.id,
372
358
  name: siteName,
373
359
  directory: props.dir,
@@ -375,14 +361,12 @@ export class StaticSite extends Resource(
375
361
  errorPage: props.errorPage,
376
362
  indexPage,
377
363
  assets: assetManifest.map((item) => item.key),
378
- createdAt: ctx.output?.createdAt || now,
364
+ createdAt: this.output?.createdAt || now,
379
365
  updatedAt: now,
380
366
  domain: props.domain,
381
367
  production: props.production !== false,
382
- url: worker.url as Input<string | undefined>,
368
+ url: worker.url,
383
369
  routes,
384
- };
385
-
386
- return output;
370
+ });
387
371
  },
388
- ) {}
372
+ );