@awsless/awsless 0.0.41 → 0.0.43

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/bin.cjs CHANGED
@@ -617,7 +617,7 @@ var createDeploymentLine = (stacks) => {
617
617
  depends: config?.depends?.map((dep) => dep.name) || []
618
618
  }));
619
619
  const names = stacks.map(({ stack }) => stack.name);
620
- const line = [];
620
+ const line2 = [];
621
621
  const deps = [];
622
622
  let limit = 100;
623
623
  while (deps.length < list3.length) {
@@ -632,9 +632,9 @@ var createDeploymentLine = (stacks) => {
632
632
  throw new Error(`Circular stack dependencies arn't allowed: ${circularNames}`);
633
633
  }
634
634
  deps.push(...local.map((stack) => stack.name));
635
- line.push(local);
635
+ line2.push(local);
636
636
  }
637
- return line;
637
+ return line2;
638
638
  };
639
639
 
640
640
  // src/plugins/cron/index.ts
@@ -647,23 +647,30 @@ var definePlugin = (plugin) => plugin;
647
647
  var import_zod = require("zod");
648
648
  var import_aws_cron_expression_validator = require("aws-cron-expression-validator");
649
649
  var RateExpressionSchema = import_zod.z.custom((value) => {
650
- return import_zod.z.string().regex(/rate\([0-9]+ (seconds?|minutes?|hours?|days?)\)/).refine((rate) => {
651
- const [str] = rate.substring(5).split(" ");
650
+ return import_zod.z.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).refine((rate) => {
651
+ const [str] = rate.split(" ");
652
652
  const number = parseInt(str);
653
653
  return number > 0;
654
654
  }).safeParse(value).success;
655
- }, "Invalid rate expression");
655
+ }, { message: "Invalid rate expression" }).transform((rate) => {
656
+ const [str] = rate.split(" ");
657
+ const number = parseInt(str);
658
+ const more = rate.endsWith("s");
659
+ if (more && number === 1) {
660
+ return `rate(${rate.substring(0, rate.length - 1)})`;
661
+ }
662
+ return `rate(${rate})`;
663
+ });
656
664
  var CronExpressionSchema = import_zod.z.custom((value) => {
657
- return import_zod.z.string().startsWith("cron(").endsWith(")").safeParse(value).success;
658
- }, "Invalid cron expression").superRefine((value, ctx) => {
659
- const cron = value.substring(5, value.length - 1);
665
+ return import_zod.z.string().safeParse(value).success;
666
+ }, { message: "Invalid cron expression" }).superRefine((value, ctx) => {
660
667
  try {
661
- (0, import_aws_cron_expression_validator.awsCronExpressionValidator)(cron);
668
+ (0, import_aws_cron_expression_validator.awsCronExpressionValidator)(value);
662
669
  } catch (error) {
663
670
  if (error instanceof Error) {
664
671
  ctx.addIssue({
665
672
  code: import_zod.z.ZodIssueCode.custom,
666
- message: error.message
673
+ message: `Invalid cron expression: ${error.message}`
667
674
  });
668
675
  } else {
669
676
  ctx.addIssue({
@@ -672,6 +679,8 @@ var CronExpressionSchema = import_zod.z.custom((value) => {
672
679
  });
673
680
  }
674
681
  }
682
+ }).transform((value) => {
683
+ return `cron(${value.trim()})`;
675
684
  });
676
685
  var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
677
686
 
@@ -735,7 +744,7 @@ function toDuration(duration) {
735
744
  return Duration.days(0);
736
745
  }
737
746
  var DurationSchema = import_zod2.z.custom((value) => {
738
- return import_zod2.z.string().regex(/[0-9]+ (seconds?|minutes?|hours?|days?)/).safeParse(value).success;
747
+ return import_zod2.z.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).safeParse(value).success;
739
748
  }, "Invalid duration").transform(toDuration);
740
749
  var durationMin = (min) => {
741
750
  return (duration) => {
@@ -761,8 +770,9 @@ var LocalFileSchema = import_zod3.z.string().refine(async (path) => {
761
770
  }, `File doesn't exist`);
762
771
 
763
772
  // src/schema/resource-id.ts
773
+ var import_change_case3 = require("change-case");
764
774
  var import_zod4 = require("zod");
765
- var ResourceIdSchema = import_zod4.z.string().min(3).max(24).regex(/[a-z\-]+/, "Invalid resource ID");
775
+ var ResourceIdSchema = import_zod4.z.string().min(3).max(24).regex(/^[a-z\-]+$/i, "Invalid resource ID").transform((value) => (0, import_change_case3.paramCase)(value));
766
776
 
767
777
  // src/schema/size.ts
768
778
  var import_zod5 = require("zod");
@@ -812,7 +822,7 @@ function toSize(size) {
812
822
  throw new TypeError(`Invalid size ${size}`);
813
823
  }
814
824
  var SizeSchema = import_zod5.z.custom((value) => {
815
- return import_zod5.z.string().regex(/[0-9]+ (KB|MB|GB)/).safeParse(value).success;
825
+ return import_zod5.z.string().regex(/^[0-9]+ (KB|MB|GB)$/).safeParse(value).success;
816
826
  }, "Invalid size").transform(toSize);
817
827
  var sizeMin = (min) => {
818
828
  return (size) => {
@@ -1021,7 +1031,7 @@ var hasOnFailure = (config) => {
1021
1031
  };
1022
1032
 
1023
1033
  // src/plugins/function.ts
1024
- var import_change_case4 = require("change-case");
1034
+ var import_change_case5 = require("change-case");
1025
1035
 
1026
1036
  // src/util/path.ts
1027
1037
  var import_promises2 = require("fs/promises");
@@ -1076,7 +1086,7 @@ var import_path6 = require("path");
1076
1086
  // src/util/type-gen.ts
1077
1087
  var import_promises3 = require("fs/promises");
1078
1088
  var import_path4 = require("path");
1079
- var import_change_case3 = require("change-case");
1089
+ var import_change_case4 = require("change-case");
1080
1090
  var generateResourceTypes = async (config) => {
1081
1091
  const plugins = [
1082
1092
  ...defaultPlugins,
@@ -1128,7 +1138,7 @@ var TypeGen = class {
1128
1138
  lines.push(...[
1129
1139
  "// Imports",
1130
1140
  ...Array.from(this.imports.entries()).map(([varName, path]) => {
1131
- return `import ${(0, import_change_case3.camelCase)(varName)} from '${path}'`;
1141
+ return `import ${(0, import_change_case4.camelCase)(varName)} from '${path}'`;
1132
1142
  }),
1133
1143
  ""
1134
1144
  ]);
@@ -1146,7 +1156,7 @@ var TypeGen = class {
1146
1156
  `declare module '${this.module}' {`,
1147
1157
  ` interface ${this.interfaceName} {`,
1148
1158
  ...Array.from(this.types.entries()).map(([propName, type]) => {
1149
- return ` readonly ${(0, import_change_case3.camelCase)(propName)}: ${type}`;
1159
+ return ` readonly ${(0, import_change_case4.camelCase)(propName)}: ${type}`;
1150
1160
  }),
1151
1161
  ` }`,
1152
1162
  `}`,
@@ -1169,7 +1179,7 @@ var TypeObject = class {
1169
1179
  return [
1170
1180
  "{",
1171
1181
  ...Array.from(this.types.entries()).map(([propName, type]) => {
1172
- return ` readonly ${(0, import_change_case3.camelCase)(propName)}: ${type}`;
1182
+ return ` readonly ${(0, import_change_case4.camelCase)(propName)}: ${type}`;
1173
1183
  }),
1174
1184
  " }"
1175
1185
  ].join("\n");
@@ -1328,7 +1338,7 @@ var functionPlugin = definePlugin({
1328
1338
  for (const stack of config.stacks) {
1329
1339
  const list3 = new TypeObject();
1330
1340
  for (const [name, fileOrProps] of Object.entries(stack.functions || {})) {
1331
- const varName = (0, import_change_case4.camelCase)(`${stack.name}-${name}`);
1341
+ const varName = (0, import_change_case5.camelCase)(`${stack.name}-${name}`);
1332
1342
  const funcName = formatName(`${config.name}-${stack.name}-${name}`);
1333
1343
  const file = typeof fileOrProps === "string" ? fileOrProps : fileOrProps.file;
1334
1344
  const relFile = (0, import_path6.relative)(directories.types, file);
@@ -1479,7 +1489,7 @@ var cronPlugin = definePlugin({
1479
1489
  * crons: {
1480
1490
  * CRON_NAME: {
1481
1491
  * consumer: 'function.ts',
1482
- * schedule: 'rate(5 minutes)',
1492
+ * schedule: '5 minutes',
1483
1493
  * }
1484
1494
  * }
1485
1495
  * }
@@ -1488,8 +1498,8 @@ var cronPlugin = definePlugin({
1488
1498
  /** The consuming lambda function properties. */
1489
1499
  consumer: FunctionSchema,
1490
1500
  /** The scheduling expression.
1491
- * @example 'cron(0 20 * * ? *)'
1492
- * @example 'rate(5 minutes)'
1501
+ * @example '0 20 * * ? *'
1502
+ * @example '5 minutes'
1493
1503
  */
1494
1504
  schedule: ScheduleExpressionSchema,
1495
1505
  // Valid JSON passed to the consumer.
@@ -1568,7 +1578,7 @@ var Queue = class extends Resource {
1568
1578
  };
1569
1579
 
1570
1580
  // src/formation/resource/lambda/event-source-mapping.ts
1571
- var import_change_case5 = require("change-case");
1581
+ var import_change_case6 = require("change-case");
1572
1582
  var EventSourceMapping = class extends Resource {
1573
1583
  constructor(logicalId, props) {
1574
1584
  super("AWS::Lambda::EventSourceMapping", logicalId);
@@ -1590,7 +1600,7 @@ var EventSourceMapping = class extends Resource {
1590
1600
  ...this.attr("ParallelizationFactor", this.props.parallelizationFactor),
1591
1601
  ...this.attr("TumblingWindowInSeconds", this.props.tumblingWindow?.toSeconds()),
1592
1602
  ...this.attr("BisectBatchOnFunctionError", this.props.bisectBatchOnError),
1593
- ...this.attr("StartingPosition", this.props.startingPosition && (0, import_change_case5.constantCase)(this.props.startingPosition)),
1603
+ ...this.attr("StartingPosition", this.props.startingPosition && (0, import_change_case6.constantCase)(this.props.startingPosition)),
1594
1604
  ...this.attr("StartingPositionTimestamp", this.props.startingPositionTimestamp),
1595
1605
  ...this.props.maxConcurrency ? {
1596
1606
  ScalingConfig: {
@@ -1631,7 +1641,8 @@ var SqsEventSource = class extends Group {
1631
1641
  };
1632
1642
 
1633
1643
  // src/plugins/queue.ts
1634
- var import_change_case6 = require("change-case");
1644
+ var import_change_case7 = require("change-case");
1645
+ var import_path8 = require("path");
1635
1646
  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");
1636
1647
  var VisibilityTimeoutSchema = DurationSchema.refine(durationMax(Duration.hours(12)), "Maximum visibility timeout is 12 hours");
1637
1648
  var DeliveryDelaySchema = DurationSchema.refine(durationMax(Duration.minutes(15)), "Maximum delivery delay is 15 minutes");
@@ -1643,10 +1654,12 @@ var MaxBatchingWindow = DurationSchema.refine(durationMax(Duration.minutes(5)),
1643
1654
  var typeGenCode2 = `
1644
1655
  import { SendMessageOptions, SendMessageBatchOptions, BatchItem } from '@awsless/sqs'
1645
1656
 
1646
- type Send<Name extends string> = {
1657
+ type Payload<Func extends (...args: any[]) => any> = Parameters<Func>[0]['Records'][number]['body']
1658
+
1659
+ type Send<Name extends string, Func extends (...args: any[]) => any> = {
1647
1660
  name: Name
1648
- batch(items:BatchItem[], options?:Omit<SendMessageBatchOptions, 'queue' | 'items'>): Promise<void>
1649
- (payload: unknown, options?: Omit<SendMessageOptions, 'queue' | 'payload'>): Promise<void>
1661
+ batch(items:BatchItem<Payload<Func>>[], options?:Omit<SendMessageBatchOptions, 'queue' | 'items'>): Promise<void>
1662
+ (payload: Payload<Func>, options?: Omit<SendMessageOptions, 'queue' | 'payload'>): Promise<void>
1650
1663
  }`;
1651
1664
  var queuePlugin = definePlugin({
1652
1665
  name: "queue",
@@ -1752,9 +1765,13 @@ var queuePlugin = definePlugin({
1752
1765
  types2.addCode(typeGenCode2);
1753
1766
  for (const stack of config.stacks) {
1754
1767
  const list3 = new TypeObject();
1755
- for (const name of Object.keys(stack.queues || {})) {
1768
+ for (const [name, fileOrProps] of Object.entries(stack.queues || {})) {
1769
+ const varName = (0, import_change_case7.camelCase)(`${stack.name}-${name}`);
1756
1770
  const queueName = formatName(`${config.name}-${stack.name}-${name}`);
1757
- list3.addType(name, `Send<'${queueName}'>`);
1771
+ const file = typeof fileOrProps === "string" ? fileOrProps : typeof fileOrProps.consumer === "string" ? fileOrProps.consumer : fileOrProps.consumer.file;
1772
+ const relFile = (0, import_path8.relative)(directories.types, file);
1773
+ types2.addImport(varName, relFile);
1774
+ list3.addType(name, `Send<'${queueName}', typeof ${varName}>`);
1758
1775
  }
1759
1776
  types2.addType(stack.name, list3.toString());
1760
1777
  }
@@ -1779,7 +1796,7 @@ var queuePlugin = definePlugin({
1779
1796
  stack.add(queue2, lambda, source);
1780
1797
  bind((lambda2) => {
1781
1798
  lambda2.addPermissions(queue2.permissions);
1782
- lambda2.addEnvironment(`QUEUE_${(0, import_change_case6.constantCase)(stack.name)}_${(0, import_change_case6.constantCase)(id)}_URL`, queue2.url);
1799
+ lambda2.addEnvironment(`QUEUE_${(0, import_change_case7.constantCase)(stack.name)}_${(0, import_change_case7.constantCase)(id)}_URL`, queue2.url);
1783
1800
  });
1784
1801
  }
1785
1802
  }
@@ -1789,7 +1806,7 @@ var queuePlugin = definePlugin({
1789
1806
  var import_zod9 = require("zod");
1790
1807
 
1791
1808
  // src/formation/resource/dynamodb/table.ts
1792
- var import_change_case7 = require("change-case");
1809
+ var import_change_case8 = require("change-case");
1793
1810
  var Table = class extends Resource {
1794
1811
  constructor(logicalId, props) {
1795
1812
  super("AWS::DynamoDB::Table", logicalId);
@@ -1862,7 +1879,7 @@ var Table = class extends Resource {
1862
1879
  return {
1863
1880
  TableName: this.name,
1864
1881
  BillingMode: "PAY_PER_REQUEST",
1865
- TableClass: (0, import_change_case7.constantCase)(this.props.class || "standard"),
1882
+ TableClass: (0, import_change_case8.constantCase)(this.props.class || "standard"),
1866
1883
  PointInTimeRecoverySpecification: {
1867
1884
  PointInTimeRecoveryEnabled: this.props.pointInTimeRecovery || false
1868
1885
  },
@@ -1873,7 +1890,7 @@ var Table = class extends Resource {
1873
1890
  AttributeDefinitions: this.attributeDefinitions(),
1874
1891
  ...this.props.stream ? {
1875
1892
  StreamSpecification: {
1876
- StreamViewType: (0, import_change_case7.constantCase)(this.props.stream)
1893
+ StreamViewType: (0, import_change_case8.constantCase)(this.props.stream)
1877
1894
  }
1878
1895
  } : {},
1879
1896
  ...this.props.timeToLiveAttribute ? {
@@ -1890,7 +1907,7 @@ var Table = class extends Resource {
1890
1907
  ...props.sort ? [{ KeyType: "RANGE", AttributeName: props.sort }] : []
1891
1908
  ],
1892
1909
  Projection: {
1893
- ProjectionType: (0, import_change_case7.constantCase)(props.projection || "all")
1910
+ ProjectionType: (0, import_change_case8.constantCase)(props.projection || "all")
1894
1911
  }
1895
1912
  }))
1896
1913
  } : {}
@@ -2075,7 +2092,7 @@ var tablePlugin = definePlugin({
2075
2092
  var import_zod10 = require("zod");
2076
2093
 
2077
2094
  // src/formation/resource/s3/bucket.ts
2078
- var import_change_case8 = require("change-case");
2095
+ var import_change_case9 = require("change-case");
2079
2096
  var Bucket = class extends Resource {
2080
2097
  constructor(logicalId, props = {}) {
2081
2098
  super("AWS::S3::Bucket", logicalId);
@@ -2110,7 +2127,7 @@ var Bucket = class extends Resource {
2110
2127
  properties() {
2111
2128
  return {
2112
2129
  BucketName: this.name,
2113
- AccessControl: (0, import_change_case8.pascalCase)(this.props.accessControl ?? "private"),
2130
+ AccessControl: (0, import_change_case9.pascalCase)(this.props.accessControl ?? "private"),
2114
2131
  ...this.props.versioned ? {
2115
2132
  VersioningConfiguration: {
2116
2133
  Status: "Enabled"
@@ -2321,12 +2338,12 @@ var extendPlugin = definePlugin({
2321
2338
  var import_zod13 = require("zod");
2322
2339
 
2323
2340
  // src/formation/resource/iot/topic-rule.ts
2324
- var import_change_case9 = require("change-case");
2341
+ var import_change_case10 = require("change-case");
2325
2342
  var TopicRule = class extends Resource {
2326
2343
  constructor(logicalId, props) {
2327
2344
  super("AWS::IoT::TopicRule", logicalId);
2328
2345
  this.props = props;
2329
- this.name = (0, import_change_case9.snakeCase)(this.props.name || logicalId);
2346
+ this.name = (0, import_change_case10.snakeCase)(this.props.name || logicalId);
2330
2347
  }
2331
2348
  name;
2332
2349
  get arn() {
@@ -2426,10 +2443,10 @@ var toArray = (value) => {
2426
2443
  };
2427
2444
 
2428
2445
  // src/plugins/graphql.ts
2429
- var import_change_case13 = require("change-case");
2446
+ var import_change_case14 = require("change-case");
2430
2447
 
2431
2448
  // src/formation/resource/appsync/graphql-api.ts
2432
- var import_change_case10 = require("change-case");
2449
+ var import_change_case11 = require("change-case");
2433
2450
  var GraphQLApi = class extends Resource {
2434
2451
  constructor(logicalId, props) {
2435
2452
  super("AWS::AppSync::GraphQLApi", logicalId);
@@ -2461,7 +2478,7 @@ var GraphQLApi = class extends Resource {
2461
2478
  properties() {
2462
2479
  return {
2463
2480
  Name: this.name,
2464
- AuthenticationType: (0, import_change_case10.constantCase)(this.props.authenticationType || "api-key"),
2481
+ AuthenticationType: (0, import_change_case11.constantCase)(this.props.authenticationType || "api-key"),
2465
2482
  AdditionalAuthenticationProviders: this.lambdaAuthProviders.map((provider) => ({
2466
2483
  AuthenticationType: "AWS_LAMBDA",
2467
2484
  LambdaAuthorizerConfig: {
@@ -2588,12 +2605,12 @@ var FileCode2 = class extends Asset {
2588
2605
  };
2589
2606
 
2590
2607
  // src/formation/resource/appsync/data-source.ts
2591
- var import_change_case11 = require("change-case");
2608
+ var import_change_case12 = require("change-case");
2592
2609
  var DataSource = class extends Resource {
2593
2610
  constructor(logicalId, props) {
2594
2611
  super("AWS::AppSync::DataSource", logicalId);
2595
2612
  this.props = props;
2596
- this.name = (0, import_change_case11.snakeCase)(this.props.name || logicalId);
2613
+ this.name = (0, import_change_case12.snakeCase)(this.props.name || logicalId);
2597
2614
  }
2598
2615
  static fromLambda(logicalId, apiId, props) {
2599
2616
  return new DataSource(logicalId, {
@@ -2633,14 +2650,14 @@ var DataSource = class extends Resource {
2633
2650
  };
2634
2651
 
2635
2652
  // src/formation/resource/appsync/function-configuration.ts
2636
- var import_change_case12 = require("change-case");
2653
+ var import_change_case13 = require("change-case");
2637
2654
  var FunctionConfiguration = class extends Resource {
2638
2655
  constructor(logicalId, props) {
2639
2656
  super("AWS::AppSync::FunctionConfiguration", logicalId, [
2640
2657
  props.code
2641
2658
  ]);
2642
2659
  this.props = props;
2643
- this.name = (0, import_change_case12.snakeCase)(this.props.name || logicalId);
2660
+ this.name = (0, import_change_case13.snakeCase)(this.props.name || logicalId);
2644
2661
  }
2645
2662
  name;
2646
2663
  get id() {
@@ -2769,9 +2786,6 @@ export function response(ctx) {
2769
2786
  return ctx.result
2770
2787
  }
2771
2788
  `;
2772
- var ResolverFieldSchema = import_zod14.z.custom((value) => {
2773
- return import_zod14.z.string().regex(/([a-z0-9\_]+)(\s){1}([a-z0-9\_]+)/gi).safeParse(value).success;
2774
- }, `Invalid resolver field. Valid example: "Query list"`);
2775
2789
  var graphqlPlugin = definePlugin({
2776
2790
  name: "graphql",
2777
2791
  schema: import_zod14.z.object({
@@ -2792,7 +2806,13 @@ var graphqlPlugin = definePlugin({
2792
2806
  LocalFileSchema,
2793
2807
  import_zod14.z.array(LocalFileSchema).min(1)
2794
2808
  ]).optional(),
2795
- resolvers: import_zod14.z.record(ResolverFieldSchema, FunctionSchema).optional()
2809
+ resolvers: import_zod14.z.record(
2810
+ import_zod14.z.string(),
2811
+ import_zod14.z.record(
2812
+ import_zod14.z.string(),
2813
+ FunctionSchema
2814
+ )
2815
+ ).optional()
2796
2816
  })).optional()
2797
2817
  }).array()
2798
2818
  }),
@@ -2857,17 +2877,18 @@ var graphqlPlugin = definePlugin({
2857
2877
  const { stack, stackConfig, bootstrap: bootstrap2 } = ctx;
2858
2878
  for (const [id, props] of Object.entries(stackConfig.graphql || {})) {
2859
2879
  const apiId = bootstrap2.import(`graphql-${id}`);
2860
- for (const [typeAndField, functionProps] of Object.entries(props.resolvers || {})) {
2861
- const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
2862
- const entryId = (0, import_change_case13.paramCase)(`${id}-${typeName}-${fieldName}`);
2863
- const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
2864
- const source = new AppsyncEventSource(entryId, lambda, {
2865
- apiId,
2866
- typeName,
2867
- fieldName,
2868
- code: Code2.fromInline(entryId, defaultResolver)
2869
- });
2870
- stack.add(lambda, source);
2880
+ for (const [typeName, fields] of Object.entries(props.resolvers || {})) {
2881
+ for (const [fieldName, functionProps] of Object.entries(fields || {})) {
2882
+ const entryId = (0, import_change_case14.paramCase)(`${id}-${typeName}-${fieldName}`);
2883
+ const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
2884
+ const source = new AppsyncEventSource(entryId, lambda, {
2885
+ apiId,
2886
+ typeName,
2887
+ fieldName,
2888
+ code: Code2.fromInline(entryId, defaultResolver)
2889
+ });
2890
+ stack.add(lambda, source);
2891
+ }
2871
2892
  }
2872
2893
  }
2873
2894
  }
@@ -3543,7 +3564,7 @@ var LoadBalancer = class extends Resource {
3543
3564
  };
3544
3565
 
3545
3566
  // src/formation/resource/elb/listener.ts
3546
- var import_change_case14 = require("change-case");
3567
+ var import_change_case15 = require("change-case");
3547
3568
  var Listener = class extends Resource {
3548
3569
  constructor(logicalId, props) {
3549
3570
  super("AWS::ElasticLoadBalancingV2::Listener", logicalId);
@@ -3559,7 +3580,7 @@ var Listener = class extends Resource {
3559
3580
  return {
3560
3581
  LoadBalancerArn: this.props.loadBalancerArn,
3561
3582
  Port: this.props.port,
3562
- Protocol: (0, import_change_case14.constantCase)(this.props.protocol),
3583
+ Protocol: (0, import_change_case15.constantCase)(this.props.protocol),
3563
3584
  Certificates: this.props.certificates.map((arn) => ({
3564
3585
  CertificateArn: arn
3565
3586
  })),
@@ -3998,7 +4019,7 @@ var SubnetGroup = class extends Resource {
3998
4019
  };
3999
4020
 
4000
4021
  // src/plugins/cache.ts
4001
- var import_change_case15 = require("change-case");
4022
+ var import_change_case16 = require("change-case");
4002
4023
  var TypeSchema = import_zod19.z.enum([
4003
4024
  "t4g.small",
4004
4025
  "t4g.medium",
@@ -4084,7 +4105,7 @@ var cachePlugin = definePlugin({
4084
4105
  }).dependsOn(subnetGroup, securityGroup);
4085
4106
  stack.add(subnetGroup, securityGroup, cluster);
4086
4107
  bind((lambda) => {
4087
- lambda.addEnvironment(`CACHE_${(0, import_change_case15.constantCase)(stack.name)}_${(0, import_change_case15.constantCase)(id)}_HOST`, cluster.address).addEnvironment(`CACHE_${(0, import_change_case15.constantCase)(stack.name)}_${(0, import_change_case15.constantCase)(id)}_PORT`, props.port.toString());
4108
+ lambda.addEnvironment(`CACHE_${(0, import_change_case16.constantCase)(stack.name)}_${(0, import_change_case16.constantCase)(id)}_HOST`, cluster.address).addEnvironment(`CACHE_${(0, import_change_case16.constantCase)(stack.name)}_${(0, import_change_case16.constantCase)(id)}_PORT`, props.port.toString());
4088
4109
  });
4089
4110
  }
4090
4111
  }
@@ -4340,7 +4361,7 @@ var toApp = async (config, filters) => {
4340
4361
  };
4341
4362
 
4342
4363
  // src/config.ts
4343
- var import_path9 = require("path");
4364
+ var import_path11 = require("path");
4344
4365
 
4345
4366
  // src/util/account.ts
4346
4367
  var import_client_sts = require("@aws-sdk/client-sts");
@@ -4411,7 +4432,7 @@ var AppSchema = import_zod23.z.object({
4411
4432
  /** The deployment stage.
4412
4433
  * @default 'prod'
4413
4434
  */
4414
- stage: import_zod23.z.string().regex(/[a-z]+/).default("prod"),
4435
+ stage: import_zod23.z.string().regex(/^[a-z]+$/).default("prod"),
4415
4436
  /** Default properties. */
4416
4437
  defaults: import_zod23.z.object({}).default({}),
4417
4438
  /** The application stacks. */
@@ -4428,7 +4449,7 @@ var import_rollup3 = require("rollup");
4428
4449
  var import_rollup_plugin_swc32 = require("rollup-plugin-swc3");
4429
4450
  var import_rollup_plugin_replace = __toESM(require("rollup-plugin-replace"), 1);
4430
4451
  var import_event_iterator = require("event-iterator");
4431
- var import_path7 = require("path");
4452
+ var import_path9 = require("path");
4432
4453
  var import_promises6 = require("fs/promises");
4433
4454
  var importFile = async (path) => {
4434
4455
  const bundle = await (0, import_rollup3.rollup)({
@@ -4438,17 +4459,17 @@ var importFile = async (path) => {
4438
4459
  },
4439
4460
  plugins: [
4440
4461
  (0, import_rollup_plugin_replace.default)({
4441
- __dirname: (id) => `'${(0, import_path7.dirname)(id)}'`
4462
+ __dirname: (id) => `'${(0, import_path9.dirname)(id)}'`
4442
4463
  }),
4443
4464
  (0, import_rollup_plugin_swc32.swc)({
4444
4465
  minify: false,
4445
4466
  jsc: {
4446
- baseUrl: (0, import_path7.dirname)(path)
4467
+ baseUrl: (0, import_path9.dirname)(path)
4447
4468
  }
4448
4469
  })
4449
4470
  ]
4450
4471
  });
4451
- const outputFile = (0, import_path7.join)(directories.cache, "config.js");
4472
+ const outputFile = (0, import_path9.join)(directories.cache, "config.js");
4452
4473
  const result = await bundle.generate({
4453
4474
  format: "esm",
4454
4475
  exports: "default"
@@ -4472,12 +4493,12 @@ var watchFile = (path) => {
4472
4493
  },
4473
4494
  plugins: [
4474
4495
  (0, import_rollup_plugin_replace.default)({
4475
- __dirname: (id) => `'${(0, import_path7.dirname)(id)}'`
4496
+ __dirname: (id) => `'${(0, import_path9.dirname)(id)}'`
4476
4497
  }),
4477
4498
  (0, import_rollup_plugin_swc32.swc)({
4478
4499
  minify: false,
4479
4500
  jsc: {
4480
- baseUrl: (0, import_path7.dirname)(path)
4501
+ baseUrl: (0, import_path9.dirname)(path)
4481
4502
  }
4482
4503
  })
4483
4504
  ]
@@ -4499,7 +4520,7 @@ var watchFile = (path) => {
4499
4520
  event.result.close();
4500
4521
  const output = result.output[0];
4501
4522
  const code = output.code;
4502
- const outputFile = (0, import_path7.join)(directories.cache, "config.js");
4523
+ const outputFile = (0, import_path9.join)(directories.cache, "config.js");
4503
4524
  await (0, import_promises6.mkdir)(directories.cache, { recursive: true });
4504
4525
  await (0, import_promises6.writeFile)(outputFile, code);
4505
4526
  debug("Save config file:", style.info(outputFile));
@@ -4517,6 +4538,14 @@ var watchFile = (path) => {
4517
4538
  };
4518
4539
 
4519
4540
  // src/config.ts
4541
+ var import_zod24 = require("zod");
4542
+ var ConfigError = class extends Error {
4543
+ constructor(error, data) {
4544
+ super(error.message);
4545
+ this.error = error;
4546
+ this.data = data;
4547
+ }
4548
+ };
4520
4549
  var importConfig = async (options) => {
4521
4550
  debug("Find the root directory");
4522
4551
  const configFile = options.configFile || "awsless.config.ts";
@@ -4524,7 +4553,7 @@ var importConfig = async (options) => {
4524
4553
  setRoot(root2);
4525
4554
  debug("CWD:", style.info(root2));
4526
4555
  debug("Import config file");
4527
- const fileName = (0, import_path9.join)(root2, configFile);
4556
+ const fileName = (0, import_path11.join)(root2, configFile);
4528
4557
  const module2 = await importFile(fileName);
4529
4558
  const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
4530
4559
  debug("Validate config file");
@@ -4538,7 +4567,15 @@ var importConfig = async (options) => {
4538
4567
  schema2 = schema2.and(plugin.schema);
4539
4568
  }
4540
4569
  }
4541
- const config = await schema2.parseAsync(appConfig);
4570
+ let config;
4571
+ try {
4572
+ config = await schema2.parseAsync(appConfig);
4573
+ } catch (error) {
4574
+ if (error instanceof import_zod24.z.ZodError) {
4575
+ throw new ConfigError(error, appConfig);
4576
+ }
4577
+ throw error;
4578
+ }
4542
4579
  debug("Load credentials", style.info(config.profile));
4543
4580
  const credentials = getCredentials(config.profile);
4544
4581
  debug("Load AWS account ID");
@@ -4557,7 +4594,7 @@ var watchConfig = async function* (options) {
4557
4594
  setRoot(root2);
4558
4595
  debug("CWD:", style.info(root2));
4559
4596
  debug("Import config file");
4560
- const fileName = (0, import_path9.join)(root2, configFile);
4597
+ const fileName = (0, import_path11.join)(root2, configFile);
4561
4598
  for await (const module2 of watchFile(fileName)) {
4562
4599
  const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
4563
4600
  debug("Validate config file");
@@ -4571,7 +4608,15 @@ var watchConfig = async function* (options) {
4571
4608
  schema2 = schema2.and(plugin.schema);
4572
4609
  }
4573
4610
  }
4574
- const config = await schema2.parseAsync(appConfig);
4611
+ let config;
4612
+ try {
4613
+ config = await schema2.parseAsync(appConfig);
4614
+ } catch (error) {
4615
+ if (error instanceof import_zod24.z.ZodError) {
4616
+ throw new ConfigError(error, appConfig);
4617
+ }
4618
+ throw error;
4619
+ }
4575
4620
  debug("Load credentials", style.info(config.profile));
4576
4621
  const credentials = getCredentials(config.profile);
4577
4622
  debug("Load AWS account ID");
@@ -4696,11 +4741,11 @@ var dialog = (type, lines) => {
4696
4741
  const padding = 3;
4697
4742
  const icon = style[type](symbol[type].padEnd(padding));
4698
4743
  return (term) => {
4699
- term.out.write(lines.map((line, i) => {
4744
+ term.out.write(lines.map((line2, i) => {
4700
4745
  if (i === 0) {
4701
- return icon + (0, import_wrap_ansi.default)(line, term.out.width(), { hard: true });
4746
+ return icon + (0, import_wrap_ansi.default)(line2, term.out.width(), { hard: true });
4702
4747
  }
4703
- return (0, import_wrap_ansi.default)(" ".repeat(padding) + line, term.out.width(), { hard: true });
4748
+ return (0, import_wrap_ansi.default)(" ".repeat(padding) + line2, term.out.width(), { hard: true });
4704
4749
  }).join(br()) + br());
4705
4750
  };
4706
4751
  };
@@ -5023,6 +5068,87 @@ var logs = () => {
5023
5068
  };
5024
5069
  };
5025
5070
 
5071
+ // src/cli/ui/layout/zod-error.ts
5072
+ var line = (value, level = 0, highlight = false) => {
5073
+ return [
5074
+ highlight ? style.error(symbol.pointerSmall) + style.placeholder(" | ") : style.placeholder.dim(" | "),
5075
+ " ".repeat(level),
5076
+ value,
5077
+ br()
5078
+ ];
5079
+ };
5080
+ var format = (value) => {
5081
+ if (Array.isArray(value)) {
5082
+ return "[ ... ]";
5083
+ }
5084
+ if (value === null) {
5085
+ return "null";
5086
+ }
5087
+ switch (typeof value) {
5088
+ case "function":
5089
+ return "() => { ... }";
5090
+ case "bigint":
5091
+ return `${value}n`;
5092
+ case "symbol":
5093
+ return "Symbol()";
5094
+ case "object":
5095
+ return "{ ... }";
5096
+ case "undefined":
5097
+ case "string":
5098
+ case "number":
5099
+ case "boolean":
5100
+ return JSON.stringify(value);
5101
+ }
5102
+ return "";
5103
+ };
5104
+ var zodError = (error, data) => {
5105
+ return (term) => {
5106
+ term.out.write(JSON.stringify(error.errors));
5107
+ for (const issue of error.issues) {
5108
+ term.out.gap();
5109
+ term.out.write(dialog("error", [
5110
+ style.error(issue.message)
5111
+ ]));
5112
+ term.out.gap();
5113
+ term.out.write(line("{"));
5114
+ let context = data;
5115
+ const inStack = issue.path[0] === "stacks" && typeof issue.path[1] === "number";
5116
+ const length2 = issue.path.length;
5117
+ const end = [];
5118
+ issue.path.forEach((path, i) => {
5119
+ const index = i + 1;
5120
+ context = context[path];
5121
+ if (typeof path === "string") {
5122
+ const key = path + `: `;
5123
+ if (index === length2) {
5124
+ const space = " ".repeat(key.length);
5125
+ const value = format(context);
5126
+ const error2 = "^".repeat(value.length);
5127
+ term.out.write(line(key + style.warning(value), index));
5128
+ term.out.write(line(space + style.error(error2), index, true));
5129
+ } else if (Array.isArray(context)) {
5130
+ term.out.write(line(key + "[", index));
5131
+ end.unshift(line("]", index));
5132
+ } else if (typeof context === "object") {
5133
+ if (inStack && index === 3) {
5134
+ const name = data.stacks[issue.path[1]].name;
5135
+ term.out.write(line("name: " + style.info(`"${name}"`) + ",", index));
5136
+ }
5137
+ term.out.write(line(key + "{", index));
5138
+ end.unshift(line("}", index));
5139
+ }
5140
+ } else if (typeof context === "object") {
5141
+ term.out.write(line("{", index));
5142
+ end.unshift(line("}", index));
5143
+ }
5144
+ });
5145
+ term.out.write(end);
5146
+ term.out.write(line("}"));
5147
+ term.out.gap();
5148
+ }
5149
+ };
5150
+ };
5151
+
5026
5152
  // src/cli/ui/layout/layout.ts
5027
5153
  var layout = async (cb) => {
5028
5154
  const term = createTerminal();
@@ -5038,7 +5164,9 @@ var layout = async (cb) => {
5038
5164
  await cb(config, term.out.write.bind(term.out), term);
5039
5165
  } catch (error) {
5040
5166
  term.out.gap();
5041
- if (error instanceof Error) {
5167
+ if (error instanceof ConfigError) {
5168
+ term.out.write(zodError(error.error, error.data));
5169
+ } else if (error instanceof Error) {
5042
5170
  term.out.write(dialog("error", [error.message]));
5043
5171
  } else if (typeof error === "string") {
5044
5172
  term.out.write(dialog("error", [error]));
@@ -5082,7 +5210,7 @@ var flexLine = (term, left, right, reserveSpace = 0) => {
5082
5210
  };
5083
5211
 
5084
5212
  // src/cli/ui/complex/builder.ts
5085
- var import_path12 = require("path");
5213
+ var import_path14 = require("path");
5086
5214
  var assetBuilder = (app) => {
5087
5215
  return async (term) => {
5088
5216
  const assets = [];
@@ -5116,7 +5244,7 @@ var assetBuilder = (app) => {
5116
5244
  }
5117
5245
  const [icon, stop] = createSpinner();
5118
5246
  const details = new Signal({});
5119
- const line = flexLine(term, [
5247
+ const line2 = flexLine(term, [
5120
5248
  icon,
5121
5249
  " ",
5122
5250
  style.label(stack.name),
@@ -5140,13 +5268,13 @@ var assetBuilder = (app) => {
5140
5268
  }),
5141
5269
  br()
5142
5270
  ]);
5143
- group.update((group2) => [...group2, line]);
5271
+ group.update((group2) => [...group2, line2]);
5144
5272
  const timer = createTimer();
5145
5273
  try {
5146
5274
  const data = await asset.build({
5147
5275
  async write(file, data2) {
5148
- const fullpath = (0, import_path12.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5149
- const basepath = (0, import_path12.dirname)(fullpath);
5276
+ const fullpath = (0, import_path14.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5277
+ const basepath = (0, import_path14.dirname)(fullpath);
5150
5278
  await (0, import_promises7.mkdir)(basepath, { recursive: true });
5151
5279
  await (0, import_promises7.writeFile)(fullpath, data2);
5152
5280
  }
@@ -5193,14 +5321,14 @@ var cleanUp = async () => {
5193
5321
 
5194
5322
  // src/cli/ui/complex/template.ts
5195
5323
  var import_promises9 = require("fs/promises");
5196
- var import_path15 = require("path");
5324
+ var import_path17 = require("path");
5197
5325
  var templateBuilder = (app) => {
5198
5326
  return async (term) => {
5199
5327
  const done = term.out.write(loadingDialog("Building stack templates..."));
5200
5328
  await Promise.all(app.stacks.map(async (stack) => {
5201
5329
  const template = stack.toString(true);
5202
- const path = (0, import_path15.join)(directories.template, app.name);
5203
- const file = (0, import_path15.join)(path, `${stack.name}.json`);
5330
+ const path = (0, import_path17.join)(directories.template, app.name);
5331
+ const file = (0, import_path17.join)(path, `${stack.name}.json`);
5204
5332
  await (0, import_promises9.mkdir)(path, { recursive: true });
5205
5333
  await (0, import_promises9.writeFile)(file, template);
5206
5334
  }));
@@ -5260,7 +5388,7 @@ var shouldDeployBootstrap = async (client, stack) => {
5260
5388
  // src/formation/client.ts
5261
5389
  var import_client_cloudformation = require("@aws-sdk/client-cloudformation");
5262
5390
  var import_client_s3 = require("@aws-sdk/client-s3");
5263
- var import_change_case16 = require("change-case");
5391
+ var import_change_case17 = require("change-case");
5264
5392
  var StackClient = class {
5265
5393
  constructor(app, account, region, credentials) {
5266
5394
  this.app = app;
@@ -5293,7 +5421,7 @@ var StackClient = class {
5293
5421
  };
5294
5422
  }
5295
5423
  stackName(stackName) {
5296
- return (0, import_change_case16.paramCase)(`${this.app.name}-${stackName}`);
5424
+ return (0, import_change_case17.paramCase)(`${this.app.name}-${stackName}`);
5297
5425
  }
5298
5426
  tags(stack) {
5299
5427
  const tags = [];
@@ -5611,13 +5739,13 @@ var bootstrap = (program2) => {
5611
5739
 
5612
5740
  // src/cli/ui/complex/deployer.ts
5613
5741
  var stacksDeployer = (deploymentLine) => {
5614
- const stackNames = deploymentLine.map((line) => line.map((stack) => stack.name)).flat();
5742
+ const stackNames = deploymentLine.map((line2) => line2.map((stack) => stack.name)).flat();
5615
5743
  const stackNameSize = Math.max(...stackNames.map((name) => name.length));
5616
5744
  return (term) => {
5617
5745
  const ui = {};
5618
5746
  term.out.gap();
5619
5747
  for (const i in deploymentLine) {
5620
- const line = flexLine(
5748
+ const line2 = flexLine(
5621
5749
  term,
5622
5750
  [" "],
5623
5751
  [
@@ -5626,7 +5754,7 @@ var stacksDeployer = (deploymentLine) => {
5626
5754
  style.placeholder(" \u2500\u2500")
5627
5755
  ]
5628
5756
  );
5629
- term.out.write(line);
5757
+ term.out.write(line2);
5630
5758
  term.out.write(br());
5631
5759
  for (const stack of deploymentLine[i]) {
5632
5760
  const icon = new Signal(" ");
@@ -5721,7 +5849,7 @@ var status = (program2) => {
5721
5849
 
5722
5850
  // src/cli/ui/complex/publisher.ts
5723
5851
  var import_promises10 = require("fs/promises");
5724
- var import_path17 = require("path");
5852
+ var import_path19 = require("path");
5725
5853
  var import_client_s32 = require("@aws-sdk/client-s3");
5726
5854
  var assetPublisher = (config, app) => {
5727
5855
  const client = new import_client_s32.S3Client({
@@ -5734,7 +5862,7 @@ var assetPublisher = (config, app) => {
5734
5862
  await Promise.all([...stack.assets].map(async (asset) => {
5735
5863
  await asset.publish?.({
5736
5864
  async read(file) {
5737
- const path = (0, import_path17.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5865
+ const path = (0, import_path19.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5738
5866
  const data = await (0, import_promises10.readFile)(path);
5739
5867
  return data;
5740
5868
  },
@@ -5806,8 +5934,8 @@ var deploy = (program2) => {
5806
5934
  const doneDeploying = write(loadingDialog("Deploying stacks to AWS..."));
5807
5935
  const client = new StackClient(app, config.account, config.region, config.credentials);
5808
5936
  const ui = write(stacksDeployer(deploymentLine));
5809
- for (const line of deploymentLine) {
5810
- const results = await Promise.allSettled(line.map(async (stack) => {
5937
+ for (const line2 of deploymentLine) {
5938
+ const results = await Promise.allSettled(line2.map(async (stack) => {
5811
5939
  const item = ui[stack.name];
5812
5940
  item.start("deploying");
5813
5941
  try {