@awsless/awsless 0.0.18 → 0.0.20

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 (4) hide show
  1. package/dist/bin.cjs +548 -175
  2. package/dist/bin.js +549 -176
  3. package/dist/index.d.ts +441 -18
  4. package/package.json +3 -1
package/dist/bin.cjs CHANGED
@@ -191,6 +191,12 @@ var formatLogicalId = (id) => {
191
191
  var formatName = (name) => {
192
192
  return (0, import_change_case2.paramCase)(name);
193
193
  };
194
+ var formatArn = (props) => {
195
+ return sub("arn:${AWS::Partition}:${service}:${AWS::Region}:${AWS::AccountId}:${resource}${seperator}${resourceName}", {
196
+ seperator: "/",
197
+ ...props
198
+ });
199
+ };
194
200
 
195
201
  // src/formation/resource.ts
196
202
  var Resource = class {
@@ -200,13 +206,19 @@ var Resource = class {
200
206
  this.logicalId = formatLogicalId(`${logicalId}-${type.replace(/^AWS::/, "")}`);
201
207
  }
202
208
  logicalId;
209
+ tags = /* @__PURE__ */ new Map();
203
210
  deps = /* @__PURE__ */ new Set();
211
+ stack;
204
212
  dependsOn(...dependencies) {
205
213
  for (const dependency of dependencies) {
206
214
  this.deps.add(dependency);
207
215
  }
208
216
  return this;
209
217
  }
218
+ tag(key, value) {
219
+ this.tags.set(key, value);
220
+ return this;
221
+ }
210
222
  attr(name, value) {
211
223
  if (typeof value === "undefined") {
212
224
  return {};
@@ -215,12 +227,41 @@ var Resource = class {
215
227
  [name]: value
216
228
  };
217
229
  }
230
+ setStack(stack) {
231
+ this.stack = stack;
232
+ return this;
233
+ }
234
+ ref() {
235
+ return this.getAtt("ref");
236
+ }
237
+ getAtt(attr) {
238
+ return new Lazy((stack) => {
239
+ if (!this.stack) {
240
+ throw new TypeError("Resource stack not defined before building template");
241
+ }
242
+ const value = attr === "ref" ? ref(this.logicalId) : getAtt(this.logicalId, attr);
243
+ if (stack === this.stack) {
244
+ return value;
245
+ }
246
+ const name = `${this.stack.name}-${this.logicalId}-${attr}`;
247
+ this.stack.export(name, value);
248
+ return this.stack.import(name);
249
+ });
250
+ }
218
251
  toJSON() {
219
252
  return {
220
253
  [this.logicalId]: {
221
254
  Type: this.type,
222
255
  DependsOn: [...this.deps].map((dep) => dep.logicalId),
223
- Properties: this.properties()
256
+ Properties: {
257
+ ...this.tags.size ? {
258
+ Tags: Array.from(this.tags.entries()).map(([key, value]) => ({
259
+ Key: key,
260
+ Value: value
261
+ }))
262
+ } : {},
263
+ ...this.properties()
264
+ }
224
265
  }
225
266
  };
226
267
  }
@@ -230,6 +271,11 @@ var Group = class {
230
271
  this.children = children;
231
272
  }
232
273
  };
274
+ var Lazy = class {
275
+ constructor(callback) {
276
+ this.callback = callback;
277
+ }
278
+ };
233
279
 
234
280
  // src/formation/resource/iam/inline-policy.ts
235
281
  var InlinePolicy = class {
@@ -335,6 +381,7 @@ var Function = class extends Resource {
335
381
  this.policy = policy;
336
382
  this.name = formatName(this.props.name || logicalId);
337
383
  this.environmentVariables = props.environment ? { ...props.environment } : {};
384
+ this.tag("name", this.name);
338
385
  }
339
386
  name;
340
387
  role;
@@ -348,11 +395,15 @@ var Function = class extends Resource {
348
395
  this.environmentVariables[name] = value;
349
396
  return this;
350
397
  }
398
+ setVpc(vpc) {
399
+ this.props.vpc = vpc;
400
+ return this;
401
+ }
351
402
  get id() {
352
- return ref(this.logicalId);
403
+ return this.ref();
353
404
  }
354
405
  get arn() {
355
- return getAtt(this.logicalId, "Arn");
406
+ return this.getAtt("Arn");
356
407
  }
357
408
  get permissions() {
358
409
  return {
@@ -360,7 +411,14 @@ var Function = class extends Resource {
360
411
  "lambda:InvokeFunction",
361
412
  "lambda:InvokeAsync"
362
413
  ],
363
- resources: [this.arn]
414
+ resources: [
415
+ formatArn({
416
+ service: "lambda",
417
+ resource: "function",
418
+ resourceName: this.name,
419
+ seperator: ":"
420
+ })
421
+ ]
364
422
  };
365
423
  }
366
424
  properties() {
@@ -371,10 +429,17 @@ var Function = class extends Resource {
371
429
  Timeout: this.props.timeout?.toSeconds() ?? 10,
372
430
  Architectures: [this.props.architecture ?? "arm64"],
373
431
  Role: this.role.arn,
432
+ ...this.attr("ReservedConcurrentExecutions", this.props.reserved),
374
433
  ...this.props.code.toCodeJson(),
375
434
  EphemeralStorage: {
376
435
  Size: this.props.ephemeralStorageSize?.toMegaBytes() ?? 512
377
436
  },
437
+ ...this.props.vpc ? {
438
+ VpcConfig: {
439
+ SecurityGroupIds: this.props.vpc.securityGroupIds,
440
+ SubnetIds: this.props.vpc.subnetIds
441
+ }
442
+ } : {},
378
443
  Environment: {
379
444
  Variables: this.environmentVariables
380
445
  }
@@ -399,6 +464,7 @@ var Stack = class {
399
464
  } else {
400
465
  this.add(...item.children);
401
466
  if (item instanceof Resource) {
467
+ item.setStack(this);
402
468
  this.resources.add(item);
403
469
  }
404
470
  }
@@ -442,8 +508,24 @@ var Stack = class {
442
508
  toJSON() {
443
509
  const resources = {};
444
510
  const outputs = {};
511
+ const walk = (object) => {
512
+ for (const [key, value] of Object.entries(object)) {
513
+ if (!object.hasOwnProperty(key)) {
514
+ continue;
515
+ }
516
+ if (value instanceof Lazy) {
517
+ object[key] = value.callback(this);
518
+ continue;
519
+ }
520
+ if (typeof value === "object" && value !== null) {
521
+ walk(value);
522
+ }
523
+ }
524
+ };
445
525
  for (const resource of this) {
446
- Object.assign(resources, resource.toJSON());
526
+ const json2 = resource.toJSON();
527
+ walk(json2);
528
+ Object.assign(resources, json2);
447
529
  }
448
530
  for (const [name, value] of this.exports.entries()) {
449
531
  Object.assign(outputs, {
@@ -511,54 +593,33 @@ var toStack = ({ config, app, stackConfig, bootstrap: bootstrap2, usEastBootstra
511
593
  }
512
594
  return {
513
595
  stack,
514
- depends: stackConfig.depends
596
+ bindings
597
+ // depends: stackConfig.depends,
515
598
  };
516
599
  };
517
600
 
518
601
  // src/util/deployment.ts
519
- var createDependencyTree = (stacks) => {
602
+ var createDeploymentLine = (stacks) => {
520
603
  const list3 = stacks.map(({ stack, config }) => ({
521
604
  stack,
522
605
  depends: config?.depends?.map((dep) => dep.name) || []
523
606
  }));
524
- const findChildren = (list4, parents) => {
525
- const children = [];
526
- const rests = [];
527
- for (const item of list4) {
528
- const isChild = item.depends.filter((dep) => !parents.includes(dep)).length === 0;
529
- if (isChild) {
530
- children.push(item);
531
- } else {
532
- rests.push(item);
607
+ const line = [];
608
+ const deps = [];
609
+ let limit = 10;
610
+ while (deps.length < list3.length) {
611
+ const local = [];
612
+ for (const { stack, depends } of list3) {
613
+ if (!deps.includes(stack.name) && depends.filter((dep) => !deps.includes(dep)).length === 0) {
614
+ local.push(stack);
533
615
  }
534
616
  }
535
- if (!rests.length) {
536
- return children.map(({ stack }) => ({
537
- stack,
538
- children: []
539
- }));
617
+ if (limit-- <= 0) {
618
+ throw new Error(`Circular stack dependencies arn't allowed.`);
540
619
  }
541
- return children.map(({ stack }) => {
542
- return {
543
- stack,
544
- children: findChildren(rests, [...parents, stack.name])
545
- };
546
- });
547
- };
548
- return findChildren(list3, []);
549
- };
550
- var createDeploymentLine = (stacks) => {
551
- const line = [];
552
- const walk = (stacks2, level) => {
553
- stacks2.forEach((node) => {
554
- if (!line[level]) {
555
- line[level] = [];
556
- }
557
- line[level].push(node.stack);
558
- walk(node.children, level + 1);
559
- });
560
- };
561
- walk(stacks, 0);
620
+ deps.push(...local.map((stack) => stack.name));
621
+ line.push(local);
622
+ }
562
623
  return line;
563
624
  };
564
625
 
@@ -947,6 +1008,7 @@ var hasOnFailure = (config) => {
947
1008
  var MemorySizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(128)), "Minimum memory size is 128 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum memory size is 10 GB");
948
1009
  var TimeoutSchema = DurationSchema.refine(durationMin(Duration.seconds(10)), "Minimum timeout duration is 10 seconds").refine(durationMax(Duration.minutes(15)), "Maximum timeout duration is 15 minutes");
949
1010
  var EphemeralStorageSizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(512)), "Minimum ephemeral storage size is 512 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum ephemeral storage size is 10 GB");
1011
+ var ReservedConcurrentExecutionsSchema = import_zod6.z.number().int().min(0);
950
1012
  var EnvironmentSchema = import_zod6.z.record(import_zod6.z.string(), import_zod6.z.string()).optional();
951
1013
  var ArchitectureSchema = import_zod6.z.enum(["x86_64", "arm64"]);
952
1014
  var RetryAttemptsSchema = import_zod6.z.number().int().min(0).max(2);
@@ -957,8 +1019,12 @@ var RuntimeSchema = import_zod6.z.enum([
957
1019
  var FunctionSchema = import_zod6.z.union([
958
1020
  LocalFileSchema,
959
1021
  import_zod6.z.object({
960
- /** The file path ofthe function code. */
1022
+ /** The file path of the function code. */
961
1023
  file: LocalFileSchema,
1024
+ /** Put the function inside your global VPC.
1025
+ * @default false
1026
+ */
1027
+ vpc: import_zod6.z.boolean().optional(),
962
1028
  /** The amount of time that Lambda allows a function to run before stopping it.
963
1029
  * You can specify a size value from 1 second to 15 minutes.
964
1030
  * @default '10 seconds'
@@ -989,6 +1055,10 @@ var FunctionSchema = import_zod6.z.union([
989
1055
  * @default 2
990
1056
  */
991
1057
  retryAttempts: RetryAttemptsSchema.optional(),
1058
+ /** The number of simultaneous executions to reserve for the function.
1059
+ * You can specify a number from 0.
1060
+ */
1061
+ reserved: ReservedConcurrentExecutionsSchema.optional(),
992
1062
  /** Environment variable key-value pairs.
993
1063
  * @example
994
1064
  * {
@@ -1004,6 +1074,10 @@ var FunctionSchema = import_zod6.z.union([
1004
1074
  var schema = import_zod6.z.object({
1005
1075
  defaults: import_zod6.z.object({
1006
1076
  function: import_zod6.z.object({
1077
+ /** Put the function inside your global VPC.
1078
+ * @default false
1079
+ */
1080
+ vpc: import_zod6.z.boolean().default(false),
1007
1081
  /** The amount of time that Lambda allows a function to run before stopping it.
1008
1082
  * You can specify a size value from 1 second to 15 minutes.
1009
1083
  * @default '10 seconds'
@@ -1034,6 +1108,10 @@ var schema = import_zod6.z.object({
1034
1108
  * @default 2
1035
1109
  */
1036
1110
  retryAttempts: RetryAttemptsSchema.default(2),
1111
+ /** The number of simultaneous executions to reserve for the function.
1112
+ * You can specify a number from 0.
1113
+ */
1114
+ reserved: ReservedConcurrentExecutionsSchema.optional(),
1037
1115
  /** Environment variable key-value pairs.
1038
1116
  * @example
1039
1117
  * {
@@ -1074,6 +1152,12 @@ var functionPlugin = definePlugin({
1074
1152
  retryAttempts: props.retryAttempts,
1075
1153
  onFailure: getGlobalOnFailure(ctx)
1076
1154
  }).dependsOn(lambda);
1155
+ if (hasOnFailure(ctx.config)) {
1156
+ lambda.addPermissions({
1157
+ actions: ["sqs:SendMessage"],
1158
+ resources: [getGlobalOnFailure(ctx)]
1159
+ });
1160
+ }
1077
1161
  stack.add(invoke, lambda);
1078
1162
  }
1079
1163
  }
@@ -1085,12 +1169,36 @@ var toLambdaFunction = (ctx, id, fileOrProps) => {
1085
1169
  const lambda = new Function(id, {
1086
1170
  name: `${config.name}-${stack.name}-${id}`,
1087
1171
  code: Code.fromFile(id, props.file),
1088
- ...props
1172
+ ...props,
1173
+ vpc: void 0
1089
1174
  });
1090
1175
  lambda.addEnvironment("APP", config.name).addEnvironment("STAGE", config.stage).addEnvironment("STACK", stack.name);
1176
+ if (props.vpc) {
1177
+ lambda.setVpc({
1178
+ securityGroupIds: [
1179
+ ctx.bootstrap.import(`vpc-security-group-id`)
1180
+ ],
1181
+ subnetIds: [
1182
+ ctx.bootstrap.import(`public-subnet-1`),
1183
+ ctx.bootstrap.import(`public-subnet-2`)
1184
+ ]
1185
+ }).addPermissions({
1186
+ actions: [
1187
+ "ec2:CreateNetworkInterface",
1188
+ "ec2:DescribeNetworkInterfaces",
1189
+ "ec2:DeleteNetworkInterface",
1190
+ "ec2:AssignPrivateIpAddresses",
1191
+ "ec2:UnassignPrivateIpAddresses"
1192
+ ],
1193
+ resources: ["*"]
1194
+ });
1195
+ }
1091
1196
  if (props.runtime.startsWith("nodejs")) {
1092
1197
  lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1");
1093
1198
  }
1199
+ ctx.bind((other) => {
1200
+ other.addPermissions(lambda.permissions);
1201
+ });
1094
1202
  return lambda;
1095
1203
  };
1096
1204
 
@@ -1168,7 +1276,7 @@ var cronPlugin = definePlugin({
1168
1276
  name: "cron",
1169
1277
  schema: import_zod7.z.object({
1170
1278
  stacks: import_zod7.z.object({
1171
- /** Define the crons in your stack
1279
+ /** Define the crons in your stack.
1172
1280
  * @example
1173
1281
  * {
1174
1282
  * crons: {
@@ -1180,7 +1288,7 @@ var cronPlugin = definePlugin({
1180
1288
  * }
1181
1289
  * */
1182
1290
  crons: import_zod7.z.record(ResourceIdSchema, import_zod7.z.object({
1183
- /** The consuming lambda function properties */
1291
+ /** The consuming lambda function properties. */
1184
1292
  consumer: FunctionSchema,
1185
1293
  /** The scheduling expression.
1186
1294
  * @example 'cron(0 20 * * ? *)'
@@ -1214,6 +1322,7 @@ var Queue = class extends Resource {
1214
1322
  super("AWS::SQS::Queue", logicalId);
1215
1323
  this.props = props;
1216
1324
  this.name = formatName(this.props.name || logicalId);
1325
+ this.tag("name", this.name);
1217
1326
  }
1218
1327
  name;
1219
1328
  setDeadLetter(arn) {
@@ -1234,7 +1343,13 @@ var Queue = class extends Resource {
1234
1343
  "sqs:GetQueueUrl",
1235
1344
  "sqs:GetQueueAttributes"
1236
1345
  ],
1237
- resources: [this.arn]
1346
+ resources: [
1347
+ formatArn({
1348
+ service: "sqs",
1349
+ resource: "queue",
1350
+ resourceName: this.name
1351
+ })
1352
+ ]
1238
1353
  };
1239
1354
  }
1240
1355
  properties() {
@@ -1247,7 +1362,8 @@ var Queue = class extends Resource {
1247
1362
  VisibilityTimeout: this.props.visibilityTimeout?.toSeconds() ?? 30,
1248
1363
  ...this.props.deadLetterArn ? {
1249
1364
  RedrivePolicy: {
1250
- deadLetterTargetArn: this.props.deadLetterArn
1365
+ deadLetterTargetArn: this.props.deadLetterArn,
1366
+ maxReceiveCount: this.props.maxReceiveCount ?? 100
1251
1367
  }
1252
1368
  } : {}
1253
1369
  };
@@ -1303,8 +1419,7 @@ var SqsEventSource = class extends Group {
1303
1419
  sourceArn: props.queueArn,
1304
1420
  batchSize: props.batchSize ?? 10,
1305
1421
  maxBatchingWindow: props.maxBatchingWindow,
1306
- maxConcurrency: props.maxConcurrency,
1307
- onFailure: props.onFailure
1422
+ maxConcurrency: props.maxConcurrency
1308
1423
  });
1309
1424
  lambda.addPermissions({
1310
1425
  actions: [
@@ -1319,6 +1434,14 @@ var SqsEventSource = class extends Group {
1319
1434
  };
1320
1435
 
1321
1436
  // src/plugins/queue.ts
1437
+ var RetentionPeriodSchema = DurationSchema.refine(durationMin(Duration.minutes(1)), "Minimum retention period is 1 minute").refine(durationMax(Duration.days(14)), "Maximum retention period is 14 days");
1438
+ var VisibilityTimeoutSchema = DurationSchema.refine(durationMax(Duration.hours(12)), "Maximum visibility timeout is 12 hours");
1439
+ var DeliveryDelaySchema = DurationSchema.refine(durationMax(Duration.minutes(15)), "Maximum delivery delay is 15 minutes");
1440
+ var ReceiveMessageWaitTimeSchema = DurationSchema.refine(durationMin(Duration.seconds(1)), "Minimum receive message wait time is 1 second").refine(durationMax(Duration.seconds(20)), "Maximum receive message wait time is 20 seconds");
1441
+ var MaxMessageSizeSchema = SizeSchema.refine(sizeMin(Size.kiloBytes(1)), "Minimum max message size is 1 KB").refine(sizeMax(Size.kiloBytes(256)), "Maximum max message size is 256 KB");
1442
+ var BatchSizeSchema = import_zod8.z.number().int().min(1, "Minimum batch size is 1").max(1e4, "Maximum batch size is 10000");
1443
+ var MaxConcurrencySchema = import_zod8.z.number().int().min(2, "Minimum max concurrency is 2").max(1e3, "Maximum max concurrency is 1000");
1444
+ var MaxBatchingWindow = DurationSchema.refine(durationMax(Duration.minutes(5)), "Maximum max batching window is 5 minutes");
1322
1445
  var queuePlugin = definePlugin({
1323
1446
  name: "queue",
1324
1447
  schema: import_zod8.z.object({
@@ -1326,29 +1449,40 @@ var queuePlugin = definePlugin({
1326
1449
  /** Define the defaults properties for all queue's in your app. */
1327
1450
  queue: import_zod8.z.object({
1328
1451
  /** The number of seconds that Amazon SQS retains a message.
1329
- * You can specify a duration value from 1 minute to 14 days.
1452
+ * You can specify a duration from 1 minute to 14 days.
1330
1453
  * @default '7 days' */
1331
- retentionPeriod: DurationSchema.default("7 days"),
1454
+ retentionPeriod: RetentionPeriodSchema.default("7 days"),
1332
1455
  /** The length of time during which a message will be unavailable after a message is delivered from the queue.
1333
1456
  * This blocks other components from receiving the same message and gives the initial component time to process and delete the message from the queue.
1334
- * You can specify a duration value from 0 to 12 hours.
1457
+ * You can specify a duration from 0 to 12 hours.
1335
1458
  * @default '30 seconds' */
1336
- visibilityTimeout: DurationSchema.default("30 seconds"),
1459
+ visibilityTimeout: VisibilityTimeoutSchema.default("30 seconds"),
1337
1460
  /** The time in seconds for which the delivery of all messages in the queue is delayed.
1338
- * You can specify a duration value from 0 to 15 minutes.
1461
+ * You can specify a duration from 0 to 15 minutes.
1339
1462
  * @default '0 seconds' */
1340
- deliveryDelay: DurationSchema.default("0 seconds"),
1463
+ deliveryDelay: DeliveryDelaySchema.default("0 seconds"),
1341
1464
  /** Specifies the duration, in seconds,
1342
1465
  * that the ReceiveMessage action call waits until a message is in the queue in order to include it in the response,
1343
1466
  * rather than returning an empty response if a message isn't yet available.
1344
- * You can specify an integer from 1 to 20.
1345
- * You can specify a duration value from 1 to 20 seconds.
1346
- * @default '0 seconds' */
1347
- receiveMessageWaitTime: DurationSchema.default("0 seconds"),
1467
+ * You can specify a duration from 1 to 20 seconds.
1468
+ * Short polling is used as the default. */
1469
+ receiveMessageWaitTime: ReceiveMessageWaitTimeSchema.optional(),
1348
1470
  /** The limit of how many bytes that a message can contain before Amazon SQS rejects it.
1349
- * You can specify an size value from 1 KB to 256 KB.
1471
+ * You can specify an size from 1 KB to 256 KB.
1350
1472
  * @default '256 KB' */
1351
- maxMessageSize: SizeSchema.default("256 KB")
1473
+ maxMessageSize: MaxMessageSizeSchema.default("256 KB"),
1474
+ /** The maximum number of records in each batch that Lambda pulls from your queue and sends to your function.
1475
+ * Lambda passes all of the records in the batch to the function in a single call, up to the payload limit for synchronous invocation (6 MB).
1476
+ * You can specify an integer from 1 to 10000.
1477
+ * @default 10 */
1478
+ batchSize: BatchSizeSchema.default(10),
1479
+ /** Limits the number of concurrent instances that the queue worker can invoke.
1480
+ * You can specify an integer from 2 to 1000. */
1481
+ maxConcurrency: MaxConcurrencySchema.optional(),
1482
+ /** The maximum amount of time, that Lambda spends gathering records before invoking the function.
1483
+ * You can specify an duration from 0 seconds to 5 minutes.
1484
+ * @default '0 seconds' */
1485
+ maxBatchingWindow: MaxBatchingWindow.optional()
1352
1486
  }).default({})
1353
1487
  }).default({}),
1354
1488
  stacks: import_zod8.z.object({
@@ -1370,26 +1504,38 @@ var queuePlugin = definePlugin({
1370
1504
  /** The number of seconds that Amazon SQS retains a message.
1371
1505
  * You can specify a duration value from 1 minute to 14 days.
1372
1506
  * @default '7 days' */
1373
- retentionPeriod: DurationSchema.optional(),
1507
+ retentionPeriod: RetentionPeriodSchema.optional(),
1374
1508
  /** The length of time during which a message will be unavailable after a message is delivered from the queue.
1375
1509
  * This blocks other components from receiving the same message and gives the initial component time to process and delete the message from the queue.
1376
1510
  * You can specify a duration value from 0 to 12 hours.
1377
1511
  * @default '30 seconds' */
1378
- visibilityTimeout: DurationSchema.optional(),
1512
+ visibilityTimeout: VisibilityTimeoutSchema.optional(),
1379
1513
  /** The time in seconds for which the delivery of all messages in the queue is delayed.
1380
1514
  * You can specify a duration value from 0 to 15 minutes.
1381
1515
  * @default '0 seconds' */
1382
- deliveryDelay: DurationSchema.optional(),
1516
+ deliveryDelay: DeliveryDelaySchema.optional(),
1383
1517
  /** Specifies the duration, in seconds,
1384
1518
  * that the ReceiveMessage action call waits until a message is in the queue in order to include it in the response,
1385
1519
  * rather than returning an empty response if a message isn't yet available.
1386
1520
  * You can specify a duration value from 1 to 20 seconds.
1387
- * @default '0 seconds' */
1388
- receiveMessageWaitTime: DurationSchema.optional(),
1521
+ * Short polling is used as the default. */
1522
+ receiveMessageWaitTime: ReceiveMessageWaitTimeSchema.optional(),
1389
1523
  /** The limit of how many bytes that a message can contain before Amazon SQS rejects it.
1390
1524
  * You can specify an size value from 1 KB to 256 KB.
1391
1525
  * @default '256 KB' */
1392
- maxMessageSize: SizeSchema.optional()
1526
+ maxMessageSize: MaxMessageSizeSchema.optional(),
1527
+ /** The maximum number of records in each batch that Lambda pulls from your queue and sends to your function.
1528
+ * Lambda passes all of the records in the batch to the function in a single call, up to the payload limit for synchronous invocation (6 MB).
1529
+ * You can specify an integer from 1 to 10000.
1530
+ * @default 10 */
1531
+ batchSize: BatchSizeSchema.optional(),
1532
+ /** Limits the number of concurrent instances that the queue worker can invoke.
1533
+ * You can specify an integer from 2 to 1000. */
1534
+ maxConcurrency: MaxConcurrencySchema.optional(),
1535
+ /** The maximum amount of time, that Lambda spends gathering records before invoking the function.
1536
+ * You can specify an duration from 0 seconds to 5 minutes.
1537
+ * @default '0 seconds' */
1538
+ maxBatchingWindow: MaxBatchingWindow.optional()
1393
1539
  })
1394
1540
  ])
1395
1541
  ).optional()
@@ -1401,12 +1547,15 @@ var queuePlugin = definePlugin({
1401
1547
  const props = typeof functionOrProps === "string" ? { ...config.defaults.queue, consumer: functionOrProps } : { ...config.defaults.queue, ...functionOrProps };
1402
1548
  const queue2 = new Queue(id, {
1403
1549
  name: `${config.name}-${stack.name}-${id}`,
1550
+ deadLetterArn: getGlobalOnFailure(ctx),
1404
1551
  ...props
1405
1552
  });
1406
1553
  const lambda = toLambdaFunction(ctx, `queue-${id}`, props.consumer);
1407
1554
  const source = new SqsEventSource(id, lambda, {
1408
1555
  queueArn: queue2.arn,
1409
- onFailure: getGlobalOnFailure(ctx)
1556
+ batchSize: props.batchSize,
1557
+ maxConcurrency: props.maxConcurrency,
1558
+ maxBatchingWindow: props.maxBatchingWindow
1410
1559
  });
1411
1560
  stack.add(queue2, lambda, source);
1412
1561
  bind((lambda2) => {
@@ -1427,6 +1576,7 @@ var Table = class extends Resource {
1427
1576
  this.props = props;
1428
1577
  this.name = formatName(this.props.name || logicalId);
1429
1578
  this.indexes = { ...this.props.indexes || {} };
1579
+ this.tag("name", this.name);
1430
1580
  }
1431
1581
  name;
1432
1582
  indexes;
@@ -1459,7 +1609,13 @@ var Table = class extends Resource {
1459
1609
  "dynamodb:Query",
1460
1610
  "dynamodb:Scan"
1461
1611
  ],
1462
- resources: [this.arn]
1612
+ resources: [
1613
+ formatArn({
1614
+ service: "dynamodb",
1615
+ resource: "table",
1616
+ resourceName: this.name
1617
+ })
1618
+ ]
1463
1619
  };
1464
1620
  }
1465
1621
  attributeDefinitions() {
@@ -1693,6 +1849,7 @@ var Bucket = class extends Resource {
1693
1849
  super("AWS::S3::Bucket", logicalId);
1694
1850
  this.props = props;
1695
1851
  this.name = formatName(this.props.name || logicalId);
1852
+ this.tag("name", this.name);
1696
1853
  }
1697
1854
  name;
1698
1855
  get arn() {
@@ -1709,7 +1866,13 @@ var Bucket = class extends Resource {
1709
1866
  "s3:GetQueueUrl",
1710
1867
  "s3:GetQueueAttributes"
1711
1868
  ],
1712
- resources: [this.arn]
1869
+ resources: [
1870
+ formatArn({
1871
+ service: "s3",
1872
+ resource: "bucket",
1873
+ resourceName: this.name
1874
+ })
1875
+ ]
1713
1876
  };
1714
1877
  }
1715
1878
  properties() {
@@ -1762,6 +1925,7 @@ var Topic = class extends Resource {
1762
1925
  super("AWS::SNS::Topic", logicalId);
1763
1926
  this.props = props;
1764
1927
  this.name = formatName(this.props.name || logicalId);
1928
+ this.tag("name", this.name);
1765
1929
  }
1766
1930
  name;
1767
1931
  get arn() {
@@ -1770,7 +1934,13 @@ var Topic = class extends Resource {
1770
1934
  get permissions() {
1771
1935
  return {
1772
1936
  actions: ["sns:Publish"],
1773
- resources: [this.arn]
1937
+ resources: [
1938
+ formatArn({
1939
+ service: "sns",
1940
+ resource: "topic",
1941
+ resourceName: this.name
1942
+ })
1943
+ ]
1774
1944
  };
1775
1945
  }
1776
1946
  properties() {
@@ -2003,6 +2173,7 @@ var GraphQLApi = class extends Resource {
2003
2173
  super("AWS::AppSync::GraphQLApi", logicalId);
2004
2174
  this.props = props;
2005
2175
  this.name = formatName(this.props.name || logicalId);
2176
+ this.tag("name", this.name);
2006
2177
  }
2007
2178
  name;
2008
2179
  lambdaAuthProviders = [];
@@ -2655,7 +2826,7 @@ var domainPlugin = definePlugin({
2655
2826
  name: DomainNameSchema.optional(),
2656
2827
  /** The DNS record type. */
2657
2828
  type: import_zod15.z.enum(["A", "AAAA", "CAA", "CNAME", "DS", "MX", "NAPTR", "NS", "PTR", "SOA", "SPF", "SRV", "TXT"]),
2658
- /** The resource record cache time to live (TTL) */
2829
+ /** The resource record cache time to live (TTL). */
2659
2830
  ttl: DurationSchema,
2660
2831
  /** One or more values that correspond with the value that you specified for the Type property. */
2661
2832
  records: import_zod15.z.string().array()
@@ -2767,6 +2938,12 @@ var Vpc = class extends Resource {
2767
2938
  get id() {
2768
2939
  return ref(this.logicalId);
2769
2940
  }
2941
+ get defaultNetworkAcl() {
2942
+ return getAtt(this.logicalId, "DefaultNetworkAcl");
2943
+ }
2944
+ get defaultSecurityGroup() {
2945
+ return getAtt(this.logicalId, "DefaultSecurityGroup");
2946
+ }
2770
2947
  properties() {
2771
2948
  return {
2772
2949
  CidrBlock: this.props.cidrBlock.ip
@@ -2778,6 +2955,7 @@ var RouteTable = class extends Resource {
2778
2955
  super("AWS::EC2::RouteTable", logicalId);
2779
2956
  this.props = props;
2780
2957
  this.name = formatName(props.name || logicalId);
2958
+ this.tag("name", this.name);
2781
2959
  }
2782
2960
  name;
2783
2961
  get id() {
@@ -2785,11 +2963,7 @@ var RouteTable = class extends Resource {
2785
2963
  }
2786
2964
  properties() {
2787
2965
  return {
2788
- VpcId: this.props.vpcId,
2789
- Tags: [{
2790
- Key: "name",
2791
- Value: this.name
2792
- }]
2966
+ VpcId: this.props.vpcId
2793
2967
  };
2794
2968
  }
2795
2969
  };
@@ -2942,6 +3116,7 @@ var vpcPlugin = definePlugin({
2942
3116
  routeTableId: publicRouteTable.id,
2943
3117
  destination: Peer.anyIpv4()
2944
3118
  }).dependsOn(gateway, publicRouteTable);
3119
+ bootstrap2.export("vpc-security-group-id", vpc.defaultSecurityGroup);
2945
3120
  bootstrap2.export(`vpc-id`, vpc.id);
2946
3121
  bootstrap2.add(
2947
3122
  vpc,
@@ -2984,7 +3159,9 @@ var SecurityGroup = class extends Resource {
2984
3159
  constructor(logicalId, props) {
2985
3160
  super("AWS::EC2::SecurityGroup", logicalId);
2986
3161
  this.props = props;
3162
+ this.name = formatName(props.name ?? logicalId);
2987
3163
  }
3164
+ name;
2988
3165
  ingress = [];
2989
3166
  egress = [];
2990
3167
  get id() {
@@ -3009,7 +3186,7 @@ var SecurityGroup = class extends Resource {
3009
3186
  properties() {
3010
3187
  return {
3011
3188
  VpcId: this.props.vpcId,
3012
- GroupName: this.logicalId,
3189
+ GroupName: this.name,
3013
3190
  GroupDescription: this.props.description,
3014
3191
  SecurityGroupIngress: this.ingress.map((rule) => ({
3015
3192
  Description: rule.description || "",
@@ -3420,6 +3597,7 @@ var Collection = class extends Resource {
3420
3597
  super("AWS::OpenSearchServerless::Collection", logicalId);
3421
3598
  this.props = props;
3422
3599
  this.name = this.props.name || logicalId;
3600
+ this.tag("name", this.name);
3423
3601
  }
3424
3602
  name;
3425
3603
  get id() {
@@ -3431,6 +3609,18 @@ var Collection = class extends Resource {
3431
3609
  get endpoint() {
3432
3610
  return getAtt(this.logicalId, "CollectionEndpoint");
3433
3611
  }
3612
+ get permissions() {
3613
+ return {
3614
+ actions: ["aoss:APIAccessAll"],
3615
+ resources: [
3616
+ formatArn({
3617
+ service: "aoss",
3618
+ resource: "collection",
3619
+ resourceName: this.name
3620
+ })
3621
+ ]
3622
+ };
3623
+ }
3434
3624
  properties() {
3435
3625
  return {
3436
3626
  Name: this.name,
@@ -3455,10 +3645,155 @@ var searchPlugin = definePlugin({
3455
3645
  type: "search"
3456
3646
  });
3457
3647
  bind((lambda) => {
3458
- lambda.addPermissions({
3459
- actions: ["aoss:APIAccessAll"],
3460
- resources: [collection.arn]
3461
- });
3648
+ lambda.addPermissions(collection.permissions);
3649
+ });
3650
+ }
3651
+ }
3652
+ });
3653
+
3654
+ // src/plugins/cache.ts
3655
+ var import_zod19 = require("zod");
3656
+
3657
+ // src/formation/resource/memorydb/cluster.ts
3658
+ var Cluster = class extends Resource {
3659
+ constructor(logicalId, props) {
3660
+ super("AWS::MemoryDB::Cluster", logicalId);
3661
+ this.props = props;
3662
+ this.name = formatName(this.props.name || logicalId);
3663
+ this.tag("name", this.name);
3664
+ }
3665
+ name;
3666
+ get status() {
3667
+ return this.getAtt("Status");
3668
+ }
3669
+ get arn() {
3670
+ return this.getAtt("ARN");
3671
+ }
3672
+ get address() {
3673
+ return this.getAtt("ClusterEndpoint.Address");
3674
+ }
3675
+ get port() {
3676
+ return this.getAtt("ClusterEndpoint.Port");
3677
+ }
3678
+ properties() {
3679
+ return {
3680
+ ClusterName: this.name,
3681
+ ClusterEndpoint: {
3682
+ Port: this.props.port
3683
+ },
3684
+ Port: this.props.port,
3685
+ ...this.attr("Description", this.props.description),
3686
+ ACLName: this.props.aclName,
3687
+ EngineVersion: this.props.engine ?? "7.0",
3688
+ ...this.attr("SubnetGroupName", this.props.subnetGroupName),
3689
+ ...this.attr("SecurityGroupIds", this.props.securityGroupIds),
3690
+ NodeType: "db." + this.props.type,
3691
+ NumReplicasPerShard: this.props.replicasPerShard ?? 1,
3692
+ NumShards: this.props.shards ?? 1,
3693
+ TLSEnabled: this.props.tls ?? false,
3694
+ DataTiering: this.props.dataTiering ? "true" : "false",
3695
+ AutoMinorVersionUpgrade: this.props.autoMinorVersionUpgrade ?? true,
3696
+ MaintenanceWindow: this.props.maintenanceWindow ?? "Sat:02:00-Sat:05:00"
3697
+ };
3698
+ }
3699
+ };
3700
+
3701
+ // src/formation/resource/memorydb/subnet-group.ts
3702
+ var SubnetGroup = class extends Resource {
3703
+ constructor(logicalId, props) {
3704
+ super("AWS::MemoryDB::SubnetGroup", logicalId);
3705
+ this.props = props;
3706
+ this.name = formatName(this.props.name || logicalId);
3707
+ }
3708
+ name;
3709
+ get arn() {
3710
+ return getAtt(this.logicalId, "Arn");
3711
+ }
3712
+ properties() {
3713
+ return {
3714
+ SubnetGroupName: this.name,
3715
+ SubnetIds: this.props.subnetIds,
3716
+ ...this.attr("Description", this.props.description)
3717
+ };
3718
+ }
3719
+ };
3720
+
3721
+ // src/plugins/cache.ts
3722
+ var TypeSchema = import_zod19.z.enum([
3723
+ "t4g.small",
3724
+ "t4g.medium",
3725
+ "r6g.large",
3726
+ "r6g.xlarge",
3727
+ "r6g.2xlarge",
3728
+ "r6g.4xlarge",
3729
+ "r6g.8xlarge",
3730
+ "r6g.12xlarge",
3731
+ "r6g.16xlarge",
3732
+ "r6gd.xlarge",
3733
+ "r6gd.2xlarge",
3734
+ "r6gd.4xlarge",
3735
+ "r6gd.8xlarge"
3736
+ ]);
3737
+ var PortSchema = import_zod19.z.number().int().min(1).max(5e4);
3738
+ var ShardsSchema = import_zod19.z.number().int().min(0).max(100);
3739
+ var ReplicasPerShardSchema = import_zod19.z.number().int().min(0).max(5);
3740
+ var EngineSchema = import_zod19.z.enum(["7.0", "6.2"]);
3741
+ var cachePlugin = definePlugin({
3742
+ name: "cache",
3743
+ schema: import_zod19.z.object({
3744
+ stacks: import_zod19.z.object({
3745
+ /** Define the caches in your stack.
3746
+ * For access to the cache put your functions inside the global VPC.
3747
+ * @example
3748
+ * {
3749
+ * caches: {
3750
+ * CACHE_NAME: {
3751
+ * type: 't4g.small'
3752
+ * }
3753
+ * }
3754
+ * }
3755
+ */
3756
+ caches: import_zod19.z.record(
3757
+ ResourceIdSchema,
3758
+ import_zod19.z.object({
3759
+ type: TypeSchema.default("t4g.small"),
3760
+ port: PortSchema.default(6379),
3761
+ shards: ShardsSchema.default(1),
3762
+ replicasPerShard: ReplicasPerShardSchema.default(1),
3763
+ engine: EngineSchema.default("7.0"),
3764
+ dataTiering: import_zod19.z.boolean().default(false)
3765
+ })
3766
+ ).optional()
3767
+ }).array()
3768
+ }),
3769
+ onStack({ config, stack, stackConfig, bootstrap: bootstrap2, bind }) {
3770
+ for (const [id, props] of Object.entries(stackConfig.caches || {})) {
3771
+ const name = `${config.name}-${stack.name}-${id}`;
3772
+ const subnetGroup = new SubnetGroup(id, {
3773
+ name,
3774
+ subnetIds: [
3775
+ bootstrap2.import(`private-subnet-1`),
3776
+ bootstrap2.import(`private-subnet-2`)
3777
+ ]
3778
+ });
3779
+ const securityGroup = new SecurityGroup(id, {
3780
+ name,
3781
+ vpcId: bootstrap2.import(`vpc-id`),
3782
+ description: name
3783
+ });
3784
+ const port = Port.tcp(props.port);
3785
+ securityGroup.addIngressRule(Peer.anyIpv4(), port);
3786
+ securityGroup.addIngressRule(Peer.anyIpv6(), port);
3787
+ const cluster = new Cluster(id, {
3788
+ name,
3789
+ aclName: "open-access",
3790
+ securityGroupIds: [securityGroup.id],
3791
+ subnetGroupName: subnetGroup.name,
3792
+ ...props
3793
+ }).dependsOn(subnetGroup, securityGroup);
3794
+ stack.add(subnetGroup, securityGroup, cluster);
3795
+ bind((lambda) => {
3796
+ lambda.addEnvironment(`CACHE_${stack.name}_${id}_HOST`, cluster.address).addEnvironment(`CACHE_${stack.name}_${id}_PORT`, props.port.toString());
3462
3797
  });
3463
3798
  }
3464
3799
  }
@@ -3469,6 +3804,7 @@ var defaultPlugins = [
3469
3804
  extendPlugin,
3470
3805
  vpcPlugin,
3471
3806
  functionPlugin,
3807
+ cachePlugin,
3472
3808
  cronPlugin,
3473
3809
  queuePlugin,
3474
3810
  tablePlugin,
@@ -3650,7 +3986,7 @@ var toApp = async (config, filters) => {
3650
3986
  config.stacks.filter((stack) => filters.includes(stack.name))
3651
3987
  );
3652
3988
  for (const stackConfig of filterdStacks) {
3653
- const { stack } = toStack({
3989
+ const { stack, bindings: bindings2 } = toStack({
3654
3990
  config,
3655
3991
  stackConfig,
3656
3992
  bootstrap: bootstrap2,
@@ -3659,7 +3995,7 @@ var toApp = async (config, filters) => {
3659
3995
  app
3660
3996
  });
3661
3997
  app.add(stack);
3662
- stacks.push({ stack, config: stackConfig });
3998
+ stacks.push({ stack, config: stackConfig, bindings: bindings2 });
3663
3999
  }
3664
4000
  for (const plugin of plugins) {
3665
4001
  for (const stack of app.stacks) {
@@ -3681,23 +4017,31 @@ var toApp = async (config, filters) => {
3681
4017
  bind2(fn);
3682
4018
  }
3683
4019
  }
3684
- let dependencyTree = createDependencyTree(stacks);
4020
+ for (const entry of stacks) {
4021
+ for (const dep of entry.config.depends || []) {
4022
+ const depStack = stacks.find((entry2) => entry2.config.name === dep.name);
4023
+ if (!depStack) {
4024
+ throw new Error(`Stack dependency not found: ${dep.name}`);
4025
+ }
4026
+ const functions2 = entry.stack.find(Function);
4027
+ for (const bind2 of depStack.bindings) {
4028
+ for (const fn of functions2) {
4029
+ bind2(fn);
4030
+ }
4031
+ }
4032
+ }
4033
+ }
4034
+ const deploymentLine = createDeploymentLine(stacks);
3685
4035
  if (bootstrap2.size > 0) {
3686
- dependencyTree = [{
3687
- stack: bootstrap2,
3688
- children: dependencyTree
3689
- }];
4036
+ deploymentLine.unshift([bootstrap2]);
3690
4037
  }
3691
4038
  if (usEastBootstrap.size > 0) {
3692
- dependencyTree = [{
3693
- stack: usEastBootstrap,
3694
- children: dependencyTree
3695
- }];
4039
+ deploymentLine.unshift([usEastBootstrap]);
3696
4040
  }
3697
4041
  return {
3698
4042
  app,
3699
4043
  plugins,
3700
- dependencyTree
4044
+ deploymentLine
3701
4045
  };
3702
4046
  };
3703
4047
 
@@ -3721,17 +4065,17 @@ var getCredentials = (profile) => {
3721
4065
  };
3722
4066
 
3723
4067
  // src/schema/app.ts
3724
- var import_zod22 = require("zod");
4068
+ var import_zod23 = require("zod");
3725
4069
 
3726
4070
  // src/schema/stack.ts
3727
- var import_zod19 = require("zod");
3728
- var StackSchema = import_zod19.z.object({
4071
+ var import_zod20 = require("zod");
4072
+ var StackSchema = import_zod20.z.object({
3729
4073
  name: ResourceIdSchema,
3730
- depends: import_zod19.z.array(import_zod19.z.lazy(() => StackSchema)).optional()
4074
+ depends: import_zod20.z.array(import_zod20.z.lazy(() => StackSchema)).optional()
3731
4075
  });
3732
4076
 
3733
4077
  // src/schema/region.ts
3734
- var import_zod20 = require("zod");
4078
+ var import_zod21 = require("zod");
3735
4079
  var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
3736
4080
  var AF = ["af-south-1"];
3737
4081
  var AP = ["ap-east-1", "ap-south-2", "ap-southeast-3", "ap-southeast-4", "ap-south-1", "ap-northeast-3", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1"];
@@ -3748,45 +4092,47 @@ var regions = [
3748
4092
  ...ME,
3749
4093
  ...SA
3750
4094
  ];
3751
- var RegionSchema = import_zod20.z.enum(regions);
4095
+ var RegionSchema = import_zod21.z.enum(regions);
3752
4096
 
3753
4097
  // src/schema/plugin.ts
3754
- var import_zod21 = require("zod");
3755
- var PluginSchema = import_zod21.z.object({
3756
- name: import_zod21.z.string(),
3757
- schema: import_zod21.z.custom().optional(),
4098
+ var import_zod22 = require("zod");
4099
+ var PluginSchema = import_zod22.z.object({
4100
+ name: import_zod22.z.string(),
4101
+ schema: import_zod22.z.custom().optional(),
3758
4102
  // depends: z.array(z.lazy(() => PluginSchema)).optional(),
3759
- onApp: import_zod21.z.function().returns(import_zod21.z.void()).optional(),
3760
- onStack: import_zod21.z.function().returns(import_zod21.z.any()).optional(),
3761
- onResource: import_zod21.z.function().returns(import_zod21.z.any()).optional()
4103
+ onApp: import_zod22.z.function().returns(import_zod22.z.void()).optional(),
4104
+ onStack: import_zod22.z.function().returns(import_zod22.z.any()).optional(),
4105
+ onResource: import_zod22.z.function().returns(import_zod22.z.any()).optional()
3762
4106
  // bind: z.function().optional(),
3763
4107
  });
3764
4108
 
3765
4109
  // src/schema/app.ts
3766
- var AppSchema = import_zod22.z.object({
4110
+ var AppSchema = import_zod23.z.object({
3767
4111
  /** App name */
3768
4112
  name: ResourceIdSchema,
3769
4113
  /** The AWS region to deploy to. */
3770
4114
  region: RegionSchema,
3771
4115
  /** The AWS profile to deploy to. */
3772
- profile: import_zod22.z.string(),
4116
+ profile: import_zod23.z.string(),
3773
4117
  /** The deployment stage.
3774
4118
  * @default 'prod'
3775
4119
  */
3776
- stage: import_zod22.z.string().regex(/[a-z]+/).default("prod"),
4120
+ stage: import_zod23.z.string().regex(/[a-z]+/).default("prod"),
3777
4121
  /** Default properties. */
3778
- defaults: import_zod22.z.object({}).default({}),
4122
+ defaults: import_zod23.z.object({}).default({}),
3779
4123
  /** The application stacks. */
3780
- stacks: import_zod22.z.array(StackSchema).min(1).refine((stacks) => {
4124
+ stacks: import_zod23.z.array(StackSchema).min(1).refine((stacks) => {
3781
4125
  const unique = new Set(stacks.map((stack) => stack.name));
3782
4126
  return unique.size === stacks.length;
3783
4127
  }, "Must be an array of unique stacks"),
3784
4128
  /** Custom plugins. */
3785
- plugins: import_zod22.z.array(PluginSchema).optional()
4129
+ plugins: import_zod23.z.array(PluginSchema).optional()
3786
4130
  });
3787
4131
 
3788
4132
  // src/util/import.ts
3789
- var import_core = require("@swc/core");
4133
+ var import_rollup3 = require("rollup");
4134
+ var import_rollup_plugin_swc32 = require("rollup-plugin-swc3");
4135
+ var import_rollup_plugin_replace = __toESM(require("rollup-plugin-replace"), 1);
3790
4136
  var import_path2 = require("path");
3791
4137
  var import_promises5 = require("fs/promises");
3792
4138
 
@@ -3835,54 +4181,25 @@ var fileExist = async (file) => {
3835
4181
  };
3836
4182
 
3837
4183
  // src/util/import.ts
3838
- var resolveFileNameExtension = async (path) => {
3839
- const options = [
3840
- "",
3841
- ".ts",
3842
- ".js",
3843
- "/index.ts",
3844
- "/index.js"
3845
- ];
3846
- for (const option of options) {
3847
- const file = path.replace(/\.js$/, "") + option;
3848
- let stat;
3849
- try {
3850
- stat = await (0, import_promises5.lstat)(file);
3851
- } catch (error) {
3852
- continue;
3853
- }
3854
- if (stat.isFile()) {
3855
- return file;
3856
- }
3857
- }
3858
- throw new Error(`Failed to load file: ${path}`);
3859
- };
3860
- var resolveDir = (path) => {
3861
- return (0, import_path2.dirname)(path).replace(directories.root + "/", "");
3862
- };
3863
4184
  var importFile = async (path) => {
3864
- const load = async (file) => {
3865
- debug("Load file:", style.info(file));
3866
- let { code: code2 } = await (0, import_core.transformFile)(file, {
3867
- isModule: true
3868
- });
3869
- const path2 = (0, import_path2.dirname)(file);
3870
- const dir = resolveDir(file);
3871
- code2 = code2.replaceAll("__dirname", `"${dir}"`);
3872
- const matches = code2.match(/(import|export)\s*{\s*[a-z0-9\_\,\s\*]+\s*}\s*from\s*('|")(\.\.?[\/a-z0-9\_\-\.]+)('|");?/ig);
3873
- if (!matches)
3874
- return code2;
3875
- await Promise.all(matches?.map(async (match) => {
3876
- const parts = /('|")(\.\.?[\/a-z0-9\_\-\.]+)('|")/ig.exec(match);
3877
- const from = parts[2];
3878
- const file2 = await resolveFileNameExtension((0, import_path2.join)(path2, from));
3879
- const result = await load(file2);
3880
- code2 = code2.replace(match, result);
3881
- }));
3882
- return code2;
3883
- };
3884
- const code = await load(path);
4185
+ const bundle = await (0, import_rollup3.rollup)({
4186
+ input: path,
4187
+ plugins: [
4188
+ (0, import_rollup_plugin_replace.default)({
4189
+ __dirname: (id) => `'${(0, import_path2.dirname)(id)}'`
4190
+ }),
4191
+ (0, import_rollup_plugin_swc32.swc)({
4192
+ minify: false
4193
+ })
4194
+ ]
4195
+ });
3885
4196
  const outputFile = (0, import_path2.join)(directories.cache, "config.js");
4197
+ const result = await bundle.generate({
4198
+ format: "esm",
4199
+ exports: "default"
4200
+ });
4201
+ const output = result.output[0];
4202
+ const code = output.code;
3886
4203
  await (0, import_promises5.mkdir)(directories.cache, { recursive: true });
3887
4204
  await (0, import_promises5.writeFile)(outputFile, code);
3888
4205
  debug("Save config file:", style.info(outputFile));
@@ -4184,7 +4501,7 @@ var Renderer = class {
4184
4501
  flushing = false;
4185
4502
  screen = [];
4186
4503
  width() {
4187
- return this.output.columns;
4504
+ return this.output.columns - 1;
4188
4505
  }
4189
4506
  height() {
4190
4507
  return this.output.rows;
@@ -5022,12 +5339,73 @@ var assetPublisher = (config, app) => {
5022
5339
  };
5023
5340
  };
5024
5341
 
5342
+ // src/cli/ui/complex/deployer.ts
5343
+ var stacksDeployer = (deploymentLine) => {
5344
+ const stackNames = deploymentLine.map((line) => line.map((stack) => stack.name)).flat();
5345
+ const stackNameSize = Math.max(...stackNames.map((name) => name.length));
5346
+ return (term) => {
5347
+ const ui = {};
5348
+ term.out.gap();
5349
+ for (const i in deploymentLine) {
5350
+ const line = flexLine(
5351
+ term,
5352
+ [" "],
5353
+ [
5354
+ " ",
5355
+ style.placeholder(Number(i) + 1),
5356
+ style.placeholder(" \u2500\u2500")
5357
+ ]
5358
+ );
5359
+ term.out.write(line);
5360
+ term.out.write(br());
5361
+ for (const stack of deploymentLine[i]) {
5362
+ const icon = new Signal(" ");
5363
+ const name = new Signal(style.label.dim(stack.name));
5364
+ const status2 = new Signal(style.info.dim("waiting"));
5365
+ let stopSpinner;
5366
+ term.out.write([
5367
+ icon,
5368
+ " ",
5369
+ name,
5370
+ " ".repeat(stackNameSize - stack.name.length),
5371
+ " ",
5372
+ style.placeholder(symbol.pointerSmall),
5373
+ " ",
5374
+ status2,
5375
+ br()
5376
+ ]);
5377
+ ui[stack.name] = {
5378
+ start: (value) => {
5379
+ const [spinner, stop] = createSpinner();
5380
+ name.set(style.label(stack.name));
5381
+ icon.set(spinner);
5382
+ status2.set(style.warning(value));
5383
+ stopSpinner = stop;
5384
+ },
5385
+ done(value) {
5386
+ stopSpinner();
5387
+ icon.set(style.success(symbol.success));
5388
+ status2.set(style.success(value));
5389
+ },
5390
+ fail(value) {
5391
+ stopSpinner();
5392
+ icon.set(style.error(symbol.error));
5393
+ status2.set(style.error(value));
5394
+ }
5395
+ };
5396
+ }
5397
+ }
5398
+ term.out.gap();
5399
+ return ui;
5400
+ };
5401
+ };
5402
+
5025
5403
  // src/cli/command/deploy.ts
5026
5404
  var deploy = (program2) => {
5027
5405
  program2.command("deploy").argument("[stacks...]", "Optionally filter stacks to deploy").description("Deploy your app to AWS").action(async (filters) => {
5028
5406
  await layout(async (config, write) => {
5029
5407
  await write(bootstrapDeployer(config));
5030
- const { app, dependencyTree } = await toApp(config, filters);
5408
+ const { app, deploymentLine } = await toApp(config, filters);
5031
5409
  const stackNames = app.stacks.map((stack) => stack.name);
5032
5410
  const formattedFilter = stackNames.map((i) => style.info(i)).join(style.placeholder(", "));
5033
5411
  debug("Stacks to deploy", formattedFilter);
@@ -5041,26 +5419,21 @@ var deploy = (program2) => {
5041
5419
  await write(assetBuilder(app));
5042
5420
  await write(assetPublisher(config, app));
5043
5421
  await write(templateBuilder(app));
5044
- const statuses = {};
5045
- for (const stack of app) {
5046
- statuses[stack.name] = new Signal(style.info("waiting"));
5047
- }
5048
5422
  const doneDeploying = write(loadingDialog("Deploying stacks to AWS..."));
5049
- write(stackTree(dependencyTree, statuses));
5050
5423
  const client = new StackClient(app, config.account, config.region, config.credentials);
5051
- const deploymentLine = createDeploymentLine(dependencyTree);
5052
- for (const stacks of deploymentLine) {
5053
- const results = await Promise.allSettled(stacks.map(async (stack) => {
5054
- const signal = statuses[stack.name];
5055
- signal.set(style.warning("deploying"));
5424
+ const ui = write(stacksDeployer(deploymentLine));
5425
+ for (const line of deploymentLine) {
5426
+ const results = await Promise.allSettled(line.map(async (stack) => {
5427
+ const item = ui[stack.name];
5428
+ item.start("deploying");
5056
5429
  try {
5057
5430
  await client.deploy(stack);
5058
5431
  } catch (error) {
5059
5432
  debugError(error);
5060
- signal.set(style.error("failed"));
5433
+ item.fail("failed");
5061
5434
  throw error;
5062
5435
  }
5063
- signal.set(style.success("deployed"));
5436
+ item.done("deployed");
5064
5437
  }));
5065
5438
  for (const result of results) {
5066
5439
  if (result.status === "rejected") {