alchemy 0.1.18 → 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.
Files changed (310) hide show
  1. package/lib/alchemy.d.ts +67 -0
  2. package/lib/alchemy.js +40 -0
  3. package/lib/apply.d.ts +3 -20
  4. package/lib/apply.js +86 -82
  5. package/lib/aws/account-id.d.ts +0 -1
  6. package/lib/aws/account-id.js +0 -1
  7. package/lib/aws/bucket.d.ts +4 -7
  8. package/lib/aws/bucket.js +8 -12
  9. package/lib/aws/function.d.ts +4 -7
  10. package/lib/aws/function.js +9 -30
  11. package/lib/aws/index.d.ts +1 -1
  12. package/lib/aws/index.js +1 -1
  13. package/lib/aws/oidc/github-oidc-provider.d.ts +2 -6
  14. package/lib/aws/oidc/github-oidc-provider.js +10 -15
  15. package/lib/aws/oidc/index.d.ts +0 -1
  16. package/lib/aws/oidc/index.js +0 -1
  17. package/lib/aws/oidc/oidc-provider.d.ts +4 -6
  18. package/lib/aws/oidc/oidc-provider.js +9 -11
  19. package/lib/aws/policy-attachment.d.ts +9 -0
  20. package/lib/aws/policy-attachment.js +20 -0
  21. package/lib/aws/policy.d.ts +4 -16
  22. package/lib/aws/policy.js +9 -40
  23. package/lib/aws/queue.d.ts +4 -34
  24. package/lib/aws/queue.js +10 -20
  25. package/lib/aws/role.d.ts +4 -7
  26. package/lib/aws/role.js +17 -26
  27. package/lib/aws/ses.d.ts +4 -10
  28. package/lib/aws/ses.js +118 -131
  29. package/lib/aws/table.d.ts +4 -7
  30. package/lib/aws/table.js +8 -11
  31. package/lib/cloudflare/api.d.ts +0 -1
  32. package/lib/cloudflare/api.js +0 -1
  33. package/lib/cloudflare/asset-manifest.d.ts +0 -1
  34. package/lib/cloudflare/asset-manifest.js +0 -1
  35. package/lib/cloudflare/auth.d.ts +0 -1
  36. package/lib/cloudflare/auth.js +0 -1
  37. package/lib/cloudflare/bindings.d.ts +1 -1
  38. package/lib/cloudflare/bindings.js +3 -2
  39. package/lib/cloudflare/bound.d.ts +0 -1
  40. package/lib/cloudflare/bound.js +0 -1
  41. package/lib/cloudflare/bucket.d.ts +7 -15
  42. package/lib/cloudflare/bucket.js +12 -19
  43. package/lib/cloudflare/durable-object-namespace.d.ts +0 -3
  44. package/lib/cloudflare/durable-object-namespace.js +0 -4
  45. package/lib/cloudflare/generate-asset-manifest.d.ts +0 -1
  46. package/lib/cloudflare/generate-asset-manifest.js +1 -2
  47. package/lib/cloudflare/index.d.ts +0 -1
  48. package/lib/cloudflare/index.js +0 -1
  49. package/lib/cloudflare/kv-namespace.d.ts +6 -9
  50. package/lib/cloudflare/kv-namespace.js +16 -20
  51. package/lib/cloudflare/state.d.ts +0 -1
  52. package/lib/cloudflare/state.js +0 -1
  53. package/lib/cloudflare/static-site-router.d.ts +0 -1
  54. package/lib/cloudflare/static-site-router.js +0 -4
  55. package/lib/cloudflare/static-site.d.ts +5 -11
  56. package/lib/cloudflare/static-site.js +16 -28
  57. package/lib/cloudflare/types.d.ts +0 -1
  58. package/lib/cloudflare/types.js +0 -1
  59. package/lib/cloudflare/upload-asset-manifest.d.ts +0 -1
  60. package/lib/cloudflare/upload-asset-manifest.js +0 -1
  61. package/lib/cloudflare/worker-metadata.d.ts +0 -1
  62. package/lib/cloudflare/worker-metadata.js +0 -1
  63. package/lib/cloudflare/worker-migration.d.ts +0 -1
  64. package/lib/cloudflare/worker-migration.js +0 -1
  65. package/lib/cloudflare/worker.d.ts +8 -14
  66. package/lib/cloudflare/worker.js +37 -49
  67. package/lib/context.d.ts +58 -0
  68. package/lib/context.js +36 -0
  69. package/lib/destroy.d.ts +10 -13
  70. package/lib/destroy.js +104 -43
  71. package/lib/{esbuild.d.ts → esbuild/bundle.d.ts} +4 -18
  72. package/lib/{esbuild.js → esbuild/bundle.js} +10 -24
  73. package/lib/esbuild/index.d.ts +1 -0
  74. package/lib/esbuild/index.js +1 -0
  75. package/lib/fs/file.d.ts +13 -0
  76. package/lib/fs/file.js +20 -0
  77. package/lib/fs/folder.d.ts +10 -0
  78. package/lib/fs/folder.js +16 -0
  79. package/lib/fs/index.d.ts +2 -0
  80. package/lib/fs/index.js +2 -0
  81. package/lib/github/client.d.ts +0 -1
  82. package/lib/github/client.js +0 -1
  83. package/lib/github/index.d.ts +0 -1
  84. package/lib/github/index.js +0 -1
  85. package/lib/github/secret.d.ts +4 -6
  86. package/lib/github/secret.js +10 -12
  87. package/lib/index.d.ts +6 -10
  88. package/lib/index.js +5 -9
  89. package/lib/resource.d.ts +34 -62
  90. package/lib/resource.js +29 -270
  91. package/lib/scope.d.ts +35 -14
  92. package/lib/scope.js +78 -23
  93. package/lib/secret.d.ts +2 -7
  94. package/lib/secret.js +7 -20
  95. package/lib/state.d.ts +14 -10
  96. package/lib/state.js +15 -14
  97. package/lib/stripe/index.d.ts +0 -1
  98. package/lib/stripe/index.js +0 -1
  99. package/lib/stripe/price.d.ts +4 -5
  100. package/lib/stripe/price.js +10 -20
  101. package/lib/stripe/product.d.ts +4 -5
  102. package/lib/stripe/product.js +10 -20
  103. package/lib/stripe/webhook.d.ts +4 -6
  104. package/lib/stripe/webhook.js +12 -25
  105. package/lib/test/bun.d.ts +19 -0
  106. package/lib/test/bun.js +55 -0
  107. package/lib/{utils → util}/content-type.d.ts +0 -1
  108. package/lib/{utils → util}/content-type.js +0 -1
  109. package/lib/{encrypt.d.ts → util/encrypt.d.ts} +0 -1
  110. package/lib/{encrypt.js → util/encrypt.js} +0 -1
  111. package/lib/{error.d.ts → util/ignore.d.ts} +0 -1
  112. package/lib/{error.js → util/ignore.js} +0 -1
  113. package/lib/{utils → util}/retry.d.ts +0 -1
  114. package/lib/{utils → util}/retry.js +0 -1
  115. package/lib/util/serde.d.ts +3 -0
  116. package/lib/{serde.js → util/serde.js} +19 -10
  117. package/lib/util/slugify.d.ts +1 -0
  118. package/lib/util/slugify.js +3 -0
  119. package/package.json +5 -4
  120. package/src/alchemy.ts +120 -0
  121. package/src/apply.ts +109 -114
  122. package/src/aws/bucket.ts +11 -14
  123. package/src/aws/function.ts +13 -33
  124. package/src/aws/index.ts +1 -0
  125. package/src/aws/oidc/github-oidc-provider.ts +14 -19
  126. package/src/aws/oidc/oidc-provider.ts +19 -12
  127. package/src/aws/policy-attachment.ts +51 -0
  128. package/src/aws/policy.ts +15 -60
  129. package/src/aws/queue.ts +17 -21
  130. package/src/aws/role.ts +25 -28
  131. package/src/aws/ses.ts +150 -164
  132. package/src/aws/table.ts +15 -15
  133. package/src/cloudflare/bindings.ts +8 -0
  134. package/src/cloudflare/bucket.ts +39 -47
  135. package/src/cloudflare/durable-object-namespace.ts +0 -10
  136. package/src/cloudflare/generate-asset-manifest.ts +1 -1
  137. package/src/cloudflare/kv-namespace.ts +35 -33
  138. package/src/cloudflare/static-site-router.ts +0 -3
  139. package/src/cloudflare/static-site.ts +44 -60
  140. package/src/cloudflare/worker.ts +105 -111
  141. package/src/context.ts +122 -0
  142. package/src/destroy.ts +124 -73
  143. package/src/{esbuild.ts → esbuild/bundle.ts} +16 -28
  144. package/src/esbuild/index.ts +1 -0
  145. package/src/fs/file.ts +39 -0
  146. package/src/fs/folder.ts +32 -0
  147. package/src/fs/index.ts +2 -0
  148. package/src/github/secret.ts +19 -16
  149. package/src/index.ts +7 -15
  150. package/src/resource.ts +101 -462
  151. package/src/scope.ts +101 -36
  152. package/src/secret.ts +9 -32
  153. package/src/state.ts +30 -21
  154. package/src/stripe/price.ts +17 -22
  155. package/src/stripe/product.ts +17 -22
  156. package/src/stripe/webhook.ts +21 -27
  157. package/src/test/bun.ts +105 -0
  158. package/src/util/serde.ts +53 -0
  159. package/src/util/slugify.ts +3 -0
  160. package/lib/$.d.ts +0 -12
  161. package/lib/$.d.ts.map +0 -1
  162. package/lib/$.js +0 -42
  163. package/lib/$.js.map +0 -1
  164. package/lib/alchemize.d.ts +0 -47
  165. package/lib/alchemize.d.ts.map +0 -1
  166. package/lib/alchemize.js +0 -116
  167. package/lib/alchemize.js.map +0 -1
  168. package/lib/apply.d.ts.map +0 -1
  169. package/lib/apply.js.map +0 -1
  170. package/lib/aws/account-id.d.ts.map +0 -1
  171. package/lib/aws/account-id.js.map +0 -1
  172. package/lib/aws/bucket.d.ts.map +0 -1
  173. package/lib/aws/bucket.js.map +0 -1
  174. package/lib/aws/function.d.ts.map +0 -1
  175. package/lib/aws/function.js.map +0 -1
  176. package/lib/aws/index.d.ts.map +0 -1
  177. package/lib/aws/index.js.map +0 -1
  178. package/lib/aws/oidc/github-oidc-provider.d.ts.map +0 -1
  179. package/lib/aws/oidc/github-oidc-provider.js.map +0 -1
  180. package/lib/aws/oidc/index.d.ts.map +0 -1
  181. package/lib/aws/oidc/index.js.map +0 -1
  182. package/lib/aws/oidc/oidc-provider.d.ts.map +0 -1
  183. package/lib/aws/oidc/oidc-provider.js.map +0 -1
  184. package/lib/aws/policy.d.ts.map +0 -1
  185. package/lib/aws/policy.js.map +0 -1
  186. package/lib/aws/queue.d.ts.map +0 -1
  187. package/lib/aws/queue.js.map +0 -1
  188. package/lib/aws/role.d.ts.map +0 -1
  189. package/lib/aws/role.js.map +0 -1
  190. package/lib/aws/ses.d.ts.map +0 -1
  191. package/lib/aws/ses.js.map +0 -1
  192. package/lib/aws/table.d.ts.map +0 -1
  193. package/lib/aws/table.js.map +0 -1
  194. package/lib/cloudflare/api.d.ts.map +0 -1
  195. package/lib/cloudflare/api.js.map +0 -1
  196. package/lib/cloudflare/asset-manifest.d.ts.map +0 -1
  197. package/lib/cloudflare/asset-manifest.js.map +0 -1
  198. package/lib/cloudflare/auth.d.ts.map +0 -1
  199. package/lib/cloudflare/auth.js.map +0 -1
  200. package/lib/cloudflare/bindings.d.ts.map +0 -1
  201. package/lib/cloudflare/bindings.js.map +0 -1
  202. package/lib/cloudflare/bound.d.ts.map +0 -1
  203. package/lib/cloudflare/bound.js.map +0 -1
  204. package/lib/cloudflare/bucket.d.ts.map +0 -1
  205. package/lib/cloudflare/bucket.js.map +0 -1
  206. package/lib/cloudflare/durable-object-namespace.d.ts.map +0 -1
  207. package/lib/cloudflare/durable-object-namespace.js.map +0 -1
  208. package/lib/cloudflare/generate-asset-manifest.d.ts.map +0 -1
  209. package/lib/cloudflare/generate-asset-manifest.js.map +0 -1
  210. package/lib/cloudflare/index.d.ts.map +0 -1
  211. package/lib/cloudflare/index.js.map +0 -1
  212. package/lib/cloudflare/kv-namespace.d.ts.map +0 -1
  213. package/lib/cloudflare/kv-namespace.js.map +0 -1
  214. package/lib/cloudflare/state.d.ts.map +0 -1
  215. package/lib/cloudflare/state.js.map +0 -1
  216. package/lib/cloudflare/static-site-router.d.ts.map +0 -1
  217. package/lib/cloudflare/static-site-router.js.map +0 -1
  218. package/lib/cloudflare/static-site.d.ts.map +0 -1
  219. package/lib/cloudflare/static-site.js.map +0 -1
  220. package/lib/cloudflare/types.d.ts.map +0 -1
  221. package/lib/cloudflare/types.js.map +0 -1
  222. package/lib/cloudflare/upload-asset-manifest.d.ts.map +0 -1
  223. package/lib/cloudflare/upload-asset-manifest.js.map +0 -1
  224. package/lib/cloudflare/worker-metadata.d.ts.map +0 -1
  225. package/lib/cloudflare/worker-metadata.js.map +0 -1
  226. package/lib/cloudflare/worker-migration.d.ts.map +0 -1
  227. package/lib/cloudflare/worker-migration.js.map +0 -1
  228. package/lib/cloudflare/worker.d.ts.map +0 -1
  229. package/lib/cloudflare/worker.js.map +0 -1
  230. package/lib/destroy.d.ts.map +0 -1
  231. package/lib/destroy.js.map +0 -1
  232. package/lib/encrypt.d.ts.map +0 -1
  233. package/lib/encrypt.js.map +0 -1
  234. package/lib/error.d.ts.map +0 -1
  235. package/lib/error.js.map +0 -1
  236. package/lib/esbuild.d.ts.map +0 -1
  237. package/lib/esbuild.js.map +0 -1
  238. package/lib/fs.d.ts +0 -12
  239. package/lib/fs.d.ts.map +0 -1
  240. package/lib/fs.js +0 -41
  241. package/lib/fs.js.map +0 -1
  242. package/lib/github/client.d.ts.map +0 -1
  243. package/lib/github/client.js.map +0 -1
  244. package/lib/github/index.d.ts.map +0 -1
  245. package/lib/github/index.js.map +0 -1
  246. package/lib/github/secret.d.ts.map +0 -1
  247. package/lib/github/secret.js.map +0 -1
  248. package/lib/global.d.ts +0 -16
  249. package/lib/global.d.ts.map +0 -1
  250. package/lib/global.js +0 -42
  251. package/lib/global.js.map +0 -1
  252. package/lib/index.d.ts.map +0 -1
  253. package/lib/index.js.map +0 -1
  254. package/lib/input.d.ts +0 -7
  255. package/lib/input.d.ts.map +0 -1
  256. package/lib/input.js +0 -2
  257. package/lib/input.js.map +0 -1
  258. package/lib/main.d.ts +0 -3
  259. package/lib/main.d.ts.map +0 -1
  260. package/lib/main.js +0 -32
  261. package/lib/main.js.map +0 -1
  262. package/lib/output.d.ts +0 -25
  263. package/lib/output.d.ts.map +0 -1
  264. package/lib/output.js +0 -23
  265. package/lib/output.js.map +0 -1
  266. package/lib/print.d.ts +0 -7
  267. package/lib/print.d.ts.map +0 -1
  268. package/lib/print.js +0 -10
  269. package/lib/print.js.map +0 -1
  270. package/lib/resource.d.ts.map +0 -1
  271. package/lib/resource.js.map +0 -1
  272. package/lib/scope.d.ts.map +0 -1
  273. package/lib/scope.js.map +0 -1
  274. package/lib/secret.d.ts.map +0 -1
  275. package/lib/secret.js.map +0 -1
  276. package/lib/serde.d.ts +0 -3
  277. package/lib/serde.d.ts.map +0 -1
  278. package/lib/serde.js.map +0 -1
  279. package/lib/slug.d.ts +0 -2
  280. package/lib/slug.d.ts.map +0 -1
  281. package/lib/slug.js +0 -4
  282. package/lib/slug.js.map +0 -1
  283. package/lib/state.d.ts.map +0 -1
  284. package/lib/state.js.map +0 -1
  285. package/lib/stripe/index.d.ts.map +0 -1
  286. package/lib/stripe/index.js.map +0 -1
  287. package/lib/stripe/price.d.ts.map +0 -1
  288. package/lib/stripe/price.js.map +0 -1
  289. package/lib/stripe/product.d.ts.map +0 -1
  290. package/lib/stripe/product.js.map +0 -1
  291. package/lib/stripe/webhook.d.ts.map +0 -1
  292. package/lib/stripe/webhook.js.map +0 -1
  293. package/lib/utils/content-type.d.ts.map +0 -1
  294. package/lib/utils/content-type.js.map +0 -1
  295. package/lib/utils/retry.d.ts.map +0 -1
  296. package/lib/utils/retry.js.map +0 -1
  297. package/src/$.ts +0 -69
  298. package/src/alchemize.ts +0 -195
  299. package/src/fs.ts +0 -47
  300. package/src/global.ts +0 -63
  301. package/src/input.ts +0 -19
  302. package/src/main.ts +0 -34
  303. package/src/output.ts +0 -75
  304. package/src/print.ts +0 -18
  305. package/src/serde.ts +0 -46
  306. package/src/slug.ts +0 -3
  307. /package/src/{utils → util}/content-type.ts +0 -0
  308. /package/src/{encrypt.ts → util/encrypt.ts} +0 -0
  309. /package/src/{error.ts → util/ignore.ts} +0 -0
  310. /package/src/{utils → util}/retry.ts +0 -0
