alchemy 0.22.4 → 0.23.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 (160) hide show
  1. package/lib/aws/bucket.d.ts.map +1 -1
  2. package/lib/aws/bucket.js +13 -12
  3. package/lib/aws/bucket.js.map +1 -1
  4. package/lib/aws/control/client.d.ts.map +1 -1
  5. package/lib/aws/control/client.js +5 -3
  6. package/lib/aws/control/client.js.map +1 -1
  7. package/lib/aws/control/resource.d.ts.map +1 -1
  8. package/lib/aws/control/resource.js +13 -4
  9. package/lib/aws/control/resource.js.map +1 -1
  10. package/lib/aws/control/types.d.ts +85129 -0
  11. package/lib/aws/function.d.ts.map +1 -1
  12. package/lib/aws/function.js +51 -42
  13. package/lib/aws/function.js.map +1 -1
  14. package/lib/aws/index.d.ts +1 -0
  15. package/lib/aws/index.d.ts.map +1 -1
  16. package/lib/aws/index.js +1 -0
  17. package/lib/aws/index.js.map +1 -1
  18. package/lib/aws/policy-attachment.d.ts.map +1 -1
  19. package/lib/aws/policy-attachment.js +5 -4
  20. package/lib/aws/policy-attachment.js.map +1 -1
  21. package/lib/aws/policy.d.ts.map +1 -1
  22. package/lib/aws/policy.js +21 -20
  23. package/lib/aws/policy.js.map +1 -1
  24. package/lib/aws/queue.d.ts.map +1 -1
  25. package/lib/aws/queue.js +19 -15
  26. package/lib/aws/queue.js.map +1 -1
  27. package/lib/aws/retry.d.ts +5 -0
  28. package/lib/aws/retry.d.ts.map +1 -0
  29. package/lib/aws/retry.js +27 -0
  30. package/lib/aws/retry.js.map +1 -0
  31. package/lib/aws/role.d.ts.map +1 -1
  32. package/lib/aws/role.js +31 -30
  33. package/lib/aws/role.js.map +1 -1
  34. package/lib/aws/ses.d.ts.map +1 -1
  35. package/lib/aws/ses.js +27 -26
  36. package/lib/aws/ses.js.map +1 -1
  37. package/lib/aws/ssm-parameter.d.ts +150 -0
  38. package/lib/aws/ssm-parameter.d.ts.map +1 -0
  39. package/lib/aws/ssm-parameter.js +184 -0
  40. package/lib/aws/ssm-parameter.js.map +1 -0
  41. package/lib/aws/table.d.ts.map +1 -1
  42. package/lib/aws/table.js +9 -27
  43. package/lib/aws/table.js.map +1 -1
  44. package/lib/cloudflare/account-id.d.ts +1 -0
  45. package/lib/cloudflare/account-id.d.ts.map +1 -1
  46. package/lib/cloudflare/account-id.js.map +1 -1
  47. package/lib/cloudflare/api.d.ts.map +1 -1
  48. package/lib/cloudflare/api.js +22 -2
  49. package/lib/cloudflare/api.js.map +1 -1
  50. package/lib/cloudflare/index.d.ts +2 -1
  51. package/lib/cloudflare/index.d.ts.map +1 -1
  52. package/lib/cloudflare/index.js +2 -1
  53. package/lib/cloudflare/index.js.map +1 -1
  54. package/lib/cloudflare/queue.d.ts.map +1 -1
  55. package/lib/cloudflare/queue.js +1 -0
  56. package/lib/cloudflare/queue.js.map +1 -1
  57. package/lib/cloudflare/route.d.ts +7 -0
  58. package/lib/cloudflare/route.d.ts.map +1 -1
  59. package/lib/cloudflare/route.js +44 -2
  60. package/lib/cloudflare/route.js.map +1 -1
  61. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  62. package/lib/cloudflare/worker-metadata.js +1 -2
  63. package/lib/cloudflare/worker-metadata.js.map +1 -1
  64. package/lib/cloudflare/worker.d.ts +2 -1
  65. package/lib/cloudflare/worker.d.ts.map +1 -1
  66. package/lib/cloudflare/worker.js +17 -8
  67. package/lib/cloudflare/worker.js.map +1 -1
  68. package/lib/cloudflare/workflow.d.ts +7 -0
  69. package/lib/cloudflare/workflow.d.ts.map +1 -1
  70. package/lib/cloudflare/workflow.js +2 -0
  71. package/lib/cloudflare/workflow.js.map +1 -1
  72. package/lib/cloudflare/wrangler.json.d.ts +1 -0
  73. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  74. package/lib/cloudflare/wrangler.json.js +1 -0
  75. package/lib/cloudflare/wrangler.json.js.map +1 -1
  76. package/lib/destroy.js +1 -1
  77. package/lib/destroy.js.map +1 -1
  78. package/lib/dns/godaddy.d.ts.map +1 -1
  79. package/lib/dns/godaddy.js +2 -1
  80. package/lib/dns/godaddy.js.map +1 -1
  81. package/lib/fs/file-system-state-store.d.ts.map +1 -1
  82. package/lib/fs/file-system-state-store.js +14 -2
  83. package/lib/fs/file-system-state-store.js.map +1 -1
  84. package/lib/github/secret.d.ts.map +1 -1
  85. package/lib/github/secret.js +1 -0
  86. package/lib/github/secret.js.map +1 -1
  87. package/lib/neon/api.d.ts.map +1 -1
  88. package/lib/neon/api.js +2 -1
  89. package/lib/neon/api.js.map +1 -1
  90. package/lib/runtime/shims.d.ts +6 -0
  91. package/lib/runtime/shims.d.ts.map +1 -0
  92. package/lib/runtime/shims.js +27 -0
  93. package/lib/runtime/shims.js.map +1 -0
  94. package/lib/sentry/api.d.ts.map +1 -1
  95. package/lib/sentry/api.js +2 -1
  96. package/lib/sentry/api.js.map +1 -1
  97. package/lib/test/bun.d.ts.map +1 -1
  98. package/lib/test/bun.js +1 -7
  99. package/lib/test/bun.js.map +1 -1
  100. package/lib/test/prune.d.ts +2 -1
  101. package/lib/test/prune.d.ts.map +1 -1
  102. package/lib/test/prune.js +29 -5
  103. package/lib/test/prune.js.map +1 -1
  104. package/lib/test/vitest.d.ts +92 -0
  105. package/lib/test/vitest.d.ts.map +1 -0
  106. package/lib/test/vitest.js +94 -0
  107. package/lib/test/vitest.js.map +1 -0
  108. package/lib/upstash/api.d.ts.map +1 -1
  109. package/lib/upstash/api.js +2 -1
  110. package/lib/upstash/api.js.map +1 -1
  111. package/lib/util/retry.js +2 -2
  112. package/lib/util/retry.js.map +1 -1
  113. package/lib/util/safe-fetch.d.ts +2 -0
  114. package/lib/util/safe-fetch.d.ts.map +1 -0
  115. package/lib/util/safe-fetch.js +48 -0
  116. package/lib/util/safe-fetch.js.map +1 -0
  117. package/lib/vercel/api.d.ts.map +1 -1
  118. package/lib/vercel/api.js +2 -1
  119. package/lib/vercel/api.js.map +1 -1
  120. package/lib/web/vitepress/process-front-matter-files.d.ts.map +1 -1
  121. package/lib/web/vitepress/process-front-matter-files.js +11 -7
  122. package/lib/web/vitepress/process-front-matter-files.js.map +1 -1
  123. package/package.json +10 -6
  124. package/src/alchemy.ts +2 -2
  125. package/src/aws/bucket.ts +55 -36
  126. package/src/aws/control/client.ts +13 -13
  127. package/src/aws/control/resource.ts +19 -3
  128. package/src/aws/function.ts +233 -178
  129. package/src/aws/index.ts +1 -0
  130. package/src/aws/policy-attachment.ts +15 -10
  131. package/src/aws/policy.ts +75 -54
  132. package/src/aws/queue.ts +53 -36
  133. package/src/aws/retry.ts +38 -0
  134. package/src/aws/role.ts +121 -90
  135. package/src/aws/ses.ts +101 -73
  136. package/src/aws/ssm-parameter.ts +315 -0
  137. package/src/aws/table.ts +61 -90
  138. package/src/cloudflare/account-id.ts +2 -0
  139. package/src/cloudflare/api.ts +26 -3
  140. package/src/cloudflare/index.ts +2 -1
  141. package/src/cloudflare/queue.ts +2 -0
  142. package/src/cloudflare/route.ts +86 -2
  143. package/src/cloudflare/worker-metadata.ts +1 -2
  144. package/src/cloudflare/worker.ts +21 -9
  145. package/src/cloudflare/workflow.ts +8 -0
  146. package/src/cloudflare/wrangler.json.ts +8 -1
  147. package/src/destroy.ts +1 -1
  148. package/src/dns/godaddy.ts +3 -1
  149. package/src/fs/file-system-state-store.ts +16 -2
  150. package/src/github/secret.ts +2 -0
  151. package/src/neon/api.ts +2 -1
  152. package/src/sentry/api.ts +2 -1
  153. package/src/test/bun.ts +1 -7
  154. package/src/test/prune.ts +31 -4
  155. package/src/test/vitest.ts +209 -0
  156. package/src/upstash/api.ts +2 -1
  157. package/src/util/retry.ts +3 -3
  158. package/src/util/safe-fetch.ts +61 -0
  159. package/src/vercel/api.ts +2 -1
  160. package/src/web/vitepress/process-front-matter-files.ts +15 -7
