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
package/src/aws/ses.ts CHANGED
@@ -19,8 +19,9 @@ import {
19
19
  type SuppressionOptions,
20
20
  type TrackingOptions,
21
21
  } from "@aws-sdk/client-sesv2";
22
- import { ignore } from "../error";
23
- import { type Context, Resource } from "../resource";
22
+ import type { Context } from "../context";
23
+ import { Resource } from "../resource";
24
+ import { ignore } from "../util/ignore";
24
25
 
25
26
  /**
26
27
  * Properties for configuring AWS SES resources
@@ -75,12 +76,7 @@ export interface SESProps {
75
76
  /**
76
77
  * Output returned after SES resource creation/update
77
78
  */
78
- export interface SESOutput extends SESProps {
79
- /**
80
- * Resource ID
81
- */
82
- id: string;
83
-
79
+ export interface SES extends Resource<"aws::SES">, SESProps {
84
80
  /**
85
81
  * ARN of the configuration set if created
86
82
  */
@@ -105,19 +101,23 @@ export interface SESOutput extends SESProps {
105
101
  /**
106
102
  * AWS SES resource for creating and configuring Simple Email Service
107
103
  */
108
- export class SES extends Resource(
104
+ export const SES = Resource(
109
105
  "aws::SES",
110
- async (ctx: Context<SESOutput>, props: SESProps) => {
106
+ async function (
107
+ this: Context<SES>,
108
+ id: string,
109
+ props: SESProps,
110
+ ): Promise<SES> {
111
111
  // Create SES client
112
112
  const client = new SESv2Client({});
113
113
 
114
114
  // Resource ID is either based on the configuration set name or email identity
115
- const id =
116
- props.configurationSetName || props.emailIdentity || ctx.resourceID;
115
+ // const id =
116
+ // props.configurationSetName || props.emailIdentity || this.resourceID;
117
117
 
118
118
  // Handle deletion
119
- if (ctx.event === "delete") {
120
- const output = ctx.output;
119
+ if (this.phase === "delete") {
120
+ const output = this.output;
121
121
 
122
122
  // Delete configuration set if it exists
123
123
  if (output?.configurationSetName) {
@@ -142,7 +142,7 @@ export class SES extends Resource(
142
142
  }
143
143
 
144
144
  // Return empty output for delete
145
- return;
145
+ return this.destroy();
146
146
  }
147
147
 
148
148
  // Created resources
@@ -153,190 +153,176 @@ export class SES extends Resource(
153
153
 
154
154
  // Create or update configuration set if specified
155
155
  if (props.configurationSetName) {
156
+ // Check if configuration set exists
157
+ let configSetExists = false;
156
158
  try {
157
- // Check if configuration set exists
158
- let configSetExists = false;
159
- try {
159
+ await client.send(
160
+ new GetConfigurationSetCommand({
161
+ ConfigurationSetName: props.configurationSetName,
162
+ }),
163
+ );
164
+ configSetExists = true;
165
+ } catch (error) {
166
+ if (error instanceof NotFoundException) {
167
+ configSetExists = false;
168
+ } else {
169
+ throw error;
170
+ }
171
+ }
172
+
173
+ if (configSetExists) {
174
+ // Update existing configuration set using appropriate update commands
175
+ if (props.sendingOptions) {
160
176
  await client.send(
161
- new GetConfigurationSetCommand({
177
+ new PutConfigurationSetSendingOptionsCommand({
162
178
  ConfigurationSetName: props.configurationSetName,
179
+ SendingEnabled: props.sendingOptions.SendingEnabled,
163
180
  }),
164
181
  );
165
- configSetExists = true;
166
- } catch (error) {
167
- if (error instanceof NotFoundException) {
168
- configSetExists = false;
169
- } else {
170
- throw error;
171
- }
172
182
  }
173
183
 
174
- if (configSetExists) {
175
- // Update existing configuration set using appropriate update commands
176
- if (props.sendingOptions) {
177
- await client.send(
178
- new PutConfigurationSetSendingOptionsCommand({
179
- ConfigurationSetName: props.configurationSetName,
180
- SendingEnabled: props.sendingOptions.SendingEnabled,
181
- }),
182
- );
183
- }
184
-
185
- if (props.reputationOptions) {
186
- await client.send(
187
- new PutConfigurationSetReputationOptionsCommand({
188
- ConfigurationSetName: props.configurationSetName,
189
- ReputationMetricsEnabled:
190
- props.reputationOptions.ReputationMetricsEnabled,
191
- }),
192
- );
193
- }
194
-
195
- if (props.trackingOptions) {
196
- await client.send(
197
- new PutConfigurationSetTrackingOptionsCommand({
198
- ConfigurationSetName: props.configurationSetName,
199
- CustomRedirectDomain:
200
- props.trackingOptions.CustomRedirectDomain,
201
- }),
202
- );
203
- }
204
-
205
- if (props.suppressionOptions) {
206
- await client.send(
207
- new PutConfigurationSetSuppressionOptionsCommand({
208
- ConfigurationSetName: props.configurationSetName,
209
- SuppressedReasons: props.suppressionOptions.SuppressedReasons,
210
- }),
211
- );
212
- }
184
+ if (props.reputationOptions) {
185
+ await client.send(
186
+ new PutConfigurationSetReputationOptionsCommand({
187
+ ConfigurationSetName: props.configurationSetName,
188
+ ReputationMetricsEnabled:
189
+ props.reputationOptions.ReputationMetricsEnabled,
190
+ }),
191
+ );
192
+ }
213
193
 
214
- if (props.deliveryOptions) {
215
- await client.send(
216
- new PutConfigurationSetDeliveryOptionsCommand({
217
- ConfigurationSetName: props.configurationSetName,
218
- TlsPolicy: props.deliveryOptions.TlsPolicy,
219
- SendingPoolName: props.deliveryOptions.SendingPoolName,
220
- }),
221
- );
222
- }
194
+ if (props.trackingOptions) {
195
+ await client.send(
196
+ new PutConfigurationSetTrackingOptionsCommand({
197
+ ConfigurationSetName: props.configurationSetName,
198
+ CustomRedirectDomain: props.trackingOptions.CustomRedirectDomain,
199
+ }),
200
+ );
201
+ }
223
202
 
224
- // In SESv2, the ARN isn't directly returned in the response
225
- configurationSetArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:configuration-set/${props.configurationSetName}`;
226
- } else {
227
- // Create new configuration set
203
+ if (props.suppressionOptions) {
228
204
  await client.send(
229
- new CreateConfigurationSetCommand({
205
+ new PutConfigurationSetSuppressionOptionsCommand({
230
206
  ConfigurationSetName: props.configurationSetName,
231
- SendingOptions: props.sendingOptions,
232
- ReputationOptions: props.reputationOptions,
233
- TrackingOptions: props.trackingOptions,
234
- SuppressionOptions: props.suppressionOptions,
235
- DeliveryOptions: props.deliveryOptions,
236
- Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
237
- Key,
238
- Value,
239
- })),
207
+ SuppressedReasons: props.suppressionOptions.SuppressedReasons,
240
208
  }),
241
209
  );
210
+ }
242
211
 
243
- // In SESv2, the ARN isn't directly returned in the response
244
- configurationSetArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:configuration-set/${props.configurationSetName}`;
212
+ if (props.deliveryOptions) {
213
+ await client.send(
214
+ new PutConfigurationSetDeliveryOptionsCommand({
215
+ ConfigurationSetName: props.configurationSetName,
216
+ TlsPolicy: props.deliveryOptions.TlsPolicy,
217
+ SendingPoolName: props.deliveryOptions.SendingPoolName,
218
+ }),
219
+ );
245
220
  }
246
- } catch (error: any) {
247
- throw error;
221
+
222
+ // In SESv2, the ARN isn't directly returned in the response
223
+ configurationSetArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:configuration-set/${props.configurationSetName}`;
224
+ } else {
225
+ // Create new configuration set
226
+ await client.send(
227
+ new CreateConfigurationSetCommand({
228
+ ConfigurationSetName: props.configurationSetName,
229
+ SendingOptions: props.sendingOptions,
230
+ ReputationOptions: props.reputationOptions,
231
+ TrackingOptions: props.trackingOptions,
232
+ SuppressionOptions: props.suppressionOptions,
233
+ DeliveryOptions: props.deliveryOptions,
234
+ Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
235
+ Key,
236
+ Value,
237
+ })),
238
+ }),
239
+ );
240
+
241
+ // In SESv2, the ARN isn't directly returned in the response
242
+ configurationSetArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:configuration-set/${props.configurationSetName}`;
248
243
  }
249
244
  }
250
245
 
251
246
  // Create or verify email identity if specified
252
247
  if (props.emailIdentity) {
248
+ // Check if identity exists
249
+ let getIdentityResult;
253
250
  try {
254
- // Check if identity exists
255
- let getIdentityResult;
256
- try {
257
- getIdentityResult = await client.send(
258
- new GetEmailIdentityCommand({
259
- EmailIdentity: props.emailIdentity,
260
- }),
261
- );
262
- } catch (error) {
263
- if (error instanceof NotFoundException) {
264
- getIdentityResult = null;
265
- } else {
266
- throw error;
267
- }
251
+ getIdentityResult = await client.send(
252
+ new GetEmailIdentityCommand({
253
+ EmailIdentity: props.emailIdentity,
254
+ }),
255
+ );
256
+ } catch (error) {
257
+ if (error instanceof NotFoundException) {
258
+ getIdentityResult = null;
259
+ } else {
260
+ throw error;
268
261
  }
262
+ }
269
263
 
270
- if (!getIdentityResult) {
271
- // Create new email identity
272
- const createIdentityResult = await client.send(
273
- new CreateEmailIdentityCommand({
274
- EmailIdentity: props.emailIdentity,
275
- Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
276
- Key,
277
- Value,
278
- })),
279
- }),
280
- );
264
+ if (!getIdentityResult) {
265
+ // Create new email identity
266
+ const createIdentityResult = await client.send(
267
+ new CreateEmailIdentityCommand({
268
+ EmailIdentity: props.emailIdentity,
269
+ Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
270
+ Key,
271
+ Value,
272
+ })),
273
+ }),
274
+ );
275
+
276
+ // If it's an email address, we don't need to explicitly verify in v2
277
+ // The verification email is automatically sent by SES in v2
278
+
279
+ // Store the identity information
280
+ emailIdentityArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:identity/${props.emailIdentity}`;
281
+ emailIdentityVerificationStatus =
282
+ createIdentityResult.VerifiedForSendingStatus
283
+ ? "VERIFIED"
284
+ : "PENDING";
285
+ } else {
286
+ // Store the identity information
287
+ emailIdentityArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:identity/${props.emailIdentity}`;
288
+ emailIdentityVerificationStatus =
289
+ getIdentityResult.VerifiedForSendingStatus ? "VERIFIED" : "PENDING";
290
+
291
+ // Update DKIM settings if requested
292
+ if (props.enableDkim !== undefined) {
293
+ if (props.enableDkim) {
294
+ await client.send(
295
+ new PutEmailIdentityDkimAttributesCommand({
296
+ EmailIdentity: props.emailIdentity,
297
+ SigningEnabled: true,
298
+ }),
299
+ );
281
300
 
282
- // If it's an email address, we don't need to explicitly verify in v2
283
- // The verification email is automatically sent by SES in v2
301
+ // We can check the current status of DKIM
302
+ dkimVerificationStatus = "PENDING"; // Default to pending
284
303
 
285
- // Store the identity information
286
- emailIdentityArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:identity/${props.emailIdentity}`;
287
- emailIdentityVerificationStatus =
288
- createIdentityResult.VerifiedForSendingStatus
289
- ? "VERIFIED"
290
- : "PENDING";
291
- } else {
292
- // Store the identity information
293
- emailIdentityArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:identity/${props.emailIdentity}`;
294
- emailIdentityVerificationStatus =
295
- getIdentityResult.VerifiedForSendingStatus ? "VERIFIED" : "PENDING";
296
-
297
- // Update DKIM settings if requested
298
- if (props.enableDkim !== undefined) {
299
- if (props.enableDkim) {
300
- await client.send(
301
- new PutEmailIdentityDkimAttributesCommand({
302
- EmailIdentity: props.emailIdentity,
303
- SigningEnabled: true,
304
- }),
305
- );
306
-
307
- // We can check the current status of DKIM
308
- dkimVerificationStatus = "PENDING"; // Default to pending
309
-
310
- // Get the updated identity to check DKIM status
311
- const updatedIdentity = await client.send(
312
- new GetEmailIdentityCommand({
313
- EmailIdentity: props.emailIdentity,
314
- }),
315
- );
316
-
317
- if (updatedIdentity.DkimAttributes?.Status) {
318
- dkimVerificationStatus = updatedIdentity.DkimAttributes.Status;
319
- }
304
+ // Get the updated identity to check DKIM status
305
+ const updatedIdentity = await client.send(
306
+ new GetEmailIdentityCommand({
307
+ EmailIdentity: props.emailIdentity,
308
+ }),
309
+ );
310
+
311
+ if (updatedIdentity.DkimAttributes?.Status) {
312
+ dkimVerificationStatus = updatedIdentity.DkimAttributes.Status;
320
313
  }
321
314
  }
322
315
  }
323
- } catch (error) {
324
- console.error(
325
- `Error configuring email identity ${props.emailIdentity}:`,
326
- error,
327
- );
328
- throw error;
329
316
  }
330
317
  }
331
318
 
332
319
  // Return the resource output
333
- return {
320
+ return this({
334
321
  ...props,
335
- id,
336
322
  configurationSetArn,
337
323
  emailIdentityArn,
338
324
  emailIdentityVerificationStatus,
339
325
  dkimVerificationStatus,
340
- };
326
+ });
341
327
  },
342
- ) {}
328
+ );
package/src/aws/table.ts CHANGED
@@ -8,9 +8,10 @@ import {
8
8
  ResourceInUseException,
9
9
  ResourceNotFoundException,
10
10
  } from "@aws-sdk/client-dynamodb";
11
- import { ignore } from "../error";
12
- import { type Context, Resource } from "../resource";
13
- import { withExponentialBackoff } from "../utils/retry";
11
+ import type { Context } from "../context";
12
+ import { Resource } from "../resource";
13
+ import { ignore } from "../util/ignore";
14
+ import { withExponentialBackoff } from "../util/retry";
14
15
 
15
16
  export interface TableProps {
16
17
  tableName: string;
@@ -28,22 +29,22 @@ export interface TableProps {
28
29
  tags?: Record<string, string>;
29
30
  }
30
31
 
31
- export interface TableOutput extends TableProps {
32
- id: string; // Same as tableName
32
+ export interface Table extends Resource<"dynamo::Table">, TableProps {
33
33
  arn: string;
34
34
  streamArn?: string;
35
35
  tableId: string;
36
36
  }
37
37
 
38
- export class Table extends Resource(
38
+ export const Table = Resource(
39
39
  "dynamo::Table",
40
- async (
41
- ctx: Context<TableOutput>,
40
+ async function (
41
+ this: Context<Table>,
42
+ id: string,
42
43
  props: TableProps,
43
- ): Promise<TableOutput | void> => {
44
+ ): Promise<Table> {
44
45
  const client = new DynamoDBClient({});
45
46
 
46
- if (ctx.event === "delete") {
47
+ if (this.phase === "delete") {
47
48
  await withExponentialBackoff(
48
49
  async () => {
49
50
  await ignore(ResourceNotFoundException.name, () =>
@@ -93,7 +94,7 @@ export class Table extends Resource(
93
94
  );
94
95
  }
95
96
 
96
- return;
97
+ return this.destroy();
97
98
  } else {
98
99
  // Setup for table creation
99
100
  const attributeDefinitions = [
@@ -213,13 +214,12 @@ export class Table extends Resource(
213
214
  );
214
215
  }
215
216
 
216
- return {
217
+ return this({
217
218
  ...props,
218
- id: props.tableName,
219
219
  arn: tableDescription!.TableArn!,
220
220
  streamArn: tableDescription!.LatestStreamArn,
221
221
  tableId: tableDescription!.TableId!,
222
- };
222
+ });
223
223
  }
224
224
  },
225
- ) {}
225
+ );
@@ -24,6 +24,14 @@ export type Binding =
24
24
  | Secret
25
25
  | string;
26
26
 
27
+ export function isDurableObjectNamespace(
28
+ binding: Binding,
29
+ ): binding is DurableObjectNamespace {
30
+ return (
31
+ typeof binding === "object" && binding.type === "durable_object_namespace"
32
+ );
33
+ }
34
+
27
35
  /**
28
36
  * Union type for all Worker binding types (API spec)
29
37
  */
@@ -1,5 +1,5 @@
1
- import type { Resolved } from "../output";
2
- import { type Context, Resource } from "../resource";
1
+ import type { Context } from "../context";
2
+ import { Resource } from "../resource";
3
3
  import { createCloudflareApi } from "./api";
4
4
 
5
5
  /**
@@ -11,7 +11,7 @@ export interface BucketProps {
11
11
  * Names can only contain lowercase letters (a-z), numbers (0-9), and hyphens (-)
12
12
  * Cannot begin or end with a hyphen
13
13
  */
14
- name?: string;
14
+ name: string;
15
15
 
16
16
  /**
17
17
  * Optional location hint for the bucket
@@ -35,11 +35,13 @@ export interface BucketProps {
35
35
  /**
36
36
  * Output returned after R2 Bucket creation/update
37
37
  */
38
- export interface BucketOutput extends BucketProps {
38
+ export interface R2Bucket
39
+ extends Resource<"cloudflare::R2Bucket">,
40
+ BucketProps {
39
41
  /**
40
- * The ID of the bucket (same as name)
42
+ * Resource type identifier
41
43
  */
42
- id: string;
44
+ type: "r2_bucket";
43
45
 
44
46
  /**
45
47
  * Location of the bucket
@@ -50,44 +52,23 @@ export interface BucketOutput extends BucketProps {
50
52
  * Time at which the bucket was created (Unix timestamp in seconds)
51
53
  */
52
54
  creationDate: number;
53
-
54
- /**
55
- * Resource type identifier
56
- */
57
- type: "r2_bucket";
58
- }
59
-
60
- /**
61
- * Cloudflare R2 bucket API response
62
- */
63
- interface CloudflareBucketResponse {
64
- result: {
65
- name: string;
66
- location?: string;
67
- creation_date: string;
68
- };
69
- success: boolean;
70
- errors: Array<{ code: number; message: string }>;
71
- messages: string[];
72
- }
73
-
74
- export function isBucket(resource: any): resource is Resolved<R2Bucket> {
75
- return (
76
- resource && typeof resource === "object" && resource.id && resource.location
77
- );
78
55
  }
79
56
 
80
- export class R2Bucket extends Resource(
57
+ export const R2Bucket = Resource(
81
58
  "cloudflare::R2Bucket",
82
- async (ctx: Context<BucketOutput>, props: BucketProps) => {
59
+ async function (
60
+ this: Context<R2Bucket>,
61
+ id: string,
62
+ props: BucketProps,
63
+ ): Promise<R2Bucket> {
83
64
  // Create Cloudflare API client with automatic account discovery
84
65
  const api = await createCloudflareApi();
85
66
 
86
67
  // Resource ID defaults to bucket name if provided
87
- const bucketName = props.name || ctx.resourceID;
68
+ const bucketName = props.name || this.id;
88
69
 
89
- if (ctx.event === "delete") {
90
- if (ctx.output?.id) {
70
+ if (this.phase === "delete") {
71
+ if (this.output?.name) {
91
72
  // Delete R2 bucket
92
73
  const headers: Record<string, string> = {};
93
74
  if (props.jurisdiction && props.jurisdiction !== "default") {
@@ -95,7 +76,7 @@ export class R2Bucket extends Resource(
95
76
  }
96
77
 
97
78
  const deleteResponse = await api.delete(
98
- `/accounts/${api.accountId}/r2/buckets/${ctx.output.id}`,
79
+ `/accounts/${api.accountId}/r2/buckets/${this.output.name}`,
99
80
  { headers },
100
81
  );
101
82
 
@@ -110,12 +91,25 @@ export class R2Bucket extends Resource(
110
91
  }
111
92
 
112
93
  // Return void (a deleted bucket has no content)
113
- return;
94
+ return this.destroy();
114
95
  } else {
96
+ /**
97
+ * Cloudflare R2 bucket API response
98
+ */
99
+ interface CloudflareBucketResponse {
100
+ result: {
101
+ name: string;
102
+ location?: string;
103
+ creation_date: string;
104
+ };
105
+ success: boolean;
106
+ errors: Array<{ code: number; message: string }>;
107
+ messages: string[];
108
+ }
115
109
  try {
116
- let bucketOutput: BucketOutput;
110
+ let bucketOutput: R2Bucket;
117
111
 
118
- if (ctx.event === "update" && ctx.output?.id) {
112
+ if (this.phase === "update" && this.output?.name) {
119
113
  // Get bucket details to verify it exists
120
114
  const headers: Record<string, string> = {};
121
115
  if (props.jurisdiction && props.jurisdiction !== "default") {
@@ -137,8 +131,7 @@ export class R2Bucket extends Resource(
137
131
  }
138
132
 
139
133
  const result = (await getResponse.json()) as CloudflareBucketResponse;
140
- bucketOutput = {
141
- id: result.result.name,
134
+ bucketOutput = this({
142
135
  name: result.result.name,
143
136
  location: result.result.location || "default",
144
137
  creationDate: Math.floor(
@@ -146,7 +139,7 @@ export class R2Bucket extends Resource(
146
139
  ),
147
140
  jurisdiction: props.jurisdiction || "default",
148
141
  type: "r2_bucket",
149
- };
142
+ });
150
143
 
151
144
  // Update public access setting if it has changed
152
145
  if (props.allowPublicAccess !== undefined) {
@@ -184,8 +177,7 @@ export class R2Bucket extends Resource(
184
177
 
185
178
  const result =
186
179
  (await createResponse.json()) as CloudflareBucketResponse;
187
- bucketOutput = {
188
- id: result.result.name,
180
+ bucketOutput = this({
189
181
  name: result.result.name,
190
182
  location: result.result.location || "default",
191
183
  creationDate: Math.floor(
@@ -193,7 +185,7 @@ export class R2Bucket extends Resource(
193
185
  ),
194
186
  jurisdiction: props.jurisdiction || "default",
195
187
  type: "r2_bucket",
196
- };
188
+ });
197
189
 
198
190
  // Set public access if requested
199
191
  if (props.allowPublicAccess) {
@@ -208,7 +200,7 @@ export class R2Bucket extends Resource(
208
200
  }
209
201
  }
210
202
  },
211
- ) {}
203
+ );
212
204
 
213
205
  /**
214
206
  * Helper function to update the public access setting for a bucket
@@ -1,5 +1,3 @@
1
- import type { Resolved } from "../output";
2
-
3
1
  export interface DurableObjectNamespaceInput {
4
2
  className: string;
5
3
  scriptName?: string | undefined;
@@ -8,14 +6,6 @@ export interface DurableObjectNamespaceInput {
8
6
  namespaceId?: string | undefined;
9
7
  }
10
8
 
11
- export function isDurableObjectNamespace(
12
- binding: any,
13
- ): binding is Resolved<DurableObjectNamespace> {
14
- return (
15
- typeof binding === "object" && binding.type === "durable_object_namespace"
16
- );
17
- }
18
-
19
9
  export class DurableObjectNamespace implements DurableObjectNamespaceInput {
20
10
  public readonly type = "durable_object_namespace" as const;
21
11
  // alias for bindingName to be consistent with other bindings
@@ -2,7 +2,7 @@ import crypto from "crypto";
2
2
  import { promises as fs } from "fs";
3
3
  import { glob } from "glob";
4
4
  import path from "path";
5
- import { getContentType } from "../utils/content-type";
5
+ import { getContentType } from "../util/content-type";
6
6
  import type {
7
7
  AssetManifest,
8
8
  AssetManifestEntry,
@@ -5,3 +5,5 @@ export * from "./kv-namespace";
5
5
  export * from "./state";
6
6
  export * from "./static-site";
7
7
  export * from "./worker";
8
+ export * from "./wrangler.json";
9
+ export * from "./zone";