@@ -0,0 +1,51 @@
1
+ import {
2
+ AttachRolePolicyCommand,
3
+ DetachRolePolicyCommand,
4
+ IAMClient,
5
+ NoSuchEntityException,
6
+ } from "@aws-sdk/client-iam";
7
+ import type { Context } from "../context";
8
+ import { Resource } from "../resource";
9
+ import { ignore } from "../util/ignore";
10
+
11
+ // PolicyAttachment resource
12
+ export interface PolicyAttachmentProps {
13
+ policyArn: string;
14
+ roleName: string;
15
+ }
16
+
17
+ export interface PolicyAttachment
18
+ extends Resource<"iam::PolicyAttachment">,
19
+ PolicyAttachmentProps {}
20
+
21
+ export const PolicyAttachment = Resource(
22
+ "iam::PolicyAttachment",
23
+ async function (
24
+ this: Context<PolicyAttachment>,
25
+ id: string,
26
+ props: PolicyAttachmentProps,
27
+ ) {
28
+ const client = new IAMClient({});
29
+
30
+ if (this.phase === "delete") {
31
+ await ignore(NoSuchEntityException.name, () =>
32
+ client.send(
33
+ new DetachRolePolicyCommand({
34
+ PolicyArn: props.policyArn,
35
+ RoleName: props.roleName,
36
+ }),
37
+ ),
38
+ );
39
+ return this.destroy();
40
+ } else {
41
+ await client.send(
42
+ new AttachRolePolicyCommand({
43
+ PolicyArn: props.policyArn,
44
+ RoleName: props.roleName,
45
+ }),
46
+ );
47
+ }
48
+
49
+ return this(props);
50
+ },
51
+ );
package/src/aws/policy.ts CHANGED
@@ -1,17 +1,15 @@
1
1
  import {
2
- AttachRolePolicyCommand,
3
2
  CreatePolicyCommand,
4
3
  CreatePolicyVersionCommand,
5
4
  DeletePolicyCommand,
6
5
  DeletePolicyVersionCommand,
7
- DetachRolePolicyCommand,
8
6
  GetPolicyCommand,
9
7
  GetPolicyVersionCommand,
10
8
  IAMClient,
11
9
  ListPolicyVersionsCommand,
12
10
  NoSuchEntityException,
13
11
  } from "@aws-sdk/client-iam";