package/src/aws/role.ts CHANGED
@@ -19,6 +19,7 @@ import type { Context } from "../context.ts";
19
19
  import { Resource } from "../resource.ts";
20
20
  import { ignore } from "../util/ignore.ts";
21
21
  import type { PolicyDocument } from "./policy.ts";
22
+ import { retry } from "./retry.ts";
22
23
 
23
24
  /**
24
25
  * Properties for creating or updating an IAM role
@@ -229,11 +230,13 @@ export const Role = Resource(
229
230
  if (props.policies) {
230
231
  for (const policy of props.policies) {
231
232
  await ignore(NoSuchEntityException.name, () =>
232
- client.send(
233
- new DeleteRolePolicyCommand({
234
- RoleName: props.roleName,
235
- PolicyName: policy.policyName,
236
- }),
233
+ retry(() =>
234
+ client.send(
235
+ new DeleteRolePolicyCommand({
236
+ RoleName: props.roleName,
237
+ PolicyName: policy.policyName,
238
+ }),
239
+ ),
237
240
  ),
238
241
  );
239
242
  }
@@ -242,10 +245,12 @@ export const Role = Resource(
242
245
  // We need to detach managed policies before deleting the role
243
246
  // First, get all attached policies
244
247
  try {
245
- const attachedPoliciesResponse = await client.send(
246
- new ListAttachedRolePoliciesCommand({
247
- RoleName: props.roleName,
248
- }),
248
+ const attachedPoliciesResponse = await retry(() =>
249
+ client.send(
250
+ new ListAttachedRolePoliciesCommand({
251
+ RoleName: props.roleName,
252
+ }),
253
+ ),
249
254
  );
250
255
 
251
256
  // Detach all managed policies
@@ -253,11 +258,13 @@ export const Role = Resource(
253
258
  attachedPoliciesResponse.AttachedPolicies || [];
254
259
  for (const policy of attachedPolicies) {
255
260
  await ignore(NoSuchEntityException.name, () =>
256
- client.send(
257
- new DetachRolePolicyCommand({
258
- RoleName: props.roleName,
259
- PolicyArn: policy.PolicyArn!,
260
- }),
261
+ retry(() =>
262
+ client.send(
263
+ new DetachRolePolicyCommand({
264
+ RoleName: props.roleName,
265
+ PolicyArn: policy.PolicyArn!,
266
+ }),
267
+ ),
261
268
  ),
262
269
  );
263
270
  }
@@ -270,10 +277,12 @@ export const Role = Resource(
270
277
 
271
278
  // Try to delete the role, ignoring if it doesn't exist
272
279
  await ignore(NoSuchEntityException.name, () =>
273
- client.send(
274
- new DeleteRoleCommand({
275
- RoleName: props.roleName,
276
- }),
280
+ retry(() =>
281
+ client.send(
282
+ new DeleteRoleCommand({
283
+ RoleName: props.roleName,
284
+ }),
285
+ ),
277
286
  ),
278
287
  );
279
288
  } catch (error: any) {
@@ -294,29 +303,31 @@ export const Role = Resource(
294
303
  try {
295
304
  if (this.phase === "create") {
296
305
  // Try to create the role
297
- await client.send(
298
- new CreateRoleCommand({
299
- RoleName: props.roleName,
300
- AssumeRolePolicyDocument: assumeRolePolicyDocument,
301
- Description: props.description,
302
- Path: props.path,
303
- MaxSessionDuration: props.maxSessionDuration,
304
- PermissionsBoundary: props.permissionsBoundary,
305
- Tags: [
306
- ...Object.entries(props.tags || {}).map(([Key, Value]) => ({
307
- Key,
308
- Value,
309
- })),
310
- {
311
- Key: "alchemy_stage",
312
- Value: this.stage,
313
- },
314
- {
315
- Key: "alchemy_resource",
316
- Value: this.id,
317
- },
318
- ],
319
- }),
306
+ await retry(() =>
307
+ client.send(
308
+ new CreateRoleCommand({
309
+ RoleName: props.roleName,
310
+ AssumeRolePolicyDocument: assumeRolePolicyDocument,
311
+ Description: props.description,
312
+ Path: props.path,
313
+ MaxSessionDuration: props.maxSessionDuration,
314
+ PermissionsBoundary: props.permissionsBoundary,
315
+ Tags: [
316
+ ...Object.entries(props.tags || {}).map(([Key, Value]) => ({
317
+ Key,
318
+ Value,
319
+ })),
320
+ {
321
+ Key: "alchemy_stage",
322
+ Value: this.stage,
323
+ },
324
+ {
325
+ Key: "alchemy_resource",
326
+ Value: this.id,
327
+ },
328
+ ],
329
+ }),
330
+ ),
320
331
  );
321
332
  }
322
333
  } catch (error: any) {
@@ -325,10 +336,12 @@ export const Role = Resource(
325
336
  this.phase === "create"
326
337
  ) {
327
338
  // Check if we were the ones who created it
328
- const existingRole = await client.send(
329
- new GetRoleCommand({
330
- RoleName: props.roleName,
331
- }),
339
+ const existingRole = await retry(() =>
340
+ client.send(
341
+ new GetRoleCommand({
342
+ RoleName: props.roleName,
343
+ }),
344
+ ),
332
345
  );
333
346
  const roleTags =
334
347
  existingRole.Role?.Tags?.reduce(
@@ -351,19 +364,23 @@ export const Role = Resource(
351
364
  }
352
365
 
353
366
  // Get or update the role
354
- role = await client.send(
355
- new GetRoleCommand({
356
- RoleName: props.roleName,
357
- }),
367
+ role = await retry(() =>
368
+ client.send(
369
+ new GetRoleCommand({
370
+ RoleName: props.roleName,
371
+ }),
372
+ ),
358
373
  );
359
374
 
360
375
  // Update assume role policy if it changed
361
376
  if (role.Role?.AssumeRolePolicyDocument !== assumeRolePolicyDocument) {
362
- await client.send(
363
- new UpdateAssumeRolePolicyCommand({
364
- RoleName: props.roleName,
365
- PolicyDocument: assumeRolePolicyDocument,
366
- }),
377
+ await retry(() =>
378
+ client.send(
379
+ new UpdateAssumeRolePolicyCommand({
380
+ RoleName: props.roleName,
381
+ PolicyDocument: assumeRolePolicyDocument,
382
+ }),
383
+ ),
367
384
  );
368
385
  }
369
386
 
@@ -372,12 +389,14 @@ export const Role = Resource(
372
389
  role.Role?.Description !== props.description ||
373
390
  role.Role?.MaxSessionDuration !== props.maxSessionDuration
374
391
  ) {
375
- await client.send(
376
- new UpdateRoleCommand({
377
- RoleName: props.roleName,
378
- Description: props.description,
379
- MaxSessionDuration: props.maxSessionDuration,
380
- }),
392
+ await retry(() =>
393
+ client.send(
394
+ new UpdateRoleCommand({
395
+ RoleName: props.roleName,
396
+ Description: props.description,
397
+ MaxSessionDuration: props.maxSessionDuration,
398
+ }),
399
+ ),
381
400
  );
382
401
  }
383
402
 
@@ -391,11 +410,13 @@ export const Role = Resource(
391
410
  Key,
392
411
  Value,
393
412
  }));
394
- await client.send(
395
- new TagRoleCommand({
396
- RoleName: props.roleName,
397
- Tags: tags,
398
- }),
413
+ await retry(() =>
414
+ client.send(
415
+ new TagRoleCommand({
416
+ RoleName: props.roleName,
417
+ Tags: tags,
418
+ }),
419
+ ),
399
420
  );
400
421
 
401
422
  // Handle policy changes
@@ -411,11 +432,13 @@ export const Role = Resource(
411
432
  )
412
433
  ) {
413
434
  await ignore(NoSuchEntityException.name, () =>
414
- client.send(
415
- new DeleteRolePolicyCommand({
416
- RoleName: props.roleName,
417
- PolicyName: oldPolicy.policyName,
418
- }),
435
+ retry(() =>
436
+ client.send(
437
+ new DeleteRolePolicyCommand({
438
+ RoleName: props.roleName,
439
+ PolicyName: oldPolicy.policyName,
440
+ }),
441
+ ),
419
442
  ),
420
443
  );
421
444
  }
@@ -431,22 +454,26 @@ export const Role = Resource(
431
454
  JSON.stringify(oldPolicy.policyDocument) !==
432
455
  JSON.stringify(policy.policyDocument)
433
456
  ) {
434
- await client.send(
435
- new PutRolePolicyCommand({
436
- RoleName: props.roleName,
437
- PolicyName: policy.policyName,
438
- PolicyDocument: JSON.stringify(policy.policyDocument),
439
- }),
457
+ await retry(() =>
458
+ client.send(
459
+ new PutRolePolicyCommand({
460
+ RoleName: props.roleName,
461
+ PolicyName: policy.policyName,
462
+ PolicyDocument: JSON.stringify(policy.policyDocument),
463
+ }),
464
+ ),
440
465
  );
441
466
  }
442
467
  }
443
468
 
444
469
  // Handle managed policy attachments
445
470
  // Get currently attached policies
446
- const attachedPoliciesResponse = await client.send(
447
- new ListAttachedRolePoliciesCommand({
448
- RoleName: props.roleName,
449
- }),
471
+ const attachedPoliciesResponse = await retry(() =>
472
+ client.send(
473
+ new ListAttachedRolePoliciesCommand({
474
+ RoleName: props.roleName,
475
+ }),
476
+ ),
450
477
  );
451
478
 
452
479
  const currentAttachedPolicies =
@@ -460,11 +487,13 @@ export const Role = Resource(
460
487
  // Detach policies that are no longer needed
461
488
  for (const policyArn of currentPolicyArns) {
462
489
  if (!desiredPolicyArns.includes(policyArn)) {
463
- await client.send(
464
- new DetachRolePolicyCommand({
465
- RoleName: props.roleName,
466
- PolicyArn: policyArn,
467
- }),
490
+ await retry(() =>
491
+ client.send(
492
+ new DetachRolePolicyCommand({
493
+ RoleName: props.roleName,
494
+ PolicyArn: policyArn,
495
+ }),
496
+ ),
468
497
  );
469
498
  }
470
499
  }
@@ -472,11 +501,13 @@ export const Role = Resource(
472
501
  // Attach new policies that weren't attached before
473
502
  for (const policyArn of desiredPolicyArns) {
474
503
  if (!currentPolicyArns.includes(policyArn)) {
475
- await client.send(
476
- new AttachRolePolicyCommand({
477
- RoleName: props.roleName,
478
- PolicyArn: policyArn,
479
- }),
504
+ await retry(() =>
505
+ client.send(
506
+ new AttachRolePolicyCommand({
507
+ RoleName: props.roleName,
508
+ PolicyArn: policyArn,
509
+ }),
510
+ ),
480
511
  );
481
512
  }
482
513
  }
package/src/aws/ses.ts CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  import type { Context } from "../context.ts";
23
23
  import { Resource } from "../resource.ts";
24
24
  import { ignore } from "../util/ignore.ts";
25
+ import { retry } from "./retry.ts";
25
26
 
26
27
  /**
27
28
  * Properties for configuring AWS SES resources
@@ -177,10 +178,12 @@ export const SES = Resource(
177
178
  // Delete configuration set if it exists
178
179
  if (output?.configurationSetName) {
179
180
  await ignore(NotFoundException.name, () =>
180
- client.send(
181
- new DeleteConfigurationSetCommand({
182
- ConfigurationSetName: output.configurationSetName,
183
- }),
181
+ retry(() =>
182
+ client.send(
183
+ new DeleteConfigurationSetCommand({
184
+ ConfigurationSetName: output.configurationSetName,
185
+ }),
186
+ ),
184
187
  ),
185
188
  );
186
189
  }
@@ -188,10 +191,12 @@ export const SES = Resource(
188
191
  // Delete email identity if it exists
189
192
  if (output?.emailIdentity) {
190
193
  await ignore(NotFoundException.name, () =>
191
- client.send(
192
- new DeleteEmailIdentityCommand({
193
- EmailIdentity: output.emailIdentity,
194
- }),
194
+ retry(() =>
195
+ client.send(
196
+ new DeleteEmailIdentityCommand({
197
+ EmailIdentity: output.emailIdentity,
198
+ }),
199
+ ),
195
200
  ),
196
201
  );
197
202
  }
@@ -211,10 +216,12 @@ export const SES = Resource(
211
216
  // Check if configuration set exists
212
217
  let configSetExists = false;
213
218
  try {
214
- await client.send(
215
- new GetConfigurationSetCommand({
216
- ConfigurationSetName: props.configurationSetName,
217
- }),
219
+ await retry(() =>
220
+ client.send(
221
+ new GetConfigurationSetCommand({
222
+ ConfigurationSetName: props.configurationSetName,
223
+ }),
224
+ ),
218
225
  );
219
226
  configSetExists = true;
220
227
  } catch (error) {
@@ -228,49 +235,60 @@ export const SES = Resource(
228
235
  if (configSetExists) {
229
236
  // Update existing configuration set using appropriate update commands
230
237
  if (props.sendingOptions) {
231
- await client.send(
232
- new PutConfigurationSetSendingOptionsCommand({
233
- ConfigurationSetName: props.configurationSetName,
234
- SendingEnabled: props.sendingOptions.SendingEnabled,
235
- }),
238
+ await retry(() =>
239
+ client.send(
240
+ new PutConfigurationSetSendingOptionsCommand({
241
+ ConfigurationSetName: props.configurationSetName,
242
+ SendingEnabled: props.sendingOptions!.SendingEnabled,
243
+ }),
244
+ ),
236
245
  );
237
246
  }
238
247
 
239
248
  if (props.reputationOptions) {
240
- await client.send(
241
- new PutConfigurationSetReputationOptionsCommand({
242
- ConfigurationSetName: props.configurationSetName,
243
- ReputationMetricsEnabled:
244
- props.reputationOptions.ReputationMetricsEnabled,
245
- }),
249
+ await retry(() =>
250
+ client.send(
251
+ new PutConfigurationSetReputationOptionsCommand({
252
+ ConfigurationSetName: props.configurationSetName,
253
+ ReputationMetricsEnabled:
254
+ props.reputationOptions!.ReputationMetricsEnabled,
255
+ }),
256
+ ),
246
257
  );
247
258
  }
248
259
 
249
260
  if (props.trackingOptions) {
250
- await client.send(
251
- new PutConfigurationSetTrackingOptionsCommand({
252
- ConfigurationSetName: props.configurationSetName,
253
- CustomRedirectDomain: props.trackingOptions.CustomRedirectDomain,
254
- }),
261
+ await retry(() =>
262
+ client.send(
263
+ new PutConfigurationSetTrackingOptionsCommand({
264
+ ConfigurationSetName: props.configurationSetName,
265
+ CustomRedirectDomain:
266
+ props.trackingOptions!.CustomRedirectDomain,
267
+ }),
268
+ ),
255
269
  );
256
270
  }
257
271
 
258
272
  if (props.suppressionOptions) {
259
- await client.send(
260
- new PutConfigurationSetSuppressionOptionsCommand({
261
- ConfigurationSetName: props.configurationSetName,
262
- SuppressedReasons: props.suppressionOptions.SuppressedReasons,
263
- }),
273
+ await retry(() =>
274
+ client.send(
275
+ new PutConfigurationSetSuppressionOptionsCommand({
276
+ ConfigurationSetName: props.configurationSetName,
277
+ SuppressedReasons: props.suppressionOptions!.SuppressedReasons,
278
+ }),
279
+ ),
264
280
  );
265
281
  }
266
282
 
267
283
  if (props.deliveryOptions) {
268
- await client.send(
269
- new PutConfigurationSetDeliveryOptionsCommand({
270
- ConfigurationSetName: props.configurationSetName,
271
- TlsPolicy: props.deliveryOptions.TlsPolicy,
272
- SendingPoolName: props.deliveryOptions.SendingPoolName,
273
- }),
284
+ await retry(() =>
285
+ client.send(
286
+ new PutConfigurationSetDeliveryOptionsCommand({
287
+ ConfigurationSetName: props.configurationSetName,
288
+ TlsPolicy: props.deliveryOptions!.TlsPolicy,
289
+ SendingPoolName: props.deliveryOptions!.SendingPoolName,
290
+ }),
291
+ ),
274
292
  );
275
293
  }
276
294
 
@@ -278,19 +296,21 @@ export const SES = Resource(
278
296
  configurationSetArn = `arn:aws:ses:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:configuration-set/${props.configurationSetName}`;
279
297
  } else {
280
298
  // Create new configuration set
281
- await client.send(
282
- new CreateConfigurationSetCommand({
283
- ConfigurationSetName: props.configurationSetName,
284
- SendingOptions: props.sendingOptions,
285
- ReputationOptions: props.reputationOptions,
286
- TrackingOptions: props.trackingOptions,
287
- SuppressionOptions: props.suppressionOptions,
288
- DeliveryOptions: props.deliveryOptions,
289
- Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
290
- Key,
291
- Value,
292
- })),
293
- }),
299
+ await retry(() =>
300
+ client.send(
301
+ new CreateConfigurationSetCommand({
302
+ ConfigurationSetName: props.configurationSetName,
303
+ SendingOptions: props.sendingOptions,
304
+ ReputationOptions: props.reputationOptions,
305
+ TrackingOptions: props.trackingOptions,
306
+ SuppressionOptions: props.suppressionOptions,
307
+ DeliveryOptions: props.deliveryOptions,
308
+ Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
309
+ Key,
310
+ Value,
311
+ })),
312
+ }),
313
+ ),
294
314
  );
295
315
 
296
316
  // In SESv2, the ARN isn't directly returned in the response
@@ -303,10 +323,12 @@ export const SES = Resource(
303
323
  // Check if identity exists
304
324
  let getIdentityResult;
305
325
  try {
306
- getIdentityResult = await client.send(
307
- new GetEmailIdentityCommand({
308
- EmailIdentity: props.emailIdentity,
309
- }),
326
+ getIdentityResult = await retry(() =>
327
+ client.send(
328
+ new GetEmailIdentityCommand({
329
+ EmailIdentity: props.emailIdentity,
330
+ }),
331
+ ),
310
332
  );
311
333
  } catch (error) {
312
334
  if (error instanceof NotFoundException) {
@@ -318,14 +340,16 @@ export const SES = Resource(
318
340
 
319
341
  if (!getIdentityResult) {
320
342
  // Create new email identity
321
- const createIdentityResult = await client.send(
322
- new CreateEmailIdentityCommand({
323
- EmailIdentity: props.emailIdentity,
324
- Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
325
- Key,
326
- Value,
327
- })),
328
- }),
343
+ const createIdentityResult = await retry(() =>
344
+ client.send(
345
+ new CreateEmailIdentityCommand({
346
+ EmailIdentity: props.emailIdentity,
347
+ Tags: Object.entries(props.tags || {}).map(([Key, Value]) => ({
348
+ Key,
349
+ Value,
350
+ })),
351
+ }),
352
+ ),
329
353
  );
330
354
 
331
355
  // If it's an email address, we don't need to explicitly verify in v2
@@ -346,21 +370,25 @@ export const SES = Resource(
346
370
  // Update DKIM settings if requested
347
371
  if (props.enableDkim !== undefined) {
348
372
  if (props.enableDkim) {
349
- await client.send(
350
- new PutEmailIdentityDkimAttributesCommand({
351
- EmailIdentity: props.emailIdentity,
352
- SigningEnabled: true,
353
- }),
373
+ await retry(() =>
374
+ client.send(
375
+ new PutEmailIdentityDkimAttributesCommand({
376
+ EmailIdentity: props.emailIdentity,
377
+ SigningEnabled: true,
378
+ }),
379
+ ),
354
380
  );
355
381
 
356
382
  // We can check the current status of DKIM
357
383
  dkimVerificationStatus = "PENDING"; // Default to pending
358
384
 
359
385
  // Get the updated identity to check DKIM status
360
- const updatedIdentity = await client.send(
361
- new GetEmailIdentityCommand({
362
- EmailIdentity: props.emailIdentity,
363
- }),
386
+ const updatedIdentity = await retry(() =>
387
+ client.send(
388
+ new GetEmailIdentityCommand({
389
+ EmailIdentity: props.emailIdentity,
390
+ }),
391
+ ),
364
392
  );
365
393
 
366
394
  if (updatedIdentity.DkimAttributes?.Status) {