alchemy 0.3.0 → 0.4.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 (154) hide show
  1. package/README.md +8 -3
  2. package/lib/ai/astro-file.js +7 -24
  3. package/lib/ai/client.d.ts +7 -0
  4. package/lib/ai/client.js +45 -0
  5. package/lib/ai/css-file.js +7 -24
  6. package/lib/ai/data.d.ts +26 -21
  7. package/lib/ai/data.js +33 -22
  8. package/lib/ai/document.d.ts +76 -5
  9. package/lib/ai/document.js +112 -56
  10. package/lib/ai/html-file.js +7 -24
  11. package/lib/ai/json-file.js +11 -32
  12. package/lib/ai/typescript-file.d.ts +1 -2
  13. package/lib/ai/typescript-file.js +8 -39
  14. package/lib/ai/vue-file.js +7 -24
  15. package/lib/ai/yaml-file.js +12 -48
  16. package/lib/alchemy.d.ts +5 -0
  17. package/lib/alchemy.js +61 -3
  18. package/lib/apply.js +18 -11
  19. package/lib/aws/account-id.d.ts +4 -1
  20. package/lib/aws/account-id.js +1 -1
  21. package/lib/aws/credentials.d.ts +5 -0
  22. package/lib/aws/credentials.js +0 -0
  23. package/lib/aws/oidc/oidc-provider.js +2 -2
  24. package/lib/aws/role.js +35 -23
  25. package/lib/cloudflare/account-api-token.d.ts +168 -0
  26. package/lib/cloudflare/account-api-token.js +179 -0
  27. package/lib/cloudflare/account-id.d.ts +1 -0
  28. package/lib/cloudflare/account-id.js +0 -0
  29. package/lib/cloudflare/api.d.ts +38 -1
  30. package/lib/cloudflare/api.js +55 -4
  31. package/lib/cloudflare/bucket.d.ts +118 -3
  32. package/lib/cloudflare/bucket.js +269 -89
  33. package/lib/cloudflare/custom-domain.d.ts +75 -0
  34. package/lib/cloudflare/custom-domain.js +154 -0
  35. package/lib/cloudflare/{dns.js → dns-records.js} +14 -1
  36. package/lib/cloudflare/generate-asset-manifest.js +1 -1
  37. package/lib/cloudflare/index.d.ts +5 -1
  38. package/lib/cloudflare/index.js +5 -1
  39. package/lib/cloudflare/permission-groups.d.ts +78 -0
  40. package/lib/cloudflare/permission-groups.js +48 -0
  41. package/lib/cloudflare/r2-rest-state-store.d.ts +2 -1
  42. package/lib/cloudflare/r2-rest-state-store.js +3 -2
  43. package/lib/cloudflare/static-site-router.js +16 -7
  44. package/lib/cloudflare/static-site.d.ts +17 -18
  45. package/lib/cloudflare/static-site.js +19 -7
  46. package/lib/cloudflare/upload-asset-manifest.js +4 -2
  47. package/lib/{util/encrypt.d.ts → encrypt.d.ts} +1 -1
  48. package/lib/{util/encrypt.js → encrypt.js} +1 -1
  49. package/lib/fs/copy-file.d.ts +54 -0
  50. package/lib/fs/copy-file.js +63 -0
  51. package/lib/fs/file-system-state-store.js +1 -1
  52. package/lib/fs/file.d.ts +31 -0
  53. package/lib/fs/file.js +30 -5
  54. package/lib/fs/index.d.ts +6 -0
  55. package/lib/fs/index.js +6 -0
  56. package/lib/fs/static-astro-file.d.ts +34 -0
  57. package/lib/fs/static-astro-file.js +39 -0
  58. package/lib/fs/static-css-file.d.ts +24 -0
  59. package/lib/fs/static-css-file.js +29 -0
  60. package/lib/fs/static-html-file.d.ts +31 -0
  61. package/lib/fs/static-html-file.js +36 -0
  62. package/lib/fs/static-json-file.d.ts +2 -2
  63. package/lib/fs/static-json-file.js +3 -2
  64. package/lib/fs/static-text-file.d.ts +1 -1
  65. package/lib/fs/static-text-file.js +3 -2
  66. package/lib/fs/static-typescript-file.d.ts +2 -2
  67. package/lib/fs/static-typescript-file.js +3 -2
  68. package/lib/fs/static-vue-file.d.ts +28 -0
  69. package/lib/fs/static-vue-file.js +33 -0
  70. package/lib/fs/static-yaml-file.d.ts +11 -8
  71. package/lib/fs/static-yaml-file.js +3 -2
  72. package/lib/internal/{providers.d.ts → docs/providers.d.ts} +14 -4
  73. package/lib/internal/docs/providers.js +196 -0
  74. package/lib/secret.d.ts +3 -0
  75. package/lib/secret.js +13 -0
  76. package/lib/{util/serde.d.ts → serde.d.ts} +1 -1
  77. package/lib/{util/serde.js → serde.js} +12 -4
  78. package/lib/test/bun.js +3 -2
  79. package/lib/util/sha256.d.ts +1 -0
  80. package/lib/util/sha256.js +4 -0
  81. package/lib/web/vitepress/config.d.ts +11 -0
  82. package/lib/web/vitepress/config.js +32 -0
  83. package/lib/web/vitepress/home-page.d.ts +5 -3
  84. package/lib/web/vitepress/home-page.js +48 -35
  85. package/lib/web/vitepress/index.d.ts +2 -0
  86. package/lib/web/vitepress/index.js +2 -0
  87. package/lib/web/vitepress/process-front-matter-files.d.ts +18 -0
  88. package/lib/web/vitepress/process-front-matter-files.js +68 -0
  89. package/lib/web/vitepress/vitepress.d.ts +5 -4
  90. package/lib/web/vitepress/vitepress.js +20 -36
  91. package/package.json +8 -4
  92. package/src/ai/astro-file.ts +11 -30
  93. package/src/ai/client.ts +59 -0
  94. package/src/ai/css-file.ts +11 -30
  95. package/src/ai/data.ts +50 -25
  96. package/src/ai/document.ts +171 -66
  97. package/src/ai/html-file.ts +11 -30
  98. package/src/ai/json-file.ts +13 -37
  99. package/src/ai/typescript-file.ts +14 -48
  100. package/src/ai/vue-file.ts +11 -30
  101. package/src/ai/yaml-file.ts +13 -53
  102. package/src/alchemy.ts +74 -9
  103. package/src/apply.ts +27 -26
  104. package/src/aws/account-id.ts +6 -2
  105. package/src/aws/credentials.ts +6 -0
  106. package/src/aws/oidc/oidc-provider.ts +17 -17
  107. package/src/aws/role.ts +68 -54
  108. package/src/cloudflare/account-api-token.ts +365 -0
  109. package/src/cloudflare/account-id.ts +0 -0
  110. package/src/cloudflare/api.ts +88 -17
  111. package/src/cloudflare/bucket.ts +493 -133
  112. package/src/cloudflare/custom-domain.ts +318 -0
  113. package/src/cloudflare/{dns.ts → dns-records.ts} +36 -22
  114. package/src/cloudflare/generate-asset-manifest.ts +4 -4
  115. package/src/cloudflare/index.ts +5 -1
  116. package/src/cloudflare/permission-groups.ts +137 -0
  117. package/src/cloudflare/r2-rest-state-store.ts +14 -13
  118. package/src/cloudflare/static-site-router.ts +18 -8
  119. package/src/cloudflare/static-site.ts +27 -35
  120. package/src/cloudflare/upload-asset-manifest.ts +6 -4
  121. package/src/cloudflare/worker.ts +44 -43
  122. package/src/dns/import-dns.ts +4 -4
  123. package/src/{util/encrypt.ts → encrypt.ts} +7 -10
  124. package/src/fs/copy-file.ts +115 -0
  125. package/src/fs/file-system-state-store.ts +5 -5
  126. package/src/fs/file.ts +64 -9
  127. package/src/fs/index.ts +6 -0
  128. package/src/fs/static-astro-file.ts +45 -0
  129. package/src/fs/static-css-file.ts +35 -0
  130. package/src/fs/static-html-file.ts +42 -0
  131. package/src/fs/static-json-file.ts +4 -3
  132. package/src/fs/static-text-file.ts +5 -2
  133. package/src/fs/static-typescript-file.ts +4 -3
  134. package/src/fs/static-vue-file.ts +39 -0
  135. package/src/fs/static-yaml-file.ts +13 -9
  136. package/src/internal/docs/providers.ts +281 -0
  137. package/src/secret.ts +16 -0
  138. package/src/{util/serde.ts → serde.ts} +16 -10
  139. package/src/test/bun.ts +8 -7
  140. package/src/util/sha256.ts +5 -0
  141. package/src/web/vitepress/config.ts +50 -0
  142. package/src/web/vitepress/home-page.ts +54 -42
  143. package/src/web/vitepress/index.ts +2 -0
  144. package/src/web/vitepress/process-front-matter-files.ts +98 -0
  145. package/src/web/vitepress/vitepress.ts +34 -50
  146. package/lib/internal/getting-started.d.ts +0 -10
  147. package/lib/internal/getting-started.js +0 -94
  148. package/lib/internal/project.d.ts +0 -13
  149. package/lib/internal/project.js +0 -101
  150. package/lib/internal/providers.js +0 -148
  151. package/src/internal/getting-started.ts +0 -107
  152. package/src/internal/project.ts +0 -119
  153. package/src/internal/providers.ts +0 -209
  154. /package/lib/cloudflare/{dns.d.ts → dns-records.d.ts} +0 -0