14
- import { ignore } from "../error";
12
+ import type { Context } from "../context";
15
13
  import { Resource } from "../resource";
16
14
 
17
15
  // Type-safe policy document types
@@ -43,8 +41,7 @@ export interface PolicyProps {
43
41
  tags?: Record<string, string>;
44
42
  }
45
43
 
46
- export interface PolicyOutput extends PolicyProps {
47
- id: string; // Same as policyName
44
+ export interface Policy extends Resource<"iam::Policy">, PolicyProps {
48
45
  arn: string;
49
46
  defaultVersionId: string;
50
47
  attachmentCount: number;
@@ -53,13 +50,17 @@ export interface PolicyOutput extends PolicyProps {
53
50
  isAttachable: boolean;
54
51
  }
55
52
 
56
- export class Policy extends Resource(
53
+ export const Policy = Resource(
57
54
  "iam::Policy",
58
- async (ctx, props: PolicyProps): Promise<PolicyOutput> => {
55
+ async function (
56
+ this: Context<Policy>,
57
+ id: string,
58
+ props: PolicyProps,
59
+ ): Promise<Policy> {
59
60
  const client = new IAMClient({});
60
61
  const policyArn = `arn:aws:iam::${process.env.AWS_ACCOUNT_ID}:policy${props.path || "/"}${props.policyName}`;
61
62
 
62
- if (ctx.event === "delete") {
63
+ if (this.phase === "delete") {
63
64
  try {
64
65
  // List and delete all non-default versions first
65
66
  const versions = await client.send(
@@ -90,16 +91,7 @@ export class Policy extends Resource(
90
91
  throw error;
91
92
  }
92
93
  }
93
- return {
94
- ...props,
95
- id: props.policyName,
96
- arn: policyArn,
97
- defaultVersionId: "v1",
98
- attachmentCount: 0,
99
- createDate: new Date(),
100
- updateDate: new Date(),
101
- isAttachable: true,
102
- };
94
+ return this.destroy();
103
95
  } else {
104
96
  try {
105
97
  // Check if policy exists
@@ -164,16 +156,15 @@ export class Policy extends Resource(
164
156
  }),
165
157
  );
166
158
 
167
- return {
159
+ return this({
168
160
  ...props,
169
- id: props.policyName,
170
161
  arn: policy.Policy!.Arn!,
171
162
  defaultVersionId: policy.Policy!.DefaultVersionId!,
172
163
  attachmentCount: policy.Policy!.AttachmentCount!,
173
164
  createDate: policy.Policy!.CreateDate!,
174
165
  updateDate: policy.Policy!.UpdateDate!,
175
166
  isAttachable: policy.Policy!.IsAttachable!,
176
- };
167
+ });
177
168
  } catch (error: any) {
178
169
  if (error.name === "NoSuchEntity") {
179
170
  // Create new policy
@@ -192,54 +183,18 @@ export class Policy extends Resource(
192
183
  }),
193
184
  );
194
185
 
195
- return {
186
+ return this({
196
187
  ...props,
197
- id: props.policyName,
198
188
  arn: newPolicy.Policy!.Arn!,
199
189
  defaultVersionId: newPolicy.Policy!.DefaultVersionId!,
200
190
  attachmentCount: newPolicy.Policy!.AttachmentCount!,
201
191
  createDate: newPolicy.Policy!.CreateDate!,
202
192
  updateDate: newPolicy.Policy!.UpdateDate!,
203
193
  isAttachable: newPolicy.Policy!.IsAttachable!,
204
- };
194
+ });
205
195
  }
206
196
  throw error;
207
197
  }
208
198
  }
209
199
  },
210
- ) {}
211
-
212
- // PolicyAttachment resource
213
- export interface PolicyAttachmentProps {
214
- policyArn: string;
215
- roleName: string;
216
- }
217
-
218
- export interface PolicyAttachmentOutput extends PolicyAttachmentProps {}
219
-
220
- export class PolicyAttachment extends Resource(
221
- "iam::PolicyAttachment",
222
- async (ctx, props: PolicyAttachmentProps) => {
223
- const client = new IAMClient({});
224
-
225
- if (ctx.event === "delete") {
226
- await ignore(NoSuchEntityException.name, () =>
227
- client.send(
228
- new DetachRolePolicyCommand({
229
- PolicyArn: props.policyArn,
230
- RoleName: props.roleName,
231
- }),
232
- ),
233
- );
234
- } else {
235
- await client.send(
236
- new AttachRolePolicyCommand({
237
- PolicyArn: props.policyArn,
238
- RoleName: props.roleName,
239
- }),
240
- );
241
- }
242
-
243
- return props;
244
- },
245
- ) {}
200
+ );
package/src/aws/queue.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  GetQueueUrlCommand,
6
6
  SQSClient,
7
7
  } from "@aws-sdk/client-sqs";
