@wraps.dev/cli 2.11.7 → 2.11.8

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.
package/dist/cli.js CHANGED
@@ -825,8 +825,8 @@ async function isAWSCLIInstalled() {
825
825
  }
826
826
  async function getAWSCLIVersion() {
827
827
  try {
828
- const output4 = execSync("aws --version", { encoding: "utf-8" });
829
- const match = output4.match(/aws-cli\/(\d+\.\d+\.\d+)/);
828
+ const output3 = execSync("aws --version", { encoding: "utf-8" });
829
+ const match = output3.match(/aws-cli\/(\d+\.\d+\.\d+)/);
830
830
  return match ? match[1] : null;
831
831
  } catch {
832
832
  return null;
@@ -4467,10 +4467,10 @@ var init_metadata = __esm({
4467
4467
  async function roleExists(roleName) {
4468
4468
  try {
4469
4469
  const { IAMClient: IAMClient4, GetRoleCommand: GetRoleCommand3 } = await import("@aws-sdk/client-iam");
4470
- const iam10 = new IAMClient4({
4470
+ const iam9 = new IAMClient4({
4471
4471
  region: process.env.AWS_REGION || "us-east-1"
4472
4472
  });
4473
- await iam10.send(new GetRoleCommand3({ RoleName: roleName }));
4473
+ await iam9.send(new GetRoleCommand3({ RoleName: roleName }));
4474
4474
  return true;
4475
4475
  } catch (error) {
4476
4476
  if (error instanceof Error && (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity" || error.Error?.Code === "NoSuchEntity")) {
@@ -4760,7 +4760,7 @@ import { builtinModules } from "module";
4760
4760
  import { tmpdir } from "os";
4761
4761
  import { dirname as dirname2, join as join7 } from "path";
4762
4762
  import { fileURLToPath as fileURLToPath3 } from "url";
4763
- import * as aws8 from "@pulumi/aws";
4763
+ import * as aws7 from "@pulumi/aws";
4764
4764
  import * as pulumi11 from "@pulumi/pulumi";
4765
4765
  import { build } from "esbuild";
4766
4766
  function getPackageRoot() {
@@ -4835,7 +4835,7 @@ Try running: pnpm build`
4835
4835
  }
4836
4836
  async function deployLambdaFunctions(config2) {
4837
4837
  const eventProcessorCode = await getLambdaCode("event-processor");
4838
- const lambdaRole = new aws8.iam.Role("wraps-email-lambda-role", {
4838
+ const lambdaRole = new aws7.iam.Role("wraps-email-lambda-role", {
4839
4839
  assumeRolePolicy: JSON.stringify({
4840
4840
  Version: "2012-10-17",
4841
4841
  Statement: [
@@ -4850,11 +4850,11 @@ async function deployLambdaFunctions(config2) {
4850
4850
  ManagedBy: "wraps-cli"
4851
4851
  }
4852
4852
  });
4853
- new aws8.iam.RolePolicyAttachment("wraps-email-lambda-basic-execution", {
4853
+ new aws7.iam.RolePolicyAttachment("wraps-email-lambda-basic-execution", {
4854
4854
  role: lambdaRole.name,
4855
4855
  policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
4856
4856
  });
4857
- new aws8.iam.RolePolicy("wraps-email-lambda-policy", {
4857
+ new aws7.iam.RolePolicy("wraps-email-lambda-policy", {
4858
4858
  role: lambdaRole.name,
4859
4859
  policy: pulumi11.all([config2.tableName, config2.queueArn]).apply(
4860
4860
  ([tableName, queueArn]) => JSON.stringify({
@@ -4898,7 +4898,7 @@ async function deployLambdaFunctions(config2) {
4898
4898
  RETENTION_DAYS: config2.retentionDays.toString()
4899
4899
  }
4900
4900
  };
4901
- const eventProcessor = exists ? new aws8.lambda.Function(
4901
+ const eventProcessor = exists ? new aws7.lambda.Function(
4902
4902
  functionName,
4903
4903
  {
4904
4904
  name: functionName,
@@ -4919,7 +4919,7 @@ async function deployLambdaFunctions(config2) {
4919
4919
  import: functionName
4920
4920
  // Import existing function
4921
4921
  }
4922
- ) : new aws8.lambda.Function(functionName, {
4922
+ ) : new aws7.lambda.Function(functionName, {
4923
4923
  name: functionName,
4924
4924
  runtime: "nodejs24.x",
4925
4925
  handler: "index.handler",
@@ -4949,14 +4949,14 @@ async function deployLambdaFunctions(config2) {
4949
4949
  functionResponseTypes: ["ReportBatchItemFailures"]
4950
4950
  // Enable partial batch responses
4951
4951
  };
4952
- const eventSourceMapping = existingMappingUuid ? new aws8.lambda.EventSourceMapping(
4952
+ const eventSourceMapping = existingMappingUuid ? new aws7.lambda.EventSourceMapping(
4953
4953
  "wraps-email-event-source-mapping",
4954
4954
  mappingConfig,
4955
4955
  {
4956
4956
  import: existingMappingUuid
4957
4957
  // Import with the UUID
4958
4958
  }
4959
- ) : new aws8.lambda.EventSourceMapping(
4959
+ ) : new aws7.lambda.EventSourceMapping(
4960
4960
  "wraps-email-event-source-mapping",
4961
4961
  mappingConfig
4962
4962
  );
@@ -4982,7 +4982,7 @@ __export(acm_exports, {
4982
4982
  createACMCertificate: () => createACMCertificate
4983
4983
  });
4984
4984
  import { ACMClient as ACMClient2, DescribeCertificateCommand as DescribeCertificateCommand2 } from "@aws-sdk/client-acm";
4985
- import * as aws12 from "@pulumi/aws";
4985
+ import * as aws11 from "@pulumi/aws";
4986
4986
  async function checkCertificateValidation(domain) {
4987
4987
  try {
4988
4988
  const acm3 = new ACMClient2({ region: "us-east-1" });
@@ -5009,10 +5009,10 @@ async function checkCertificateValidation(domain) {
5009
5009
  }
5010
5010
  }
5011
5011
  async function createACMCertificate(config2) {
5012
- const usEast1Provider = new aws12.Provider("acm-us-east-1", {
5012
+ const usEast1Provider = new aws11.Provider("acm-us-east-1", {
5013
5013
  region: "us-east-1"
5014
5014
  });
5015
- const certificate = new aws12.acm.Certificate(
5015
+ const certificate = new aws11.acm.Certificate(
5016
5016
  "wraps-email-tracking-cert",
5017
5017
  {
5018
5018
  domainName: config2.domain,
@@ -5035,7 +5035,7 @@ async function createACMCertificate(config2) {
5035
5035
  );
5036
5036
  let certificateValidation;
5037
5037
  if (config2.hostedZoneId) {
5038
- const validationRecord = new aws12.route53.Record(
5038
+ const validationRecord = new aws11.route53.Record(
5039
5039
  "wraps-email-tracking-cert-validation",
5040
5040
  {
5041
5041
  zoneId: config2.hostedZoneId,
@@ -5045,7 +5045,7 @@ async function createACMCertificate(config2) {
5045
5045
  ttl: 60
5046
5046
  }
5047
5047
  );
5048
- certificateValidation = new aws12.acm.CertificateValidation(
5048
+ certificateValidation = new aws11.acm.CertificateValidation(
5049
5049
  "wraps-email-tracking-cert-validation-waiter",
5050
5050
  {
5051
5051
  certificateArn: certificate.arn,
@@ -5074,7 +5074,7 @@ var cloudfront_exports = {};
5074
5074
  __export(cloudfront_exports, {
5075
5075
  createCloudFrontTracking: () => createCloudFrontTracking
5076
5076
  });
5077
- import * as aws13 from "@pulumi/aws";
5077
+ import * as aws12 from "@pulumi/aws";
5078
5078
  async function findDistributionByAlias(alias) {
5079
5079
  try {
5080
5080
  const { CloudFrontClient, ListDistributionsCommand } = await import("@aws-sdk/client-cloudfront");
@@ -5090,10 +5090,10 @@ async function findDistributionByAlias(alias) {
5090
5090
  }
5091
5091
  }
5092
5092
  async function createWAFWebACL() {
5093
- const usEast1Provider = new aws13.Provider("waf-us-east-1", {
5093
+ const usEast1Provider = new aws12.Provider("waf-us-east-1", {
5094
5094
  region: "us-east-1"
5095
5095
  });
5096
- const webAcl = new aws13.wafv2.WebAcl(
5096
+ const webAcl = new aws12.wafv2.WebAcl(
5097
5097
  "wraps-email-tracking-waf",
5098
5098
  {
5099
5099
  scope: "CLOUDFRONT",
@@ -5208,14 +5208,14 @@ async function createCloudFrontTracking(config2) {
5208
5208
  Description: "Wraps email tracking CloudFront distribution"
5209
5209
  }
5210
5210
  };
5211
- const distribution = existingDistributionId ? new aws13.cloudfront.Distribution(
5211
+ const distribution = existingDistributionId ? new aws12.cloudfront.Distribution(
5212
5212
  "wraps-email-tracking-cdn",
5213
5213
  distributionConfig,
5214
5214
  {
5215
5215
  import: existingDistributionId
5216
5216
  // Import existing distribution
5217
5217
  }
5218
- ) : new aws13.cloudfront.Distribution(
5218
+ ) : new aws12.cloudfront.Distribution(
5219
5219
  "wraps-email-tracking-cdn",
5220
5220
  distributionConfig
5221
5221
  );
@@ -5396,10 +5396,10 @@ var s3_inbound_exports = {};
5396
5396
  __export(s3_inbound_exports, {
5397
5397
  createS3InboundResources: () => createS3InboundResources
5398
5398
  });
5399
- import * as aws14 from "@pulumi/aws";
5399
+ import * as aws13 from "@pulumi/aws";
5400
5400
  async function createS3InboundResources(config2) {
5401
5401
  const bucketName = `wraps-inbound-${config2.accountId}-${config2.region}`;
5402
- const bucket = new aws14.s3.BucketV2("wraps-inbound-bucket", {
5402
+ const bucket = new aws13.s3.BucketV2("wraps-inbound-bucket", {
5403
5403
  bucket: bucketName,
5404
5404
  forceDestroy: true,
5405
5405
  tags: {
@@ -5407,14 +5407,14 @@ async function createS3InboundResources(config2) {
5407
5407
  Service: "email-inbound"
5408
5408
  }
5409
5409
  });
5410
- new aws14.s3.BucketPublicAccessBlock("wraps-inbound-public-access-block", {
5410
+ new aws13.s3.BucketPublicAccessBlock("wraps-inbound-public-access-block", {
5411
5411
  bucket: bucket.id,
5412
5412
  blockPublicAcls: true,
5413
5413
  blockPublicPolicy: true,
5414
5414
  ignorePublicAcls: true,
5415
5415
  restrictPublicBuckets: true
5416
5416
  });
5417
- new aws14.s3.BucketServerSideEncryptionConfigurationV2(
5417
+ new aws13.s3.BucketServerSideEncryptionConfigurationV2(
5418
5418
  "wraps-inbound-encryption",
5419
5419
  {
5420
5420
  bucket: bucket.id,
@@ -5430,7 +5430,7 @@ async function createS3InboundResources(config2) {
5430
5430
  if (config2.retention) {
5431
5431
  const retentionDays = retentionToDays2(config2.retention);
5432
5432
  if (retentionDays > 0) {
5433
- new aws14.s3.BucketLifecycleConfigurationV2("wraps-inbound-lifecycle", {
5433
+ new aws13.s3.BucketLifecycleConfigurationV2("wraps-inbound-lifecycle", {
5434
5434
  bucket: bucket.id,
5435
5435
  rules: [
5436
5436
  {
@@ -5444,8 +5444,8 @@ async function createS3InboundResources(config2) {
5444
5444
  });
5445
5445
  }
5446
5446
  }
5447
- const identity = await aws14.getCallerIdentity();
5448
- new aws14.s3.BucketPolicy("wraps-inbound-bucket-policy", {
5447
+ const identity = await aws13.getCallerIdentity();
5448
+ new aws13.s3.BucketPolicy("wraps-inbound-bucket-policy", {
5449
5449
  bucket: bucket.id,
5450
5450
  policy: bucket.arn.apply(
5451
5451
  (arn) => JSON.stringify({
@@ -5487,9 +5487,9 @@ var sqs_inbound_exports = {};
5487
5487
  __export(sqs_inbound_exports, {
5488
5488
  createSQSInboundResources: () => createSQSInboundResources
5489
5489
  });
5490
- import * as aws15 from "@pulumi/aws";
5490
+ import * as aws14 from "@pulumi/aws";
5491
5491
  function createSQSInboundResources() {
5492
- const dlq = new aws15.sqs.Queue("wraps-inbound-events-dlq", {
5492
+ const dlq = new aws14.sqs.Queue("wraps-inbound-events-dlq", {
5493
5493
  name: "wraps-inbound-events-dlq",
5494
5494
  messageRetentionSeconds: 1209600,
5495
5495
  // 14 days
@@ -5499,7 +5499,7 @@ function createSQSInboundResources() {
5499
5499
  Description: "Dead letter queue for failed inbound email processing"
5500
5500
  }
5501
5501
  });
5502
- const queue = new aws15.sqs.Queue("wraps-inbound-events", {
5502
+ const queue = new aws14.sqs.Queue("wraps-inbound-events", {
5503
5503
  name: "wraps-inbound-events",
5504
5504
  visibilityTimeoutSeconds: 300,
5505
5505
  // Must be >= Lambda timeout (120s) * 2 + buffer
@@ -5536,11 +5536,11 @@ var lambda_inbound_exports = {};
5536
5536
  __export(lambda_inbound_exports, {
5537
5537
  deployInboundLambda: () => deployInboundLambda
5538
5538
  });
5539
- import * as aws16 from "@pulumi/aws";
5539
+ import * as aws15 from "@pulumi/aws";
5540
5540
  import * as pulumi12 from "@pulumi/pulumi";
5541
5541
  async function deployInboundLambda(config2) {
5542
5542
  const inboundProcessorCode = await getLambdaCode("inbound-processor");
5543
- const lambdaRole = new aws16.iam.Role("wraps-inbound-lambda-role", {
5543
+ const lambdaRole = new aws15.iam.Role("wraps-inbound-lambda-role", {
5544
5544
  name: "wraps-inbound-lambda-role",
5545
5545
  assumeRolePolicy: JSON.stringify({
5546
5546
  Version: "2012-10-17",
@@ -5557,11 +5557,11 @@ async function deployInboundLambda(config2) {
5557
5557
  Service: "email-inbound"
5558
5558
  }
5559
5559
  });
5560
- new aws16.iam.RolePolicyAttachment("wraps-inbound-lambda-basic-execution", {
5560
+ new aws15.iam.RolePolicyAttachment("wraps-inbound-lambda-basic-execution", {
5561
5561
  role: lambdaRole.name,
5562
5562
  policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
5563
5563
  });
5564
- new aws16.iam.RolePolicy("wraps-inbound-lambda-policy", {
5564
+ new aws15.iam.RolePolicy("wraps-inbound-lambda-policy", {
5565
5565
  role: lambdaRole.name,
5566
5566
  policy: pulumi12.all([config2.bucketArn, config2.dlqArn]).apply(
5567
5567
  ([bucketArn, dlqArn]) => JSON.stringify({
@@ -5590,7 +5590,7 @@ async function deployInboundLambda(config2) {
5590
5590
  )
5591
5591
  });
5592
5592
  const functionName = "wraps-inbound-email-processor";
5593
- const lambdaFunction = new aws16.lambda.Function(functionName, {
5593
+ const lambdaFunction = new aws15.lambda.Function(functionName, {
5594
5594
  name: functionName,
5595
5595
  runtime: "nodejs20.x",
5596
5596
  handler: "index.handler",
@@ -5612,7 +5612,7 @@ async function deployInboundLambda(config2) {
5612
5612
  Service: "email-inbound"
5613
5613
  }
5614
5614
  });
5615
- const s3InvokePermission = new aws16.lambda.Permission(
5615
+ const s3InvokePermission = new aws15.lambda.Permission(
5616
5616
  "wraps-inbound-s3-invoke",
5617
5617
  {
5618
5618
  action: "lambda:InvokeFunction",
@@ -5640,9 +5640,9 @@ var eventbridge_inbound_exports = {};
5640
5640
  __export(eventbridge_inbound_exports, {
5641
5641
  createEventBridgeInboundResources: () => createEventBridgeInboundResources
5642
5642
  });
5643
- import * as aws17 from "@pulumi/aws";
5643
+ import * as aws16 from "@pulumi/aws";
5644
5644
  function createEventBridgeInboundResources(config2) {
5645
- const rule = new aws17.cloudwatch.EventRule("wraps-inbound-events-rule", {
5645
+ const rule = new aws16.cloudwatch.EventRule("wraps-inbound-events-rule", {
5646
5646
  name: "wraps-inbound-events-to-webhook",
5647
5647
  description: "Route inbound email events to webhook",
5648
5648
  eventBusName: "default",
@@ -5659,7 +5659,7 @@ function createEventBridgeInboundResources(config2) {
5659
5659
  let webhookApiDestination;
5660
5660
  let webhookTarget;
5661
5661
  if (config2.webhookUrl && config2.webhookSecret) {
5662
- webhookConnection = new aws17.cloudwatch.EventConnection(
5662
+ webhookConnection = new aws16.cloudwatch.EventConnection(
5663
5663
  "wraps-inbound-webhook-connection",
5664
5664
  {
5665
5665
  name: "wraps-inbound-webhook-connection",
@@ -5673,7 +5673,7 @@ function createEventBridgeInboundResources(config2) {
5673
5673
  }
5674
5674
  }
5675
5675
  );
5676
- webhookApiDestination = new aws17.cloudwatch.EventApiDestination(
5676
+ webhookApiDestination = new aws16.cloudwatch.EventApiDestination(
5677
5677
  "wraps-inbound-webhook-destination",
5678
5678
  {
5679
5679
  name: "wraps-inbound-webhook-destination",
@@ -5684,7 +5684,7 @@ function createEventBridgeInboundResources(config2) {
5684
5684
  invocationRateLimitPerSecond: 100
5685
5685
  }
5686
5686
  );
5687
- const webhookRole = new aws17.iam.Role("wraps-inbound-webhook-role", {
5687
+ const webhookRole = new aws16.iam.Role("wraps-inbound-webhook-role", {
5688
5688
  name: "wraps-inbound-eventbridge-webhook-role",
5689
5689
  assumeRolePolicy: JSON.stringify({
5690
5690
  Version: "2012-10-17",
@@ -5703,7 +5703,7 @@ function createEventBridgeInboundResources(config2) {
5703
5703
  Service: "email-inbound"
5704
5704
  }
5705
5705
  });
5706
- new aws17.iam.RolePolicy("wraps-inbound-webhook-policy", {
5706
+ new aws16.iam.RolePolicy("wraps-inbound-webhook-policy", {
5707
5707
  role: webhookRole.name,
5708
5708
  policy: webhookApiDestination.arn.apply(
5709
5709
  (destArn) => JSON.stringify({
@@ -5718,7 +5718,7 @@ function createEventBridgeInboundResources(config2) {
5718
5718
  })
5719
5719
  )
5720
5720
  });
5721
- webhookTarget = new aws17.cloudwatch.EventTarget(
5721
+ webhookTarget = new aws16.cloudwatch.EventTarget(
5722
5722
  "wraps-inbound-webhook-target",
5723
5723
  {
5724
5724
  rule: rule.name,
@@ -9419,13 +9419,12 @@ async function deleteCdnDNSRecords(hostedZoneId, customDomain) {
9419
9419
  // src/commands/cdn/init.ts
9420
9420
  init_esm_shims();
9421
9421
  import * as clack10 from "@clack/prompts";
9422
- import * as pulumi4 from "@pulumi/pulumi";
9422
+ import * as pulumi5 from "@pulumi/pulumi";
9423
9423
  import pc11 from "picocolors";
9424
9424
 
9425
9425
  // src/infrastructure/cdn-stack.ts
9426
9426
  init_esm_shims();
9427
- import * as aws3 from "@pulumi/aws";
9428
- import * as pulumi3 from "@pulumi/pulumi";
9427
+ import * as pulumi4 from "@pulumi/pulumi";
9429
9428
 
9430
9429
  // src/infrastructure/resources/s3-cdn.ts
9431
9430
  init_esm_shims();
@@ -9749,19 +9748,133 @@ async function createCdnACMCertificate(config2) {
9749
9748
  };
9750
9749
  }
9751
9750
 
9752
- // src/infrastructure/cdn-stack.ts
9751
+ // src/infrastructure/shared/iam.ts
9752
+ init_esm_shims();
9753
9753
  init_resource_checks();
9754
+ import * as aws2 from "@pulumi/aws";
9755
+ import * as pulumi3 from "@pulumi/pulumi";
9756
+ async function createServiceIAMRole(config2) {
9757
+ let assumeRolePolicy;
9758
+ if (config2.provider === "vercel" && config2.oidcProvider) {
9759
+ const hasAdditionalPrincipals = config2.additionalVercelPrincipals && config2.additionalVercelPrincipals.length > 0;
9760
+ if (hasAdditionalPrincipals) {
9761
+ const serviceStatement = JSON.stringify({
9762
+ Effect: "Allow",
9763
+ Principal: {
9764
+ Service: config2.additionalVercelPrincipals.length === 1 ? config2.additionalVercelPrincipals[0] : config2.additionalVercelPrincipals
9765
+ },
9766
+ Action: "sts:AssumeRole"
9767
+ });
9768
+ assumeRolePolicy = pulumi3.interpolate`{
9769
+ "Version": "2012-10-17",
9770
+ "Statement": [
9771
+ {
9772
+ "Effect": "Allow",
9773
+ "Principal": {
9774
+ "Federated": "${config2.oidcProvider.arn}"
9775
+ },
9776
+ "Action": "sts:AssumeRoleWithWebIdentity",
9777
+ "Condition": {
9778
+ "StringEquals": {
9779
+ "oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
9780
+ },
9781
+ "StringLike": {
9782
+ "oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
9783
+ }
9784
+ }
9785
+ },
9786
+ ${serviceStatement}
9787
+ ]
9788
+ }`;
9789
+ } else {
9790
+ assumeRolePolicy = pulumi3.interpolate`{
9791
+ "Version": "2012-10-17",
9792
+ "Statement": [{
9793
+ "Effect": "Allow",
9794
+ "Principal": {
9795
+ "Federated": "${config2.oidcProvider.arn}"
9796
+ },
9797
+ "Action": "sts:AssumeRoleWithWebIdentity",
9798
+ "Condition": {
9799
+ "StringEquals": {
9800
+ "oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
9801
+ },
9802
+ "StringLike": {
9803
+ "oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
9804
+ }
9805
+ }
9806
+ }]
9807
+ }`;
9808
+ }
9809
+ } else if (config2.provider === "aws") {
9810
+ assumeRolePolicy = pulumi3.output(`{
9811
+ "Version": "2012-10-17",
9812
+ "Statement": [{
9813
+ "Effect": "Allow",
9814
+ "Principal": {
9815
+ "Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
9816
+ },
9817
+ "Action": "sts:AssumeRole"
9818
+ }]
9819
+ }`);
9820
+ } else {
9821
+ throw new Error("Other providers not yet implemented");
9822
+ }
9823
+ const roleName = `wraps-${config2.serviceName}-role`;
9824
+ const exists = await roleExists(roleName);
9825
+ const tags = {
9826
+ ManagedBy: "wraps-cli",
9827
+ Provider: config2.provider,
9828
+ ...config2.extraTags
9829
+ };
9830
+ const role = exists ? new aws2.iam.Role(
9831
+ roleName,
9832
+ { name: roleName, assumeRolePolicy, tags },
9833
+ {
9834
+ import: roleName,
9835
+ ...config2.customTimeouts && {
9836
+ customTimeouts: config2.customTimeouts
9837
+ }
9838
+ }
9839
+ ) : new aws2.iam.Role(
9840
+ roleName,
9841
+ { name: roleName, assumeRolePolicy, tags },
9842
+ config2.customTimeouts ? { customTimeouts: config2.customTimeouts } : void 0
9843
+ );
9844
+ const policyName = `wraps-${config2.serviceName}-policy`;
9845
+ const isOutputStatements = pulumi3.Output.isInstance(config2.policyStatements);
9846
+ if (isOutputStatements) {
9847
+ new aws2.iam.RolePolicy(policyName, {
9848
+ role: role.name,
9849
+ policy: config2.policyStatements.apply(
9850
+ (stmts) => JSON.stringify({
9851
+ Version: "2012-10-17",
9852
+ Statement: stmts
9853
+ })
9854
+ )
9855
+ });
9856
+ } else {
9857
+ new aws2.iam.RolePolicy(policyName, {
9858
+ role: role.name,
9859
+ policy: JSON.stringify({
9860
+ Version: "2012-10-17",
9861
+ Statement: config2.policyStatements
9862
+ })
9863
+ });
9864
+ }
9865
+ return role;
9866
+ }
9754
9867
 
9755
9868
  // src/infrastructure/vercel-oidc.ts
9756
9869
  init_esm_shims();
9757
- import * as aws2 from "@pulumi/aws";
9870
+ import * as aws3 from "@pulumi/aws";
9758
9871
  async function getExistingOIDCProviderArn(url) {
9759
9872
  try {
9760
9873
  const { IAMClient: IAMClient4, ListOpenIDConnectProvidersCommand } = await import("@aws-sdk/client-iam");
9761
- const iam10 = new IAMClient4({
9874
+ const iam9 = new IAMClient4({
9762
9875
  region: process.env.AWS_REGION || "us-east-1"
9763
9876
  });
9764
- const response = await iam10.send(new ListOpenIDConnectProvidersCommand({}));
9877
+ const response = await iam9.send(new ListOpenIDConnectProvidersCommand({}));
9765
9878
  const expectedArnSuffix = url.replace("https://", "");
9766
9879
  const provider = response.OpenIDConnectProviderList?.find(
9767
9880
  (p) => p.Arn?.endsWith(expectedArnSuffix)
@@ -9776,7 +9889,7 @@ async function createVercelOIDC(config2) {
9776
9889
  const url = `https://oidc.vercel.com/${config2.teamSlug}`;
9777
9890
  const existingArn = await getExistingOIDCProviderArn(url);
9778
9891
  if (existingArn) {
9779
- return new aws2.iam.OpenIdConnectProvider(
9892
+ return new aws3.iam.OpenIdConnectProvider(
9780
9893
  "wraps-vercel-oidc",
9781
9894
  {
9782
9895
  url,
@@ -9797,7 +9910,7 @@ async function createVercelOIDC(config2) {
9797
9910
  }
9798
9911
  );
9799
9912
  }
9800
- return new aws2.iam.OpenIdConnectProvider("wraps-vercel-oidc", {
9913
+ return new aws3.iam.OpenIdConnectProvider("wraps-vercel-oidc", {
9801
9914
  url,
9802
9915
  clientIdLists: [`https://vercel.com/${config2.teamSlug}`],
9803
9916
  thumbprintLists: [
@@ -9814,104 +9927,46 @@ async function createVercelOIDC(config2) {
9814
9927
 
9815
9928
  // src/infrastructure/cdn-stack.ts
9816
9929
  async function createCdnIAMRole(config2) {
9817
- let assumeRolePolicy;
9818
- if (config2.provider === "vercel" && config2.oidcProvider) {
9819
- assumeRolePolicy = pulumi3.interpolate`{
9820
- "Version": "2012-10-17",
9821
- "Statement": [{
9822
- "Effect": "Allow",
9823
- "Principal": {
9824
- "Federated": "${config2.oidcProvider.arn}"
9825
- },
9826
- "Action": "sts:AssumeRoleWithWebIdentity",
9827
- "Condition": {
9828
- "StringEquals": {
9829
- "oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
9830
- },
9831
- "StringLike": {
9832
- "oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
9833
- }
9834
- }
9835
- }]
9836
- }`;
9837
- } else if (config2.provider === "aws") {
9838
- assumeRolePolicy = pulumi3.output(`{
9839
- "Version": "2012-10-17",
9840
- "Statement": [{
9841
- "Effect": "Allow",
9842
- "Principal": {
9843
- "Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
9844
- },
9845
- "Action": "sts:AssumeRole"
9846
- }]
9847
- }`);
9848
- } else {
9849
- throw new Error("Other providers not yet implemented");
9850
- }
9851
- const roleName = "wraps-cdn-role";
9852
- const exists = await roleExists(roleName);
9853
- const role = exists ? new aws3.iam.Role(
9854
- roleName,
9855
- {
9856
- name: roleName,
9857
- assumeRolePolicy,
9858
- tags: {
9859
- ManagedBy: "wraps-cli",
9860
- Service: "cdn",
9861
- Provider: config2.provider
9930
+ const resolvedStatements = pulumi4.all([config2.bucketArn, config2.distributionArn]).apply(([bucketArn, distributionArn]) => {
9931
+ const statements = [
9932
+ {
9933
+ Sid: "StorageBucketAccess",
9934
+ Effect: "Allow",
9935
+ Action: [
9936
+ "s3:PutObject",
9937
+ "s3:GetObject",
9938
+ "s3:DeleteObject",
9939
+ "s3:ListBucket",
9940
+ "s3:GetBucketLocation",
9941
+ "s3:GetObjectTagging",
9942
+ "s3:PutObjectTagging"
9943
+ ],
9944
+ Resource: [bucketArn, `${bucketArn}/*`]
9862
9945
  }
9863
- },
9864
- {
9865
- import: roleName
9866
- }
9867
- ) : new aws3.iam.Role(roleName, {
9868
- name: roleName,
9869
- assumeRolePolicy,
9870
- tags: {
9871
- ManagedBy: "wraps-cli",
9872
- Service: "cdn",
9873
- Provider: config2.provider
9946
+ ];
9947
+ if (distributionArn) {
9948
+ statements.push({
9949
+ Sid: "CloudFrontInvalidation",
9950
+ Effect: "Allow",
9951
+ Action: [
9952
+ "cloudfront:CreateInvalidation",
9953
+ "cloudfront:GetInvalidation",
9954
+ "cloudfront:ListInvalidations"
9955
+ ],
9956
+ Resource: distributionArn
9957
+ });
9874
9958
  }
9959
+ return statements;
9875
9960
  });
9876
- const statements = [
9877
- // S3 bucket access
9878
- {
9879
- Sid: "StorageBucketAccess",
9880
- Effect: "Allow",
9881
- Action: [
9882
- "s3:PutObject",
9883
- "s3:GetObject",
9884
- "s3:DeleteObject",
9885
- "s3:ListBucket",
9886
- "s3:GetBucketLocation",
9887
- "s3:GetObjectTagging",
9888
- "s3:PutObjectTagging"
9889
- ],
9890
- Resource: [config2.bucketArn, pulumi3.interpolate`${config2.bucketArn}/*`]
9891
- }
9892
- ];
9893
- if (config2.distributionArn) {
9894
- statements.push({
9895
- Sid: "CloudFrontInvalidation",
9896
- Effect: "Allow",
9897
- Action: [
9898
- "cloudfront:CreateInvalidation",
9899
- "cloudfront:GetInvalidation",
9900
- "cloudfront:ListInvalidations"
9901
- ],
9902
- Resource: config2.distributionArn
9903
- });
9904
- }
9905
- new aws3.iam.RolePolicy("wraps-cdn-policy", {
9906
- role: role.name,
9907
- policy: pulumi3.all([statements]).apply(
9908
- ([stmts]) => JSON.stringify({
9909
- Version: "2012-10-17",
9910
- Statement: stmts
9911
- })
9912
- )
9961
+ return createServiceIAMRole({
9962
+ serviceName: "cdn",
9963
+ provider: config2.provider,
9964
+ oidcProvider: config2.oidcProvider,
9965
+ vercelTeamSlug: config2.vercelTeamSlug,
9966
+ vercelProjectName: config2.vercelProjectName,
9967
+ policyStatements: resolvedStatements,
9968
+ extraTags: { Service: "cdn" }
9913
9969
  });
9914
- return role;
9915
9970
  }
9916
9971
  async function deployCdnStack(config2) {
9917
9972
  const accountId = config2.accountId;
@@ -9943,7 +9998,7 @@ async function deployCdnStack(config2) {
9943
9998
  if (config2.cdnConfig.cdn.enabled) {
9944
9999
  const hasAutoValidation2 = acmResources?.certificateValidation;
9945
10000
  const useCertFromUpgrade = config2.certValidated && config2.existingCertArn;
9946
- const certificateArn = useCertFromUpgrade ? pulumi3.output(config2.existingCertArn) : hasAutoValidation2 ? acmResources?.certificateValidation?.certificateArn : void 0;
10001
+ const certificateArn = useCertFromUpgrade ? pulumi4.output(config2.existingCertArn) : hasAutoValidation2 ? acmResources?.certificateValidation?.certificateArn : void 0;
9947
10002
  const customDomainForCdn = useCertFromUpgrade || hasAutoValidation2 ? config2.cdnConfig.cdn.customDomain : void 0;
9948
10003
  cdnResources = await createCdnDistribution({
9949
10004
  bucket: bucketResources.bucket,
@@ -10529,7 +10584,7 @@ ${pc11.yellow(pc11.bold("Configuration Notes:"))}`);
10529
10584
  "Generating infrastructure preview",
10530
10585
  async () => {
10531
10586
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
10532
- const stack = await pulumi4.automation.LocalWorkspace.createOrSelectStack(
10587
+ const stack = await pulumi5.automation.LocalWorkspace.createOrSelectStack(
10533
10588
  {
10534
10589
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
10535
10590
  projectName: "wraps-cdn",
@@ -10594,7 +10649,7 @@ ${pc11.yellow(pc11.bold("Configuration Notes:"))}`);
10594
10649
  "Deploying CDN infrastructure (this may take 2-3 minutes)",
10595
10650
  async () => {
10596
10651
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
10597
- const stack = await pulumi4.automation.LocalWorkspace.createOrSelectStack(
10652
+ const stack = await pulumi5.automation.LocalWorkspace.createOrSelectStack(
10598
10653
  {
10599
10654
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
10600
10655
  projectName: "wraps-cdn",
@@ -10929,7 +10984,7 @@ init_aws();
10929
10984
  init_fs();
10930
10985
  init_metadata();
10931
10986
  import * as clack11 from "@clack/prompts";
10932
- import * as pulumi5 from "@pulumi/pulumi";
10987
+ import * as pulumi6 from "@pulumi/pulumi";
10933
10988
  import pc12 from "picocolors";
10934
10989
  async function cdnStatus(options) {
10935
10990
  const startTime = Date.now();
@@ -10965,7 +11020,7 @@ async function cdnStatus(options) {
10965
11020
  let stackOutputs = {};
10966
11021
  try {
10967
11022
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
10968
- const stack = await pulumi5.automation.LocalWorkspace.selectStack({
11023
+ const stack = await pulumi6.automation.LocalWorkspace.selectStack({
10969
11024
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
10970
11025
  workDir: getPulumiWorkDir()
10971
11026
  });
@@ -11087,7 +11142,7 @@ ${pc12.bold("Commands:")}`);
11087
11142
  // src/commands/cdn/sync.ts
11088
11143
  init_esm_shims();
11089
11144
  import * as clack12 from "@clack/prompts";
11090
- import * as pulumi6 from "@pulumi/pulumi";
11145
+ import * as pulumi7 from "@pulumi/pulumi";
11091
11146
  import pc13 from "picocolors";
11092
11147
  init_client();
11093
11148
  init_events();
@@ -11143,7 +11198,7 @@ async function cdnSync(options) {
11143
11198
  if (cdnConfig.cdn.customDomain) {
11144
11199
  try {
11145
11200
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
11146
- const checkStack = await pulumi6.automation.LocalWorkspace.selectStack({
11201
+ const checkStack = await pulumi7.automation.LocalWorkspace.selectStack({
11147
11202
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
11148
11203
  workDir: getPulumiWorkDir()
11149
11204
  });
@@ -11180,7 +11235,7 @@ async function cdnSync(options) {
11180
11235
  try {
11181
11236
  await progress.execute("Syncing CDN infrastructure", async () => {
11182
11237
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
11183
- const stack = await pulumi6.automation.LocalWorkspace.createOrSelectStack(
11238
+ const stack = await pulumi7.automation.LocalWorkspace.createOrSelectStack(
11184
11239
  {
11185
11240
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
11186
11241
  projectName: "wraps-cdn",
@@ -11242,7 +11297,7 @@ async function cdnSync(options) {
11242
11297
  // src/commands/cdn/upgrade.ts
11243
11298
  init_esm_shims();
11244
11299
  import * as clack13 from "@clack/prompts";
11245
- import * as pulumi7 from "@pulumi/pulumi";
11300
+ import * as pulumi8 from "@pulumi/pulumi";
11246
11301
  import pc14 from "picocolors";
11247
11302
  init_client();
11248
11303
  init_events();
@@ -11298,7 +11353,7 @@ async function cdnUpgrade(options) {
11298
11353
  let stackOutputs = {};
11299
11354
  try {
11300
11355
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
11301
- const stack = await pulumi7.automation.LocalWorkspace.selectStack({
11356
+ const stack = await pulumi8.automation.LocalWorkspace.selectStack({
11302
11357
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
11303
11358
  workDir: getPulumiWorkDir()
11304
11359
  });
@@ -11436,7 +11491,7 @@ Ready to add custom domain: ${pc14.cyan(pendingDomain)}`);
11436
11491
  "Updating CloudFront distribution (this may take 2-3 minutes)",
11437
11492
  async () => {
11438
11493
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
11439
- const stack = await pulumi7.automation.LocalWorkspace.createOrSelectStack(
11494
+ const stack = await pulumi8.automation.LocalWorkspace.createOrSelectStack(
11440
11495
  {
11441
11496
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
11442
11497
  projectName: "wraps-cdn",
@@ -11524,7 +11579,7 @@ init_aws();
11524
11579
  init_fs();
11525
11580
  init_metadata();
11526
11581
  import * as clack14 from "@clack/prompts";
11527
- import * as pulumi8 from "@pulumi/pulumi";
11582
+ import * as pulumi9 from "@pulumi/pulumi";
11528
11583
  import pc15 from "picocolors";
11529
11584
  async function checkDNSRecord(hostname, expectedValue) {
11530
11585
  try {
@@ -11607,7 +11662,7 @@ async function cdnVerify(options) {
11607
11662
  let stackOutputs = {};
11608
11663
  try {
11609
11664
  await ensurePulumiWorkDir({ accountId: identity.accountId, region });
11610
- const stack = await pulumi8.automation.LocalWorkspace.selectStack({
11665
+ const stack = await pulumi9.automation.LocalWorkspace.selectStack({
11611
11666
  stackName: `wraps-cdn-${identity.accountId}-${region}`,
11612
11667
  workDir: getPulumiWorkDir()
11613
11668
  });
@@ -14754,7 +14809,7 @@ import pc17 from "picocolors";
14754
14809
  // src/infrastructure/email-stack.ts
14755
14810
  init_esm_shims();
14756
14811
  init_dist();
14757
- import * as aws18 from "@pulumi/aws";
14812
+ import * as aws17 from "@pulumi/aws";
14758
14813
 
14759
14814
  // src/infrastructure/resources/alerting.ts
14760
14815
  init_esm_shims();
@@ -15022,7 +15077,7 @@ async function createDynamoDBTables(_config) {
15022
15077
  // src/infrastructure/resources/eventbridge.ts
15023
15078
  init_esm_shims();
15024
15079
  import * as aws6 from "@pulumi/aws";
15025
- import * as pulumi9 from "@pulumi/pulumi";
15080
+ import * as pulumi10 from "@pulumi/pulumi";
15026
15081
  async function createEventBridgeResources(config2) {
15027
15082
  const eventBusName = config2.eventBusArn.apply((arn) => arn.split("/").pop());
15028
15083
  const rule = new aws6.cloudwatch.EventRule("wraps-email-events-rule", {
@@ -15040,7 +15095,7 @@ async function createEventBridgeResources(config2) {
15040
15095
  });
15041
15096
  new aws6.sqs.QueuePolicy("wraps-email-events-queue-policy", {
15042
15097
  queueUrl: config2.queueUrl,
15043
- policy: pulumi9.all([config2.queueArn, rule.arn]).apply(
15098
+ policy: pulumi10.all([config2.queueArn, rule.arn]).apply(
15044
15099
  ([queueArn, ruleArn]) => JSON.stringify({
15045
15100
  Version: "2012-10-17",
15046
15101
  Statement: [
@@ -15149,68 +15204,7 @@ async function createEventBridgeResources(config2) {
15149
15204
 
15150
15205
  // src/infrastructure/resources/iam.ts
15151
15206
  init_esm_shims();
15152
- init_resource_checks();
15153
- import * as aws7 from "@pulumi/aws";
15154
- import * as pulumi10 from "@pulumi/pulumi";
15155
15207
  async function createIAMRole(config2) {
15156
- let assumeRolePolicy;
15157
- if (config2.provider === "vercel" && config2.oidcProvider) {
15158
- assumeRolePolicy = pulumi10.interpolate`{
15159
- "Version": "2012-10-17",
15160
- "Statement": [{
15161
- "Effect": "Allow",
15162
- "Principal": {
15163
- "Federated": "${config2.oidcProvider.arn}"
15164
- },
15165
- "Action": "sts:AssumeRoleWithWebIdentity",
15166
- "Condition": {
15167
- "StringEquals": {
15168
- "oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
15169
- },
15170
- "StringLike": {
15171
- "oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
15172
- }
15173
- }
15174
- }]
15175
- }`;
15176
- } else if (config2.provider === "aws") {
15177
- assumeRolePolicy = pulumi10.output(`{
15178
- "Version": "2012-10-17",
15179
- "Statement": [{
15180
- "Effect": "Allow",
15181
- "Principal": {
15182
- "Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
15183
- },
15184
- "Action": "sts:AssumeRole"
15185
- }]
15186
- }`);
15187
- } else {
15188
- throw new Error("Other providers not yet implemented");
15189
- }
15190
- const roleName = "wraps-email-role";
15191
- const exists = await roleExists(roleName);
15192
- const role = exists ? new aws7.iam.Role(
15193
- roleName,
15194
- {
15195
- name: roleName,
15196
- assumeRolePolicy,
15197
- tags: {
15198
- ManagedBy: "wraps-cli",
15199
- Provider: config2.provider
15200
- }
15201
- },
15202
- {
15203
- import: roleName
15204
- // Import existing role (use role name, not ARN)
15205
- }
15206
- ) : new aws7.iam.Role(roleName, {
15207
- name: roleName,
15208
- assumeRolePolicy,
15209
- tags: {
15210
- ManagedBy: "wraps-cli",
15211
- Provider: config2.provider
15212
- }
15213
- });
15214
15208
  const statements = [];
15215
15209
  statements.push({
15216
15210
  Effect: "Allow",
@@ -15316,14 +15310,14 @@ async function createIAMRole(config2) {
15316
15310
  Resource: "arn:aws:ses:*:*:mailmanager-archive/*"
15317
15311
  });
15318
15312
  }
15319
- new aws7.iam.RolePolicy("wraps-email-policy", {
15320
- role: role.name,
15321
- policy: JSON.stringify({
15322
- Version: "2012-10-17",
15323
- Statement: statements
15324
- })
15313
+ return createServiceIAMRole({
15314
+ serviceName: "email",
15315
+ provider: config2.provider,
15316
+ oidcProvider: config2.oidcProvider,
15317
+ vercelTeamSlug: config2.vercelTeamSlug,
15318
+ vercelProjectName: config2.vercelProjectName,
15319
+ policyStatements: statements
15325
15320
  });
15326
- return role;
15327
15321
  }
15328
15322
 
15329
15323
  // src/infrastructure/email-stack.ts
@@ -15331,7 +15325,7 @@ init_lambda();
15331
15325
 
15332
15326
  // src/infrastructure/resources/ses.ts
15333
15327
  init_esm_shims();
15334
- import * as aws9 from "@pulumi/aws";
15328
+ import * as aws8 from "@pulumi/aws";
15335
15329
  async function configurationSetExists(configSetName, region) {
15336
15330
  try {
15337
15331
  const { SESv2Client: SESv2Client6, GetConfigurationSetCommand: GetConfigurationSetCommand2 } = await import("@aws-sdk/client-sesv2");
@@ -15409,16 +15403,16 @@ async function createSESResources(config2) {
15409
15403
  }
15410
15404
  const configSetName = "wraps-email-tracking";
15411
15405
  const exists = await configurationSetExists(configSetName, config2.region);
15412
- const configSet = exists ? new aws9.sesv2.ConfigurationSet(configSetName, configSetOptions, {
15406
+ const configSet = exists ? new aws8.sesv2.ConfigurationSet(configSetName, configSetOptions, {
15413
15407
  import: configSetName
15414
15408
  // Import existing configuration set
15415
- }) : new aws9.sesv2.ConfigurationSet(configSetName, configSetOptions);
15416
- const defaultEventBus = aws9.cloudwatch.getEventBusOutput({
15409
+ }) : new aws8.sesv2.ConfigurationSet(configSetName, configSetOptions);
15410
+ const defaultEventBus = aws8.cloudwatch.getEventBusOutput({
15417
15411
  name: "default"
15418
15412
  });
15419
15413
  if (config2.eventTrackingEnabled) {
15420
15414
  const eventDestName = "wraps-email-eventbridge";
15421
- new aws9.sesv2.ConfigurationSetEventDestination(
15415
+ new aws8.sesv2.ConfigurationSetEventDestination(
15422
15416
  "wraps-email-all-events",
15423
15417
  {
15424
15418
  configurationSetName: configSet.configurationSetName,
@@ -15458,7 +15452,7 @@ async function createSESResources(config2) {
15458
15452
  config2.domain,
15459
15453
  config2.region
15460
15454
  );
15461
- domainIdentity = identityExists ? new aws9.sesv2.EmailIdentity(
15455
+ domainIdentity = identityExists ? new aws8.sesv2.EmailIdentity(
15462
15456
  "wraps-email-domain",
15463
15457
  {
15464
15458
  emailIdentity: config2.domain,
@@ -15475,7 +15469,7 @@ async function createSESResources(config2) {
15475
15469
  import: config2.domain
15476
15470
  // Import existing identity
15477
15471
  }
15478
- ) : new aws9.sesv2.EmailIdentity("wraps-email-domain", {
15472
+ ) : new aws8.sesv2.EmailIdentity("wraps-email-domain", {
15479
15473
  emailIdentity: config2.domain,
15480
15474
  configurationSetName: configSet.configurationSetName,
15481
15475
  // Link configuration set to domain
@@ -15491,7 +15485,7 @@ async function createSESResources(config2) {
15491
15485
  );
15492
15486
  if (config2.mailFromDomain) {
15493
15487
  mailFromDomain = config2.mailFromDomain;
15494
- new aws9.sesv2.EmailIdentityMailFromAttributes(
15488
+ new aws8.sesv2.EmailIdentityMailFromAttributes(
15495
15489
  "wraps-email-mail-from",
15496
15490
  {
15497
15491
  emailIdentity: config2.domain,
@@ -15522,7 +15516,7 @@ async function createSESResources(config2) {
15522
15516
  // src/infrastructure/resources/smtp-credentials.ts
15523
15517
  init_esm_shims();
15524
15518
  import { createHmac as createHmac2 } from "crypto";
15525
- import * as aws10 from "@pulumi/aws";
15519
+ import * as aws9 from "@pulumi/aws";
15526
15520
  function convertToSMTPPassword2(secretAccessKey, region) {
15527
15521
  const DATE = "11111111";
15528
15522
  const SERVICE = "ses";
@@ -15543,10 +15537,10 @@ function convertToSMTPPassword2(secretAccessKey, region) {
15543
15537
  async function userExists(userName) {
15544
15538
  try {
15545
15539
  const { IAMClient: IAMClient4, GetUserCommand } = await import("@aws-sdk/client-iam");
15546
- const iam10 = new IAMClient4({
15540
+ const iam9 = new IAMClient4({
15547
15541
  region: process.env.AWS_REGION || "us-east-1"
15548
15542
  });
15549
- await iam10.send(new GetUserCommand({ UserName: userName }));
15543
+ await iam9.send(new GetUserCommand({ UserName: userName }));
15550
15544
  return true;
15551
15545
  } catch (error) {
15552
15546
  if (error.name === "NoSuchEntityException" || error.Code === "NoSuchEntity") {
@@ -15558,7 +15552,7 @@ async function userExists(userName) {
15558
15552
  async function createSMTPCredentials(config2) {
15559
15553
  const userName = "wraps-email-smtp-user";
15560
15554
  const userAlreadyExists = await userExists(userName);
15561
- const iamUser = userAlreadyExists ? new aws10.iam.User(
15555
+ const iamUser = userAlreadyExists ? new aws9.iam.User(
15562
15556
  userName,
15563
15557
  {
15564
15558
  name: userName,
@@ -15568,14 +15562,14 @@ async function createSMTPCredentials(config2) {
15568
15562
  }
15569
15563
  },
15570
15564
  { import: userName }
15571
- ) : new aws10.iam.User(userName, {
15565
+ ) : new aws9.iam.User(userName, {
15572
15566
  name: userName,
15573
15567
  tags: {
15574
15568
  ManagedBy: "wraps-cli",
15575
15569
  Purpose: "SES SMTP Authentication"
15576
15570
  }
15577
15571
  });
15578
- new aws10.iam.UserPolicy("wraps-email-smtp-policy", {
15572
+ new aws9.iam.UserPolicy("wraps-email-smtp-policy", {
15579
15573
  user: iamUser.name,
15580
15574
  policy: JSON.stringify({
15581
15575
  Version: "2012-10-17",
@@ -15593,7 +15587,7 @@ async function createSMTPCredentials(config2) {
15593
15587
  ]
15594
15588
  })
15595
15589
  });
15596
- const accessKey = new aws10.iam.AccessKey("wraps-email-smtp-key", {
15590
+ const accessKey = new aws9.iam.AccessKey("wraps-email-smtp-key", {
15597
15591
  user: iamUser.name
15598
15592
  });
15599
15593
  const smtpPassword = accessKey.secret.apply(
@@ -15608,9 +15602,9 @@ async function createSMTPCredentials(config2) {
15608
15602
 
15609
15603
  // src/infrastructure/resources/sqs.ts
15610
15604
  init_esm_shims();
15611
- import * as aws11 from "@pulumi/aws";
15605
+ import * as aws10 from "@pulumi/aws";
15612
15606
  async function createSQSResources() {
15613
- const dlq = new aws11.sqs.Queue("wraps-email-events-dlq", {
15607
+ const dlq = new aws10.sqs.Queue("wraps-email-events-dlq", {
15614
15608
  name: "wraps-email-events-dlq",
15615
15609
  messageRetentionSeconds: 1209600,
15616
15610
  // 14 days
@@ -15619,7 +15613,7 @@ async function createSQSResources() {
15619
15613
  Description: "Dead letter queue for failed SES event processing"
15620
15614
  }
15621
15615
  });
15622
- const queue = new aws11.sqs.Queue("wraps-email-events", {
15616
+ const queue = new aws10.sqs.Queue("wraps-email-events", {
15623
15617
  name: "wraps-email-events",
15624
15618
  visibilityTimeoutSeconds: 60,
15625
15619
  // Must be >= Lambda timeout
@@ -15647,7 +15641,7 @@ async function createSQSResources() {
15647
15641
 
15648
15642
  // src/infrastructure/email-stack.ts
15649
15643
  async function deployEmailStack(config2) {
15650
- const identity = await aws18.getCallerIdentity();
15644
+ const identity = await aws17.getCallerIdentity();
15651
15645
  const accountId = identity.accountId;
15652
15646
  let oidcProvider;
15653
15647
  if (config2.provider === "vercel" && config2.vercel) {
@@ -15810,7 +15804,7 @@ async function deployEmailStack(config2) {
15810
15804
  region: config2.region,
15811
15805
  dlqArn: sqsInbound.dlq.arn
15812
15806
  });
15813
- new aws18.s3.BucketNotification(
15807
+ new aws17.s3.BucketNotification(
15814
15808
  "wraps-inbound-s3-notification",
15815
15809
  {
15816
15810
  bucket: s3Inbound.bucket.id,
@@ -16323,13 +16317,13 @@ async function scanLambdaFunctions(region) {
16323
16317
  }
16324
16318
  }
16325
16319
  async function scanIAMRoles(region) {
16326
- const iam10 = new IAMClient({ region });
16320
+ const iam9 = new IAMClient({ region });
16327
16321
  const roles = [];
16328
16322
  try {
16329
16323
  let marker;
16330
16324
  let hasMore = true;
16331
16325
  while (hasMore) {
16332
- const listResponse = await iam10.send(
16326
+ const listResponse = await iam9.send(
16333
16327
  new ListRolesCommand({
16334
16328
  Marker: marker,
16335
16329
  MaxItems: 100
@@ -16757,7 +16751,7 @@ async function getEmailIdentityInfo(domain, region) {
16757
16751
  mailFromDomain: response.MailFromAttributes?.MailFromDomain
16758
16752
  };
16759
16753
  } catch (error) {
16760
- if (isAWSError(error)) {
16754
+ if (isAWSNotFoundError(error)) {
16761
16755
  return { dkimTokens: [] };
16762
16756
  }
16763
16757
  throw error;
@@ -17549,11 +17543,11 @@ Run ${pc20.cyan("wraps email domains add")} to add a domain.
17549
17543
  verified: details.VerifiedForSendingStatus,
17550
17544
  dkimStatus: details.DkimAttributes?.Status || "PENDING"
17551
17545
  };
17552
- } catch {
17546
+ } catch (error) {
17553
17547
  return {
17554
17548
  name: domain.IdentityName,
17555
17549
  verified: false,
17556
- dkimStatus: "UNKNOWN"
17550
+ dkimStatus: isAWSNotFoundError(error) ? "UNKNOWN" : "ERROR"
17557
17551
  };
17558
17552
  }
17559
17553
  })
@@ -19415,7 +19409,7 @@ Run ${pc24.cyan("wraps email init")} to deploy email infrastructure.
19415
19409
  purpose: tracked?.purpose
19416
19410
  };
19417
19411
  } catch (error) {
19418
- if (isAWSError(error)) {
19412
+ if (isAWSNotFoundError(error)) {
19419
19413
  return {
19420
19414
  domain: d.domain,
19421
19415
  status: d.verified ? "verified" : "pending",
@@ -22459,9 +22453,9 @@ ${pc28.green("\u2713")} ${pc28.bold("Upgrade complete!")}
22459
22453
  iamUserArn: outputs.smtpUserArn,
22460
22454
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
22461
22455
  };
22462
- await saveConnectionMetadata(metadata);
22463
22456
  }
22464
22457
  }
22458
+ await saveConnectionMetadata(metadata);
22465
22459
  const enabledFeatures = [];
22466
22460
  if (updatedConfig.tracking?.enabled) {
22467
22461
  enabledFeatures.push("tracking");
@@ -24574,10 +24568,10 @@ async function deployEventBridge(metadata, region, identity, webhookSecret, prog
24574
24568
  var WRAPS_PLATFORM_ACCOUNT_ID = "905130073023";
24575
24569
  async function updatePlatformRole(metadata, progress, externalId) {
24576
24570
  const roleName = "wraps-console-access-role";
24577
- const iam10 = new IAMClient2({ region: "us-east-1" });
24571
+ const iam9 = new IAMClient2({ region: "us-east-1" });
24578
24572
  let roleExists2 = false;
24579
24573
  try {
24580
- await iam10.send(new GetRoleCommand({ RoleName: roleName }));
24574
+ await iam9.send(new GetRoleCommand({ RoleName: roleName }));
24581
24575
  roleExists2 = true;
24582
24576
  } catch (error) {
24583
24577
  const isNotFound = error instanceof Error && (error.name === "NoSuchEntityException" || error.name === "NoSuchEntity" || error.message.includes("NoSuchEntity"));
@@ -24590,7 +24584,7 @@ async function updatePlatformRole(metadata, progress, externalId) {
24590
24584
  const policy = buildConsolePolicyDocument(emailConfig, smsConfig);
24591
24585
  if (roleExists2) {
24592
24586
  await progress.execute("Updating platform access role", async () => {
24593
- await iam10.send(
24587
+ await iam9.send(
24594
24588
  new PutRolePolicyCommand({
24595
24589
  RoleName: roleName,
24596
24590
  PolicyName: "wraps-console-access-policy",
@@ -24618,7 +24612,7 @@ async function updatePlatformRole(metadata, progress, externalId) {
24618
24612
  }
24619
24613
  ]
24620
24614
  };
24621
- await iam10.send(
24615
+ await iam9.send(
24622
24616
  new CreateRoleCommand({
24623
24617
  RoleName: roleName,
24624
24618
  Description: "Allows Wraps dashboard to access CloudWatch metrics and SES data",
@@ -24629,7 +24623,7 @@ async function updatePlatformRole(metadata, progress, externalId) {
24629
24623
  ]
24630
24624
  })
24631
24625
  );
24632
- await iam10.send(
24626
+ await iam9.send(
24633
24627
  new PutRolePolicyCommand({
24634
24628
  RoleName: roleName,
24635
24629
  PolicyName: "wraps-console-access-policy",
@@ -25045,10 +25039,10 @@ Run ${pc33.cyan("wraps email init")} or ${pc33.cyan("wraps sms init")} first.
25045
25039
  progress.succeed("Event streaming already configured");
25046
25040
  }
25047
25041
  const roleName = "wraps-console-access-role";
25048
- const iam10 = new IAMClient2({ region: "us-east-1" });
25042
+ const iam9 = new IAMClient2({ region: "us-east-1" });
25049
25043
  let roleExists2 = false;
25050
25044
  try {
25051
- await iam10.send(new GetRoleCommand({ RoleName: roleName }));
25045
+ await iam9.send(new GetRoleCommand({ RoleName: roleName }));
25052
25046
  roleExists2 = true;
25053
25047
  } catch (error) {
25054
25048
  const isNotFound = error instanceof Error && (error.name === "NoSuchEntityException" || error.name === "NoSuchEntity" || error.message.includes("NoSuchEntity"));
@@ -25061,7 +25055,7 @@ Run ${pc33.cyan("wraps email init")} or ${pc33.cyan("wraps sms init")} first.
25061
25055
  const smsConfig = metadata.services.sms?.config;
25062
25056
  const policy = buildConsolePolicyDocument(emailConfig, smsConfig);
25063
25057
  await progress.execute("Updating platform access role", async () => {
25064
- await iam10.send(
25058
+ await iam9.send(
25065
25059
  new PutRolePolicyCommand({
25066
25060
  RoleName: roleName,
25067
25061
  PolicyName: "wraps-console-access-policy",
@@ -25212,10 +25206,10 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
25212
25206
  process.exit(1);
25213
25207
  }
25214
25208
  const roleName = "wraps-console-access-role";
25215
- const iam10 = new IAMClient3({ region: "us-east-1" });
25209
+ const iam9 = new IAMClient3({ region: "us-east-1" });
25216
25210
  let roleExists2 = false;
25217
25211
  try {
25218
- await iam10.send(new GetRoleCommand2({ RoleName: roleName }));
25212
+ await iam9.send(new GetRoleCommand2({ RoleName: roleName }));
25219
25213
  roleExists2 = true;
25220
25214
  } catch (error) {
25221
25215
  const isNotFound = error instanceof Error && (error.name === "NoSuchEntityException" || error.name === "NoSuchEntity" || error.message.includes("NoSuchEntity"));
@@ -25284,7 +25278,7 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
25284
25278
  }
25285
25279
  ]
25286
25280
  };
25287
- await iam10.send(
25281
+ await iam9.send(
25288
25282
  new CreateRoleCommand2({
25289
25283
  RoleName: roleName,
25290
25284
  Description: "Allows Wraps dashboard to access CloudWatch metrics and SES data",
@@ -25296,7 +25290,7 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
25296
25290
  })
25297
25291
  );
25298
25292
  const { PutRolePolicyCommand: PutRolePolicyCommand2 } = await import("@aws-sdk/client-iam");
25299
- await iam10.send(
25293
+ await iam9.send(
25300
25294
  new PutRolePolicyCommand2({
25301
25295
  RoleName: roleName,
25302
25296
  PolicyName: "wraps-console-access-policy",
@@ -25307,7 +25301,7 @@ Run ${pc35.cyan("wraps email init")} to deploy infrastructure first.
25307
25301
  } else {
25308
25302
  await progress.execute("Updating IAM role permissions", async () => {
25309
25303
  const { PutRolePolicyCommand: PutRolePolicyCommand2 } = await import("@aws-sdk/client-iam");
25310
- await iam10.send(
25304
+ await iam9.send(
25311
25305
  new PutRolePolicyCommand2({
25312
25306
  RoleName: roleName,
25313
25307
  PolicyName: "wraps-console-access-policy",
@@ -28501,85 +28495,10 @@ import pc39 from "picocolors";
28501
28495
 
28502
28496
  // src/infrastructure/sms-stack.ts
28503
28497
  init_esm_shims();
28504
- init_resource_checks();
28505
- import * as aws19 from "@pulumi/aws";
28498
+ import * as aws18 from "@pulumi/aws";
28506
28499
  import * as pulumi24 from "@pulumi/pulumi";
28500
+ init_resource_checks();
28507
28501
  async function createSMSIAMRole(config2) {
28508
- let assumeRolePolicy;
28509
- if (config2.provider === "vercel" && config2.oidcProvider) {
28510
- assumeRolePolicy = pulumi24.interpolate`{
28511
- "Version": "2012-10-17",
28512
- "Statement": [
28513
- {
28514
- "Effect": "Allow",
28515
- "Principal": {
28516
- "Federated": "${config2.oidcProvider.arn}"
28517
- },
28518
- "Action": "sts:AssumeRoleWithWebIdentity",
28519
- "Condition": {
28520
- "StringEquals": {
28521
- "oidc.vercel.com/${config2.vercelTeamSlug}:aud": "https://vercel.com/${config2.vercelTeamSlug}"
28522
- },
28523
- "StringLike": {
28524
- "oidc.vercel.com/${config2.vercelTeamSlug}:sub": "owner:${config2.vercelTeamSlug}:project:${config2.vercelProjectName}:environment:*"
28525
- }
28526
- }
28527
- },
28528
- {
28529
- "Effect": "Allow",
28530
- "Principal": {
28531
- "Service": "lambda.amazonaws.com"
28532
- },
28533
- "Action": "sts:AssumeRole"
28534
- }
28535
- ]
28536
- }`;
28537
- } else if (config2.provider === "aws") {
28538
- assumeRolePolicy = pulumi24.output(`{
28539
- "Version": "2012-10-17",
28540
- "Statement": [{
28541
- "Effect": "Allow",
28542
- "Principal": {
28543
- "Service": ["lambda.amazonaws.com", "ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
28544
- },
28545
- "Action": "sts:AssumeRole"
28546
- }]
28547
- }`);
28548
- } else {
28549
- throw new Error("Other providers not yet implemented");
28550
- }
28551
- const roleName = "wraps-sms-role";
28552
- const exists = await roleExists(roleName);
28553
- const role = exists ? new aws19.iam.Role(
28554
- roleName,
28555
- {
28556
- name: roleName,
28557
- assumeRolePolicy,
28558
- tags: {
28559
- ManagedBy: "wraps-cli",
28560
- Service: "sms",
28561
- Provider: config2.provider
28562
- }
28563
- },
28564
- {
28565
- import: roleName,
28566
- customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28567
- }
28568
- ) : new aws19.iam.Role(
28569
- roleName,
28570
- {
28571
- name: roleName,
28572
- assumeRolePolicy,
28573
- tags: {
28574
- ManagedBy: "wraps-cli",
28575
- Service: "sms",
28576
- Provider: config2.provider
28577
- }
28578
- },
28579
- {
28580
- customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28581
- }
28582
- );
28583
28502
  const statements = [];
28584
28503
  statements.push({
28585
28504
  Effect: "Allow",
@@ -28660,17 +28579,20 @@ async function createSMSIAMRole(config2) {
28660
28579
  Resource: "arn:aws:logs:*:*:log-group:/aws/lambda/wraps-sms-*"
28661
28580
  });
28662
28581
  }
28663
- new aws19.iam.RolePolicy("wraps-sms-policy", {
28664
- role: role.name,
28665
- policy: JSON.stringify({
28666
- Version: "2012-10-17",
28667
- Statement: statements
28668
- })
28582
+ return createServiceIAMRole({
28583
+ serviceName: "sms",
28584
+ provider: config2.provider,
28585
+ oidcProvider: config2.oidcProvider,
28586
+ vercelTeamSlug: config2.vercelTeamSlug,
28587
+ vercelProjectName: config2.vercelProjectName,
28588
+ additionalVercelPrincipals: ["lambda.amazonaws.com"],
28589
+ policyStatements: statements,
28590
+ extraTags: { Service: "sms" },
28591
+ customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28669
28592
  });
28670
- return role;
28671
28593
  }
28672
28594
  function createSMSConfigurationSet() {
28673
- return new aws19.pinpoint.Smsvoicev2ConfigurationSet("wraps-sms-config", {
28595
+ return new aws18.pinpoint.Smsvoicev2ConfigurationSet("wraps-sms-config", {
28674
28596
  name: "wraps-sms-config",
28675
28597
  defaultMessageType: "TRANSACTIONAL",
28676
28598
  tags: {
@@ -28680,7 +28602,7 @@ function createSMSConfigurationSet() {
28680
28602
  });
28681
28603
  }
28682
28604
  function createSMSOptOutList() {
28683
- return new aws19.pinpoint.Smsvoicev2OptOutList("wraps-sms-optouts", {
28605
+ return new aws18.pinpoint.Smsvoicev2OptOutList("wraps-sms-optouts", {
28684
28606
  name: "wraps-sms-optouts",
28685
28607
  tags: {
28686
28608
  ManagedBy: "wraps-cli",
@@ -28744,7 +28666,7 @@ async function createSMSPhoneNumber(phoneNumberType, optOutList) {
28744
28666
  }
28745
28667
  };
28746
28668
  if (existingArn) {
28747
- return new aws19.pinpoint.Smsvoicev2PhoneNumber(
28669
+ return new aws18.pinpoint.Smsvoicev2PhoneNumber(
28748
28670
  "wraps-sms-number",
28749
28671
  phoneConfig,
28750
28672
  {
@@ -28753,7 +28675,7 @@ async function createSMSPhoneNumber(phoneNumberType, optOutList) {
28753
28675
  }
28754
28676
  );
28755
28677
  }
28756
- return new aws19.pinpoint.Smsvoicev2PhoneNumber(
28678
+ return new aws18.pinpoint.Smsvoicev2PhoneNumber(
28757
28679
  "wraps-sms-number",
28758
28680
  phoneConfig,
28759
28681
  {
@@ -28782,10 +28704,10 @@ async function createSMSSQSResources() {
28782
28704
  Description: "Dead letter queue for failed SMS event processing"
28783
28705
  }
28784
28706
  };
28785
- const dlq = dlqUrl ? new aws19.sqs.Queue(dlqName, dlqConfig, {
28707
+ const dlq = dlqUrl ? new aws18.sqs.Queue(dlqName, dlqConfig, {
28786
28708
  import: dlqUrl,
28787
28709
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28788
- }) : new aws19.sqs.Queue(dlqName, dlqConfig, {
28710
+ }) : new aws18.sqs.Queue(dlqName, dlqConfig, {
28789
28711
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28790
28712
  });
28791
28713
  const queueConfig = {
@@ -28808,10 +28730,10 @@ async function createSMSSQSResources() {
28808
28730
  Description: "Queue for SMS events from SNS"
28809
28731
  }
28810
28732
  };
28811
- const queue = queueUrl ? new aws19.sqs.Queue(queueName, queueConfig, {
28733
+ const queue = queueUrl ? new aws18.sqs.Queue(queueName, queueConfig, {
28812
28734
  import: queueUrl,
28813
28735
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28814
- }) : new aws19.sqs.Queue(queueName, queueConfig, {
28736
+ }) : new aws18.sqs.Queue(queueName, queueConfig, {
28815
28737
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28816
28738
  });
28817
28739
  return { queue, dlq };
@@ -28827,13 +28749,13 @@ async function createSMSSNSResources(config2) {
28827
28749
  Description: "SNS topic for SMS delivery events"
28828
28750
  }
28829
28751
  };
28830
- const topic = topicArn ? new aws19.sns.Topic("wraps-sms-events-topic", topicConfig, {
28752
+ const topic = topicArn ? new aws18.sns.Topic("wraps-sms-events-topic", topicConfig, {
28831
28753
  import: topicArn,
28832
28754
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28833
- }) : new aws19.sns.Topic("wraps-sms-events-topic", topicConfig, {
28755
+ }) : new aws18.sns.Topic("wraps-sms-events-topic", topicConfig, {
28834
28756
  customTimeouts: { create: "2m", update: "2m", delete: "2m" }
28835
28757
  });
28836
- new aws19.sns.TopicPolicy("wraps-sms-events-topic-policy", {
28758
+ new aws18.sns.TopicPolicy("wraps-sms-events-topic-policy", {
28837
28759
  arn: topic.arn,
28838
28760
  policy: topic.arn.apply(
28839
28761
  (topicArn2) => JSON.stringify({
@@ -28850,7 +28772,7 @@ async function createSMSSNSResources(config2) {
28850
28772
  })
28851
28773
  )
28852
28774
  });
28853
- new aws19.sqs.QueuePolicy("wraps-sms-events-queue-policy", {
28775
+ new aws18.sqs.QueuePolicy("wraps-sms-events-queue-policy", {
28854
28776
  queueUrl: config2.queueUrl,
28855
28777
  policy: pulumi24.all([config2.queueArn, topic.arn]).apply(
28856
28778
  ([queueArn, topicArn2]) => JSON.stringify({
@@ -28869,7 +28791,7 @@ async function createSMSSNSResources(config2) {
28869
28791
  })
28870
28792
  )
28871
28793
  });
28872
- const subscription = new aws19.sns.TopicSubscription(
28794
+ const subscription = new aws18.sns.TopicSubscription(
28873
28795
  "wraps-sms-events-subscription",
28874
28796
  {
28875
28797
  topic: topic.arn,
@@ -28918,17 +28840,17 @@ async function createSMSDynamoDBTable() {
28918
28840
  Service: "sms"
28919
28841
  }
28920
28842
  };
28921
- return exists ? new aws19.dynamodb.Table(tableName, tableConfig, {
28843
+ return exists ? new aws18.dynamodb.Table(tableName, tableConfig, {
28922
28844
  import: tableName,
28923
28845
  customTimeouts: { create: "5m", update: "5m", delete: "5m" }
28924
- }) : new aws19.dynamodb.Table(tableName, tableConfig, {
28846
+ }) : new aws18.dynamodb.Table(tableName, tableConfig, {
28925
28847
  customTimeouts: { create: "5m", update: "5m", delete: "5m" }
28926
28848
  });
28927
28849
  }
28928
28850
  async function deploySMSLambdaFunction(config2) {
28929
28851
  const { getLambdaCode: getLambdaCode2 } = await Promise.resolve().then(() => (init_lambda(), lambda_exports));
28930
28852
  const codeDir = await getLambdaCode2("sms-event-processor");
28931
- const lambdaRole = new aws19.iam.Role("wraps-sms-lambda-role", {
28853
+ const lambdaRole = new aws18.iam.Role("wraps-sms-lambda-role", {
28932
28854
  name: "wraps-sms-lambda-role",
28933
28855
  assumeRolePolicy: JSON.stringify({
28934
28856
  Version: "2012-10-17",
@@ -28945,11 +28867,11 @@ async function deploySMSLambdaFunction(config2) {
28945
28867
  Service: "sms"
28946
28868
  }
28947
28869
  });
28948
- new aws19.iam.RolePolicyAttachment("wraps-sms-lambda-basic-execution", {
28870
+ new aws18.iam.RolePolicyAttachment("wraps-sms-lambda-basic-execution", {
28949
28871
  role: lambdaRole.name,
28950
28872
  policyArn: "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
28951
28873
  });
28952
- new aws19.iam.RolePolicy("wraps-sms-lambda-policy", {
28874
+ new aws18.iam.RolePolicy("wraps-sms-lambda-policy", {
28953
28875
  role: lambdaRole.name,
28954
28876
  policy: pulumi24.all([config2.tableName, config2.queueArn]).apply(
28955
28877
  ([tableName, queueArn]) => JSON.stringify({
@@ -28981,7 +28903,7 @@ async function deploySMSLambdaFunction(config2) {
28981
28903
  })
28982
28904
  )
28983
28905
  });
28984
- const eventProcessor = new aws19.lambda.Function(
28906
+ const eventProcessor = new aws18.lambda.Function(
28985
28907
  "wraps-sms-event-processor",
28986
28908
  {
28987
28909
  name: "wraps-sms-event-processor",
@@ -29009,7 +28931,7 @@ async function deploySMSLambdaFunction(config2) {
29009
28931
  customTimeouts: { create: "5m", update: "5m", delete: "2m" }
29010
28932
  }
29011
28933
  );
29012
- new aws19.lambda.EventSourceMapping(
28934
+ new aws18.lambda.EventSourceMapping(
29013
28935
  "wraps-sms-event-source-mapping",
29014
28936
  {
29015
28937
  eventSourceArn: config2.queueArn,
@@ -29025,7 +28947,7 @@ async function deploySMSLambdaFunction(config2) {
29025
28947
  return eventProcessor;
29026
28948
  }
29027
28949
  async function deploySMSStack(config2) {
29028
- const identity = await aws19.getCallerIdentity();
28950
+ const identity = await aws18.getCallerIdentity();
29029
28951
  const accountId = identity.accountId;
29030
28952
  let oidcProvider;
29031
28953
  if (config2.provider === "vercel" && config2.vercel) {