@@ -9,7 +9,7 @@ import {
9
9
  } from "@aws-sdk/client-iam";
10
10
  import type { Context } from "../../context";
11
11
  import { Resource } from "../../resource";
12
- import { getAccountId } from "../account-id";
12
+ import { AccountId } from "../account-id";
13
13
 
14
14
  /**
15
15
  * Properties for configuring an AWS OIDC provider for GitHub Actions
@@ -121,7 +121,7 @@ export const OIDCProvider = Resource(
121
121
  async function (
122
122
  this: Context<OIDCProvider>,
123
123
  id: string,
124
- props: OIDCProviderProps,
124
+ props: OIDCProviderProps
125
125
  ) {
126
126
  // Initialize AWS SDK client
127
127
  const client = new IAMClient({
@@ -135,24 +135,24 @@ export const OIDCProvider = Resource(
135
135
  const getRole = await client.send(
136
136
  new GetRoleCommand({
137
137
  RoleName: props.roleArn.split("/").pop(),
138
- }),
138
+ })
139
139
  );
140
140
 
141
141
  if (getRole.Role?.AssumeRolePolicyDocument) {
142
142
  const policy = JSON.parse(
143
- decodeURIComponent(getRole.Role.AssumeRolePolicyDocument),
143
+ decodeURIComponent(getRole.Role.AssumeRolePolicyDocument)
144
144
  );
145
145
 
146
146
  // Remove our specific statement while preserving others
147
147
  policy.Statement = policy.Statement.filter(
148
- (stmt: any) => stmt.Sid !== TRUST_POLICY_SID,
148
+ (stmt: any) => stmt.Sid !== TRUST_POLICY_SID
149
149
  );
150
150
 
151
151
  await client.send(
152
152
  new UpdateAssumeRolePolicyCommand({
153
153
  RoleName: props.roleArn.split("/").pop(),
154
154
  PolicyDocument: JSON.stringify(policy),
155
- }),
155
+ })
156
156
  );
157
157
  }
158
158
 
@@ -160,7 +160,7 @@ export const OIDCProvider = Resource(
160
160
  const provider = await client.send(
161
161
  new GetOpenIDConnectProviderCommand({
162
162
  OpenIDConnectProviderArn: this.output.providerArn,
163
- }),
163
+ })
164
164
  );
165
165
 
166
166
  // Only delete the provider if it exists and has no other tags
@@ -168,7 +168,7 @@ export const OIDCProvider = Resource(
168
168
  await client.send(
169
169
  new DeleteOpenIDConnectProviderCommand({
170
170
  OpenIDConnectProviderArn: this.output.providerArn,
171
- }),
171
+ })
172
172
  );
173
173
  }
174
174
  } catch (error) {
@@ -197,13 +197,13 @@ export const OIDCProvider = Resource(
197
197
  Value: "alchemy",
198
198
  },
199
199
  ] as Tag[],
200
- }),
200
+ })
201
201
  );
202
202
  providerArn = createProvider.OpenIDConnectProviderArn!;
203
203
  } catch (error: any) {
204
204
  if (error.name === "EntityAlreadyExistsException") {
205
205
  // Provider exists, use its ARN
206
- providerArn = `arn:aws:iam::${await getAccountId()}:oidc-provider/${url}`;
206
+ providerArn = `arn:aws:iam::${await AccountId()}:oidc-provider/${url}`;
207
207
  } else {
208
208
  throw error;
209
209
  }
@@ -213,13 +213,13 @@ export const OIDCProvider = Resource(
213
213
  const getRole = await client.send(
214
214
  new GetRoleCommand({
215
215
  RoleName: props.roleArn.split("/").pop(),
216
- }),
216
+ })
217
217
  );
218
218
 
219
219
  let policy: any;
220
220
  if (getRole.Role?.AssumeRolePolicyDocument) {
221
221
  policy = JSON.parse(
222
- decodeURIComponent(getRole.Role.AssumeRolePolicyDocument),
222
+ decodeURIComponent(getRole.Role.AssumeRolePolicyDocument)
223
223
  );
224
224
  } else {
225
225
  policy = {
@@ -240,7 +240,7 @@ export const OIDCProvider = Resource(
240
240
  conditions.StringEquals["token.actions.githubusercontent.com:sub"] =
241
241
  props.branches.map(
242
242
  (branch) =>
243
- `repo:${props.owner}/${props.repository}:ref:refs/heads/${branch}`,
243
+ `repo:${props.owner}/${props.repository}:ref:refs/heads/${branch}`
244
244
  );
245
245
  }
246
246
 
@@ -248,7 +248,7 @@ export const OIDCProvider = Resource(
248
248
  conditions.StringEquals["token.actions.githubusercontent.com:sub"] =
249
249
  props.environments.map(
250
250
  (env) =>
251
- `repo:${props.owner}/${props.repository}:environment:${env}`,
251
+ `repo:${props.owner}/${props.repository}:environment:${env}`
252
252
  );
253
253
  }
254
254
 
@@ -266,7 +266,7 @@ export const OIDCProvider = Resource(
266
266
  // Remove any existing statement with our SID and add the new one
267
267
  policy.Statement = [
268
268
  ...policy.Statement.filter(
269
- (stmt: any) => stmt.Sid !== TRUST_POLICY_SID,
269
+ (stmt: any) => stmt.Sid !== TRUST_POLICY_SID
270
270
  ),
271
271
  ourStatement,
272
272
  ];
@@ -276,7 +276,7 @@ export const OIDCProvider = Resource(
276
276
  new UpdateAssumeRolePolicyCommand({
277
277
  RoleName: props.roleArn.split("/").pop(),
278
278
  PolicyDocument: JSON.stringify(policy),
279
- }),
279
+ })
280
280
  );
281
281
 
282
282
  return this({
@@ -288,5 +288,5 @@ export const OIDCProvider = Resource(
288
288
  console.error("Error configuring OIDC provider:", error);
289
289
  throw error;
290
290
  }
291
- },
291
+ }
292
292
  );
package/src/aws/role.ts CHANGED
@@ -219,58 +219,72 @@ export const Role = Resource(
219
219
  async function (
220
220
  this: Context<Role>,
221
221
  id: string,
222
- props: RoleProps,
222
+ props: RoleProps
223
223
  ): Promise<Role> {
224
224
  const client = new IAMClient({});
225
225
 
226
226
  if (this.phase === "delete") {
227
- // Delete any inline policies first
228
- if (props.policies) {
229
- for (const policy of props.policies) {
230
- await ignore(NoSuchEntityException.name, () =>
231
- client.send(
232
- new DeleteRolePolicyCommand({
233
- RoleName: props.roleName,
234
- PolicyName: policy.policyName,
235
- }),
236
- ),
237
- );
238
- }
239
- }
240
-
241
- // We need to detach managed policies before deleting the role
242
- // First, get all attached policies
243
227
  try {
244
- const attachedPoliciesResponse = await client.send(
245
- new ListAttachedRolePoliciesCommand({
246
- RoleName: props.roleName,
247
- }),
248
- );
228
+ // Delete any inline policies first
229
+ if (props.policies) {
230
+ for (const policy of props.policies) {
231
+ await ignore(NoSuchEntityException.name, () =>
232
+ client.send(
233
+ new DeleteRolePolicyCommand({
234
+ RoleName: props.roleName,
235
+ PolicyName: policy.policyName,
236
+ })
237
+ )
238
+ );
239
+ }
240
+ }
249
241
 
250
- // Detach all managed policies
251
- const attachedPolicies =
252
- attachedPoliciesResponse.AttachedPolicies || [];
253
- for (const policy of attachedPolicies) {
254
- await client.send(
255
- new DetachRolePolicyCommand({
242
+ // We need to detach managed policies before deleting the role
243
+ // First, get all attached policies
244
+ try {
245
+ const attachedPoliciesResponse = await client.send(
246
+ new ListAttachedRolePoliciesCommand({
256
247
  RoleName: props.roleName,
257
- PolicyArn: policy.PolicyArn!,
258
- }),
248
+ })
259
249
  );
250
+
251
+ // Detach all managed policies
252
+ const attachedPolicies =
253
+ attachedPoliciesResponse.AttachedPolicies || [];
254
+ for (const policy of attachedPolicies) {
255
+ await ignore(NoSuchEntityException.name, () =>
256
+ client.send(
257
+ new DetachRolePolicyCommand({
258
+ RoleName: props.roleName,
259
+ PolicyArn: policy.PolicyArn!,
260
+ })
261
+ )
262
+ );
263
+ }
264
+ } catch (error: any) {
265
+ if (error.name !== NoSuchEntityException.name) {
266
+ throw error;
267
+ }
268
+ // Role doesn't exist, no need to continue with detaching policies
260
269
  }
270
+
271
+ // Try to delete the role, ignoring if it doesn't exist
272
+ await ignore(NoSuchEntityException.name, () =>
273
+ client.send(
274
+ new DeleteRoleCommand({
275
+ RoleName: props.roleName,
276
+ })
277
+ )
278
+ );
261
279
  } catch (error: any) {
280
+ // If we get any other error besides NoSuchEntityException, log it but don't fail
281
+ // This ensures the resource is still marked as destroyed
262
282
  if (error.name !== NoSuchEntityException.name) {
263
- throw error;
283
+ console.error(`Error deleting role ${props.roleName}:`, error);
264
284
  }
265
285
  }
266
286
 
267
- await ignore(NoSuchEntityException.name, () =>
268
- client.send(
269
- new DeleteRoleCommand({
270
- RoleName: props.roleName,
271
- }),
272
- ),
273
- );
287
+ // Always return destroyed state regardless of any errors
274
288
  return this.destroy();
275
289
  }
276
290
 
@@ -302,7 +316,7 @@ export const Role = Resource(
302
316
  Value: this.id,
303
317
  },
304
318
  ],
305
- }),
319
+ })
306
320
  );
307
321
  }
308
322
  } catch (error: any) {
@@ -314,7 +328,7 @@ export const Role = Resource(
314
328
  const existingRole = await client.send(
315
329
  new GetRoleCommand({
316
330
  RoleName: props.roleName,
317
- }),
331
+ })
318
332
  );
319
333
  const roleTags =
320
334
  existingRole.Role?.Tags?.reduce(
@@ -322,7 +336,7 @@ export const Role = Resource(
322
336
  acc[tag.Key!] = tag.Value!;
323
337
  return acc;
324
338
  },
325
- {} as Record<string, string>,
339
+ {} as Record<string, string>
326
340
  ) || {};
327
341
 
328
342
  if (
@@ -340,7 +354,7 @@ export const Role = Resource(
340
354
  role = await client.send(
341
355
  new GetRoleCommand({
342
356
  RoleName: props.roleName,
343
- }),
357
+ })
344
358
  );
345
359
 
346
360
  // Update assume role policy if it changed
@@ -349,7 +363,7 @@ export const Role = Resource(
349
363
  new UpdateAssumeRolePolicyCommand({
350
364
  RoleName: props.roleName,
351
365
  PolicyDocument: assumeRolePolicyDocument,
352
- }),
366
+ })
353
367
  );
354
368
  }
355
369
 
@@ -363,7 +377,7 @@ export const Role = Resource(
363
377
  RoleName: props.roleName,
364
378
  Description: props.description,
365
379
  MaxSessionDuration: props.maxSessionDuration,
366
- }),
380
+ })
367
381
  );
368
382
  }
369
383
 
@@ -381,7 +395,7 @@ export const Role = Resource(
381
395
  new TagRoleCommand({
382
396
  RoleName: props.roleName,
383
397
  Tags: tags,
384
- }),
398
+ })
385
399
  );
386
400
 
387
401
  // Handle policy changes
@@ -393,7 +407,7 @@ export const Role = Resource(
393
407
  for (const oldPolicy of previousPolicies) {
394
408
  if (
395
409
  !currentPolicies.some(
396
- (p: { policyName: string }) => p.policyName === oldPolicy.policyName,
410
+ (p: { policyName: string }) => p.policyName === oldPolicy.policyName
397
411
  )
398
412
  ) {
399
413
  await ignore(NoSuchEntityException.name, () =>
@@ -401,8 +415,8 @@ export const Role = Resource(
401
415
  new DeleteRolePolicyCommand({
402
416
  RoleName: props.roleName,
403
417
  PolicyName: oldPolicy.policyName,
404
- }),
405
- ),
418
+ })
419
+ )
406
420
  );
407
421
  }
408
422
  }
@@ -410,7 +424,7 @@ export const Role = Resource(
410
424
  // Update or create policies
411
425
  for (const policy of currentPolicies) {
412
426
  const oldPolicy = previousPolicies.find(
413
- (p) => p.policyName === policy.policyName,
427
+ (p) => p.policyName === policy.policyName
414
428
  );
415
429
  if (
416
430
  !oldPolicy ||
@@ -422,7 +436,7 @@ export const Role = Resource(
422
436
  RoleName: props.roleName,
423
437
  PolicyName: policy.policyName,
424
438
  PolicyDocument: JSON.stringify(policy.policyDocument),
425
- }),
439
+ })
426
440
  );
427
441
  }
428
442
  }
@@ -432,7 +446,7 @@ export const Role = Resource(
432
446
  const attachedPoliciesResponse = await client.send(
433
447
  new ListAttachedRolePoliciesCommand({
434
448
  RoleName: props.roleName,
435
- }),
449
+ })
436
450
  );
437
451
 
438
452
  const currentAttachedPolicies =
@@ -450,7 +464,7 @@ export const Role = Resource(
450
464
  new DetachRolePolicyCommand({
451
465
  RoleName: props.roleName,
452
466
  PolicyArn: policyArn,
453
- }),
467
+ })
454
468
  );
455
469
  }
456
470
  }
@@ -462,7 +476,7 @@ export const Role = Resource(
462
476
  new AttachRolePolicyCommand({
463
477
  RoleName: props.roleName,
464
478
  PolicyArn: policyArn,
465
- }),
479
+ })
466
480
  );
467
481
  }
468
482
  }
@@ -479,5 +493,5 @@ export const Role = Resource(
479
493
  roleName: role.Role.RoleName ?? props.roleName,
480
494
  createDate: role.Role.CreateDate!,
481
495
  });
482
- },
496
+ }
483
497
  );