8
+ import type { Context } from "../context";
8
9
  import { Resource } from "../resource";
9
10
 
10
11
  export interface QueueProps {
@@ -37,15 +38,18 @@ export interface QueueProps {
37
38
  tags?: Record<string, string>;
38
39
  }
39
40
 
40
- export interface QueueOutput extends QueueProps {
41
- id: string; // Same as queueName
41
+ export interface Queue extends Resource<"sqs::Queue">, QueueProps {
42
42
  arn: string;
43
43
  url: string;
44
44
  }
45
45
 
46
- export class Queue extends Resource(
46
+ export const Queue = Resource(
47
47
  "sqs::Queue",
48
- async (ctx, props: QueueProps) => {
48
+ async function (
49
+ this: Context<Queue>,
50
+ id: string,
51
+ props: QueueProps,
52
+ ): Promise<Queue> {
49
53
  const client = new SQSClient({});
50
54
  // Don't automatically add .fifo suffix - user must include it in queueName
51
55
  const queueName = props.queueName;
@@ -55,7 +59,7 @@ export class Queue extends Resource(
55
59
  throw new Error("FIFO queue names must end with .fifo suffix");
56
60
  }
57
61
 
58
- if (ctx.event === "delete") {
62
+ if (this.phase === "delete") {
59
63
  try {
60
64
  // Get queue URL first
61
65
  const urlResponse = await client.send(
@@ -96,12 +100,7 @@ export class Queue extends Resource(
96
100
  }
97
101
  }
98
102
 
99
- return {
100
- ...props,
101
- id: props.queueName,
102
- arn: `arn:aws:sqs:${client.config.region}:${process.env.AWS_ACCOUNT_ID}:${queueName}`,
103
- url: "",
104
- };
103
+ return this.destroy();
105
104
  } else {
106
105
  // Create queue with attributes
107
106
  const attributes: Record<string, string> = {};
@@ -164,12 +163,11 @@ export class Queue extends Resource(
164
163
  }),
165
164
  );
166
165
 
167
- return {
166
+ return this({
168
167
  ...props,
169
- id: props.queueName,
170
168
  arn: attributesResponse.Attributes!.QueueArn!,
171
169
  url: createResponse.QueueUrl!,
172
- };
170
+ });
173
171
  } catch (error: any) {
174
172
  if (error.name === "QueueAlreadyExists") {
175
173
  // Get existing queue URL
@@ -187,12 +185,11 @@ export class Queue extends Resource(
187
185
  }),
188
186
  );
189
187
 
190
- return {
188
+ return this({
191
189
  ...props,
192
- id: props.queueName,
193
190
  arn: attributesResponse.Attributes!.QueueArn!,
194
191
  url: urlResponse.QueueUrl!,
195
- };
192
+ });
196
193
  } else if (error.name === "QueueDeletedRecently") {
197
194
  // Queue was recently deleted, wait and retry
198
195
  const maxRetries = 3;
@@ -220,12 +217,11 @@ export class Queue extends Resource(
220
217
  }),
221
218
  );
222
219
 
223
- return {
220
+ return this({
224
221
  ...props,
225
- id: props.queueName,
226
222
  arn: attributesResponse.Attributes!.QueueArn!,
227
223
  url: createResponse.QueueUrl!,
228
- };
224
+ });
229
225
  } catch (retryError: any) {
230
226
  if (
231
227
  retryError.name !== "QueueDeletedRecently" ||
@@ -241,4 +237,4 @@ export class Queue extends Resource(
241
237
  }
242
238
  }
243
239
  },
244
- ) {}
240
+ );
package/src/aws/role.ts CHANGED
@@ -15,8 +15,9 @@ import {
15
15
  UpdateAssumeRolePolicyCommand,
16
16
  UpdateRoleCommand,
17
17
  } from "@aws-sdk/client-iam";
18
- import { ignore } from "../error";
19
- import { type Context, Resource } from "../resource";
18
+ import type { Context } from "../context";
19
+ import { Resource } from "../resource";
20
+ import { ignore } from "../util/ignore";
20
21
  import type { PolicyDocument } from "./policy";
21
22
 
22
23
  export interface RoleProps {
@@ -34,20 +35,23 @@ export interface RoleProps {
34
35
  tags?: Record<string, string>;
35
36
  }
36
37
 
37
- export interface RoleOutput extends RoleProps {
38
- id: string; // Same as roleName
38
+ export interface Role extends Resource<"iam::Role">, RoleProps {
39
39
  arn: string;
40
40
  uniqueId: string; // Unique identifier for the role
41
41
  roleId: string; // The stable and unique string identifying the role
42
42
  createDate: Date;
43
43
  }
44
44
 
45
- export class Role extends Resource(
45
+ export const Role = Resource(
46
46
  "iam::Role",
47
- async (ctx: Context<RoleOutput>, props: RoleProps): Promise<RoleOutput> => {
47
+ async function (
48
+ this: Context<Role>,
49
+ id: string,
50
+ props: RoleProps,
51
+ ): Promise<Role> {
48
52
  const client = new IAMClient({});
49
53
 
50
- if (ctx.event === "delete") {
54
+ if (this.phase === "delete") {
51
55
  // Delete any inline policies first
52
56
  if (props.policies) {
53
57
  for (const policy of props.policies) {
@@ -95,21 +99,14 @@ export class Role extends Resource(
95
99
  }),
96
100
  ),
97
101
  );
98
- return {
99
- ...props,
100
- id: props.roleName,
101
- arn: `arn:aws:iam::${process.env.AWS_ACCOUNT_ID}:role/${props.roleName}`,
102
- uniqueId: "",
103
- roleId: "",
104
- createDate: new Date(),
105
- };
102
+ return this.destroy();
106
103
  }
107
104
 
108
105
  const assumeRolePolicyDocument = JSON.stringify(props.assumeRolePolicy);
109
106
  let role;
110
107
 
111
108
  try {
112
- if (ctx.event === "create") {
109
+ if (this.phase === "create") {
113
110
  // Try to create the role
114
111
  await client.send(
115
112
  new CreateRoleCommand({
@@ -126,11 +123,11 @@ export class Role extends Resource(
126
123
  })),
127
124
  {
128
125
  Key: "alchemy_stage",
129
- Value: ctx.stage,
126
+ Value: this.stage,
130
127
  },
131
128
  {
132
129
  Key: "alchemy_resource",
133
- Value: ctx.resourceID,
130
+ Value: this.id,
134
131
  },
135
132
  ],
136
133
  }),
@@ -139,7 +136,7 @@ export class Role extends Resource(
139
136
  } catch (error: any) {
140
137
  if (
141
138
  error instanceof EntityAlreadyExistsException &&
142
- ctx.event === "create"
139
+ this.phase === "create"
143
140
  ) {
144
141
  // Check if we were the ones who created it
145
142
  const existingRole = await client.send(
@@ -157,8 +154,8 @@ export class Role extends Resource(
157
154
  ) || {};
158
155
 
159
156
  if (
160
- roleTags.alchemy_stage !== ctx.stage ||
161
- roleTags.alchemy_resource !== ctx.resourceID
157
+ roleTags.alchemy_stage !== this.stage ||
158
+ roleTags.alchemy_resource !== this.id
162
159
  ) {
163
160
  throw error;
164
161
  }
@@ -201,8 +198,8 @@ export class Role extends Resource(
201
198
  // Update tags
202
199
  const newTags = {
203
200
  ...props.tags,
204
- alchemy_stage: ctx.stage,
205
- alchemy_resource: ctx.resourceID,
201
+ alchemy_stage: this.stage,
202
+ alchemy_resource: this.id,
206
203
  };
207
204
  const tags: Tag[] = Object.entries(newTags).map(([Key, Value]) => ({
208
205
  Key,
@@ -217,7 +214,7 @@ export class Role extends Resource(
217
214
 
218
215
  // Handle policy changes
219
216
  const previousPolicies =
220
- ctx.event === "update" ? ctx.output.policies || [] : [];
217
+ this.phase === "update" ? this.output!.policies || [] : [];
221
218
  const currentPolicies = props.policies || [];
222
219
 
223
220
  // Delete policies that were removed
@@ -302,13 +299,13 @@ export class Role extends Resource(
302
299
  throw new Error(`Failed to create or update role ${props.roleName}`);
303
300
  }
304
301
 
305
- return {
302
+ return this({
306
303
  ...props,
307
- id: props.roleName,
308
304
  arn: role.Role.Arn!,
309
305
  uniqueId: role.Role.RoleId!,
310
306
  roleId: role.Role.RoleId!,
307
+ roleName: role.Role.RoleName ?? props.roleName,
311
308
  createDate: role.Role.CreateDate!,
312
- };
309
+ });
313
310
  },
314
- ) {}
311
+ );