@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.js CHANGED
@@ -597,7 +597,7 @@ var createDeploymentLine = (stacks) => {
597
597
  depends: config?.depends?.map((dep) => dep.name) || []
598
598
  }));
599
599
  const names = stacks.map(({ stack }) => stack.name);
600
- const line = [];
600
+ const line2 = [];
601
601
  const deps = [];
602
602
  let limit = 100;
603
603
  while (deps.length < list3.length) {
@@ -612,9 +612,9 @@ var createDeploymentLine = (stacks) => {
612
612
  throw new Error(`Circular stack dependencies arn't allowed: ${circularNames}`);
613
613
  }
614
614
  deps.push(...local.map((stack) => stack.name));
615
- line.push(local);
615
+ line2.push(local);
616
616
  }
617
- return line;
617
+ return line2;
618
618
  };
619
619
 
620
620
  // src/plugins/cron/index.ts
@@ -624,23 +624,30 @@ import { z as z7 } from "zod";
624
624
  import { z } from "zod";
625
625
  import { awsCronExpressionValidator } from "aws-cron-expression-validator";
626
626
  var RateExpressionSchema = z.custom((value) => {
627
- return z.string().regex(/rate\([0-9]+ (seconds?|minutes?|hours?|days?)\)/).refine((rate) => {
628
- const [str] = rate.substring(5).split(" ");
627
+ return z.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).refine((rate) => {
628
+ const [str] = rate.split(" ");
629
629
  const number = parseInt(str);
630
630
  return number > 0;
631
631
  }).safeParse(value).success;
632
- }, "Invalid rate expression");
632
+ }, { message: "Invalid rate expression" }).transform((rate) => {
633
+ const [str] = rate.split(" ");
634
+ const number = parseInt(str);
635
+ const more = rate.endsWith("s");
636
+ if (more && number === 1) {
637
+ return `rate(${rate.substring(0, rate.length - 1)})`;
638
+ }
639
+ return `rate(${rate})`;
640
+ });
633
641
  var CronExpressionSchema = z.custom((value) => {
634
- return z.string().startsWith("cron(").endsWith(")").safeParse(value).success;
635
- }, "Invalid cron expression").superRefine((value, ctx) => {
636
- const cron = value.substring(5, value.length - 1);
642
+ return z.string().safeParse(value).success;
643
+ }, { message: "Invalid cron expression" }).superRefine((value, ctx) => {
637
644
  try {
638
- awsCronExpressionValidator(cron);
645
+ awsCronExpressionValidator(value);
639
646
  } catch (error) {
640
647
  if (error instanceof Error) {
641
648
  ctx.addIssue({
642
649
  code: z.ZodIssueCode.custom,
643
- message: error.message
650
+ message: `Invalid cron expression: ${error.message}`
644
651
  });
645
652
  } else {
646
653
  ctx.addIssue({
@@ -649,6 +656,8 @@ var CronExpressionSchema = z.custom((value) => {
649
656
  });
650
657
  }
651
658
  }
659
+ }).transform((value) => {
660
+ return `cron(${value.trim()})`;
652
661
  });
653
662
  var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
654
663
 
@@ -712,7 +721,7 @@ function toDuration(duration) {
712
721
  return Duration.days(0);
713
722
  }
714
723
  var DurationSchema = z2.custom((value) => {
715
- return z2.string().regex(/[0-9]+ (seconds?|minutes?|hours?|days?)/).safeParse(value).success;
724
+ return z2.string().regex(/^[0-9]+ (seconds?|minutes?|hours?|days?)$/).safeParse(value).success;
716
725
  }, "Invalid duration").transform(toDuration);
717
726
  var durationMin = (min) => {
718
727
  return (duration) => {
@@ -738,8 +747,9 @@ var LocalFileSchema = z3.string().refine(async (path) => {
738
747
  }, `File doesn't exist`);
739
748
 
740
749
  // src/schema/resource-id.ts
750
+ import { paramCase as paramCase3 } from "change-case";
741
751
  import { z as z4 } from "zod";
742
- var ResourceIdSchema = z4.string().min(3).max(24).regex(/[a-z\-]+/, "Invalid resource ID");
752
+ var ResourceIdSchema = z4.string().min(3).max(24).regex(/^[a-z\-]+$/i, "Invalid resource ID").transform((value) => paramCase3(value));
743
753
 
744
754
  // src/schema/size.ts
745
755
  import { z as z5 } from "zod";
@@ -789,7 +799,7 @@ function toSize(size) {
789
799
  throw new TypeError(`Invalid size ${size}`);
790
800
  }
791
801
  var SizeSchema = z5.custom((value) => {
792
- return z5.string().regex(/[0-9]+ (KB|MB|GB)/).safeParse(value).success;
802
+ return z5.string().regex(/^[0-9]+ (KB|MB|GB)$/).safeParse(value).success;
793
803
  }, "Invalid size").transform(toSize);
794
804
  var sizeMin = (min) => {
795
805
  return (size) => {
@@ -1456,7 +1466,7 @@ var cronPlugin = definePlugin({
1456
1466
  * crons: {
1457
1467
  * CRON_NAME: {
1458
1468
  * consumer: 'function.ts',
1459
- * schedule: 'rate(5 minutes)',
1469
+ * schedule: '5 minutes',
1460
1470
  * }
1461
1471
  * }
1462
1472
  * }
@@ -1465,8 +1475,8 @@ var cronPlugin = definePlugin({
1465
1475
  /** The consuming lambda function properties. */
1466
1476
  consumer: FunctionSchema,
1467
1477
  /** The scheduling expression.
1468
- * @example 'cron(0 20 * * ? *)'
1469
- * @example 'rate(5 minutes)'
1478
+ * @example '0 20 * * ? *'
1479
+ * @example '5 minutes'
1470
1480
  */
1471
1481
  schedule: ScheduleExpressionSchema,
1472
1482
  // Valid JSON passed to the consumer.
@@ -1608,7 +1618,8 @@ var SqsEventSource = class extends Group {
1608
1618
  };
1609
1619
 
1610
1620
  // src/plugins/queue.ts
1611
- import { constantCase as constantCase2 } from "change-case";
1621
+ import { camelCase as camelCase3, constantCase as constantCase2 } from "change-case";
1622
+ import { relative as relative3 } from "path";
1612
1623
  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");
1613
1624
  var VisibilityTimeoutSchema = DurationSchema.refine(durationMax(Duration.hours(12)), "Maximum visibility timeout is 12 hours");
1614
1625
  var DeliveryDelaySchema = DurationSchema.refine(durationMax(Duration.minutes(15)), "Maximum delivery delay is 15 minutes");
@@ -1620,10 +1631,12 @@ var MaxBatchingWindow = DurationSchema.refine(durationMax(Duration.minutes(5)),
1620
1631
  var typeGenCode2 = `
1621
1632
  import { SendMessageOptions, SendMessageBatchOptions, BatchItem } from '@awsless/sqs'
1622
1633
 
1623
- type Send<Name extends string> = {
1634
+ type Payload<Func extends (...args: any[]) => any> = Parameters<Func>[0]['Records'][number]['body']
1635
+
1636
+ type Send<Name extends string, Func extends (...args: any[]) => any> = {
1624
1637
  name: Name
1625
- batch(items:BatchItem[], options?:Omit<SendMessageBatchOptions, 'queue' | 'items'>): Promise<void>
1626
- (payload: unknown, options?: Omit<SendMessageOptions, 'queue' | 'payload'>): Promise<void>
1638
+ batch(items:BatchItem<Payload<Func>>[], options?:Omit<SendMessageBatchOptions, 'queue' | 'items'>): Promise<void>
1639
+ (payload: Payload<Func>, options?: Omit<SendMessageOptions, 'queue' | 'payload'>): Promise<void>
1627
1640
  }`;
1628
1641
  var queuePlugin = definePlugin({
1629
1642
  name: "queue",
@@ -1729,9 +1742,13 @@ var queuePlugin = definePlugin({
1729
1742
  types2.addCode(typeGenCode2);
1730
1743
  for (const stack of config.stacks) {
1731
1744
  const list3 = new TypeObject();
1732
- for (const name of Object.keys(stack.queues || {})) {
1745
+ for (const [name, fileOrProps] of Object.entries(stack.queues || {})) {
1746
+ const varName = camelCase3(`${stack.name}-${name}`);
1733
1747
  const queueName = formatName(`${config.name}-${stack.name}-${name}`);
1734
- list3.addType(name, `Send<'${queueName}'>`);
1748
+ const file = typeof fileOrProps === "string" ? fileOrProps : typeof fileOrProps.consumer === "string" ? fileOrProps.consumer : fileOrProps.consumer.file;
1749
+ const relFile = relative3(directories.types, file);
1750
+ types2.addImport(varName, relFile);
1751
+ list3.addType(name, `Send<'${queueName}', typeof ${varName}>`);
1735
1752
  }
1736
1753
  types2.addType(stack.name, list3.toString());
1737
1754
  }
@@ -2403,7 +2420,7 @@ var toArray = (value) => {
2403
2420
  };
2404
2421
 
2405
2422
  // src/plugins/graphql.ts
2406
- import { paramCase as paramCase3 } from "change-case";
2423
+ import { paramCase as paramCase4 } from "change-case";
2407
2424
 
2408
2425
  // src/formation/resource/appsync/graphql-api.ts
2409
2426
  import { constantCase as constantCase4 } from "change-case";
@@ -2746,9 +2763,6 @@ export function response(ctx) {
2746
2763
  return ctx.result
2747
2764
  }
2748
2765
  `;
2749
- var ResolverFieldSchema = z14.custom((value) => {
2750
- return z14.string().regex(/([a-z0-9\_]+)(\s){1}([a-z0-9\_]+)/gi).safeParse(value).success;
2751
- }, `Invalid resolver field. Valid example: "Query list"`);
2752
2766
  var graphqlPlugin = definePlugin({
2753
2767
  name: "graphql",
2754
2768
  schema: z14.object({
@@ -2769,7 +2783,13 @@ var graphqlPlugin = definePlugin({
2769
2783
  LocalFileSchema,
2770
2784
  z14.array(LocalFileSchema).min(1)
2771
2785
  ]).optional(),
2772
- resolvers: z14.record(ResolverFieldSchema, FunctionSchema).optional()
2786
+ resolvers: z14.record(
2787
+ z14.string(),
2788
+ z14.record(
2789
+ z14.string(),
2790
+ FunctionSchema
2791
+ )
2792
+ ).optional()
2773
2793
  })).optional()
2774
2794
  }).array()
2775
2795
  }),
@@ -2834,17 +2854,18 @@ var graphqlPlugin = definePlugin({
2834
2854
  const { stack, stackConfig, bootstrap: bootstrap2 } = ctx;
2835
2855
  for (const [id, props] of Object.entries(stackConfig.graphql || {})) {
2836
2856
  const apiId = bootstrap2.import(`graphql-${id}`);
2837
- for (const [typeAndField, functionProps] of Object.entries(props.resolvers || {})) {
2838
- const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
2839
- const entryId = paramCase3(`${id}-${typeName}-${fieldName}`);
2840
- const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
2841
- const source = new AppsyncEventSource(entryId, lambda, {
2842
- apiId,
2843
- typeName,
2844
- fieldName,
2845
- code: Code2.fromInline(entryId, defaultResolver)
2846
- });
2847
- stack.add(lambda, source);
2857
+ for (const [typeName, fields] of Object.entries(props.resolvers || {})) {
2858
+ for (const [fieldName, functionProps] of Object.entries(fields || {})) {
2859
+ const entryId = paramCase4(`${id}-${typeName}-${fieldName}`);
2860
+ const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
2861
+ const source = new AppsyncEventSource(entryId, lambda, {
2862
+ apiId,
2863
+ typeName,
2864
+ fieldName,
2865
+ code: Code2.fromInline(entryId, defaultResolver)
2866
+ });
2867
+ stack.add(lambda, source);
2868
+ }
2848
2869
  }
2849
2870
  }
2850
2871
  }
@@ -4388,7 +4409,7 @@ var AppSchema = z23.object({
4388
4409
  /** The deployment stage.
4389
4410
  * @default 'prod'
4390
4411
  */
4391
- stage: z23.string().regex(/[a-z]+/).default("prod"),
4412
+ stage: z23.string().regex(/^[a-z]+$/).default("prod"),
4392
4413
  /** Default properties. */
4393
4414
  defaults: z23.object({}).default({}),
4394
4415
  /** The application stacks. */
@@ -4494,6 +4515,14 @@ var watchFile = (path) => {
4494
4515
  };
4495
4516
 
4496
4517
  // src/config.ts
4518
+ import { z as z24 } from "zod";
4519
+ var ConfigError = class extends Error {
4520
+ constructor(error, data) {
4521
+ super(error.message);
4522
+ this.error = error;
4523
+ this.data = data;
4524
+ }
4525
+ };
4497
4526
  var importConfig = async (options) => {
4498
4527
  debug("Find the root directory");
4499
4528
  const configFile = options.configFile || "awsless.config.ts";
@@ -4515,7 +4544,15 @@ var importConfig = async (options) => {
4515
4544
  schema2 = schema2.and(plugin.schema);
4516
4545
  }
4517
4546
  }
4518
- const config = await schema2.parseAsync(appConfig);
4547
+ let config;
4548
+ try {
4549
+ config = await schema2.parseAsync(appConfig);
4550
+ } catch (error) {
4551
+ if (error instanceof z24.ZodError) {
4552
+ throw new ConfigError(error, appConfig);
4553
+ }
4554
+ throw error;
4555
+ }
4519
4556
  debug("Load credentials", style.info(config.profile));
4520
4557
  const credentials = getCredentials(config.profile);
4521
4558
  debug("Load AWS account ID");
@@ -4548,7 +4585,15 @@ var watchConfig = async function* (options) {
4548
4585
  schema2 = schema2.and(plugin.schema);
4549
4586
  }
4550
4587
  }
4551
- const config = await schema2.parseAsync(appConfig);
4588
+ let config;
4589
+ try {
4590
+ config = await schema2.parseAsync(appConfig);
4591
+ } catch (error) {
4592
+ if (error instanceof z24.ZodError) {
4593
+ throw new ConfigError(error, appConfig);
4594
+ }
4595
+ throw error;
4596
+ }
4552
4597
  debug("Load credentials", style.info(config.profile));
4553
4598
  const credentials = getCredentials(config.profile);
4554
4599
  debug("Load AWS account ID");
@@ -4673,11 +4718,11 @@ var dialog = (type, lines) => {
4673
4718
  const padding = 3;
4674
4719
  const icon = style[type](symbol[type].padEnd(padding));
4675
4720
  return (term) => {
4676
- term.out.write(lines.map((line, i) => {
4721
+ term.out.write(lines.map((line2, i) => {
4677
4722
  if (i === 0) {
4678
- return icon + wrapAnsi(line, term.out.width(), { hard: true });
4723
+ return icon + wrapAnsi(line2, term.out.width(), { hard: true });
4679
4724
  }
4680
- return wrapAnsi(" ".repeat(padding) + line, term.out.width(), { hard: true });
4725
+ return wrapAnsi(" ".repeat(padding) + line2, term.out.width(), { hard: true });
4681
4726
  }).join(br()) + br());
4682
4727
  };
4683
4728
  };
@@ -5000,6 +5045,87 @@ var logs = () => {
5000
5045
  };
5001
5046
  };
5002
5047
 
5048
+ // src/cli/ui/layout/zod-error.ts
5049
+ var line = (value, level = 0, highlight = false) => {
5050
+ return [
5051
+ highlight ? style.error(symbol.pointerSmall) + style.placeholder(" | ") : style.placeholder.dim(" | "),
5052
+ " ".repeat(level),
5053
+ value,
5054
+ br()
5055
+ ];
5056
+ };
5057
+ var format = (value) => {
5058
+ if (Array.isArray(value)) {
5059
+ return "[ ... ]";
5060
+ }
5061
+ if (value === null) {
5062
+ return "null";
5063
+ }
5064
+ switch (typeof value) {
5065
+ case "function":
5066
+ return "() => { ... }";
5067
+ case "bigint":
5068
+ return `${value}n`;
5069
+ case "symbol":
5070
+ return "Symbol()";
5071
+ case "object":
5072
+ return "{ ... }";
5073
+ case "undefined":
5074
+ case "string":
5075
+ case "number":
5076
+ case "boolean":
5077
+ return JSON.stringify(value);
5078
+ }
5079
+ return "";
5080
+ };
5081
+ var zodError = (error, data) => {
5082
+ return (term) => {
5083
+ term.out.write(JSON.stringify(error.errors));
5084
+ for (const issue of error.issues) {
5085
+ term.out.gap();
5086
+ term.out.write(dialog("error", [
5087
+ style.error(issue.message)
5088
+ ]));
5089
+ term.out.gap();
5090
+ term.out.write(line("{"));
5091
+ let context = data;
5092
+ const inStack = issue.path[0] === "stacks" && typeof issue.path[1] === "number";
5093
+ const length2 = issue.path.length;
5094
+ const end = [];
5095
+ issue.path.forEach((path, i) => {
5096
+ const index = i + 1;
5097
+ context = context[path];
5098
+ if (typeof path === "string") {
5099
+ const key = path + `: `;
5100
+ if (index === length2) {
5101
+ const space = " ".repeat(key.length);
5102
+ const value = format(context);
5103
+ const error2 = "^".repeat(value.length);
5104
+ term.out.write(line(key + style.warning(value), index));
5105
+ term.out.write(line(space + style.error(error2), index, true));
5106
+ } else if (Array.isArray(context)) {
5107
+ term.out.write(line(key + "[", index));
5108
+ end.unshift(line("]", index));
5109
+ } else if (typeof context === "object") {
5110
+ if (inStack && index === 3) {
5111
+ const name = data.stacks[issue.path[1]].name;
5112
+ term.out.write(line("name: " + style.info(`"${name}"`) + ",", index));
5113
+ }
5114
+ term.out.write(line(key + "{", index));
5115
+ end.unshift(line("}", index));
5116
+ }
5117
+ } else if (typeof context === "object") {
5118
+ term.out.write(line("{", index));
5119
+ end.unshift(line("}", index));
5120
+ }
5121
+ });
5122
+ term.out.write(end);
5123
+ term.out.write(line("}"));
5124
+ term.out.gap();
5125
+ }
5126
+ };
5127
+ };
5128
+
5003
5129
  // src/cli/ui/layout/layout.ts
5004
5130
  var layout = async (cb) => {
5005
5131
  const term = createTerminal();
@@ -5015,7 +5141,9 @@ var layout = async (cb) => {
5015
5141
  await cb(config, term.out.write.bind(term.out), term);
5016
5142
  } catch (error) {
5017
5143
  term.out.gap();
5018
- if (error instanceof Error) {
5144
+ if (error instanceof ConfigError) {
5145
+ term.out.write(zodError(error.error, error.data));
5146
+ } else if (error instanceof Error) {
5019
5147
  term.out.write(dialog("error", [error.message]));
5020
5148
  } else if (typeof error === "string") {
5021
5149
  term.out.write(dialog("error", [error]));
@@ -5093,7 +5221,7 @@ var assetBuilder = (app) => {
5093
5221
  }
5094
5222
  const [icon, stop] = createSpinner();
5095
5223
  const details = new Signal({});
5096
- const line = flexLine(term, [
5224
+ const line2 = flexLine(term, [
5097
5225
  icon,
5098
5226
  " ",
5099
5227
  style.label(stack.name),
@@ -5117,7 +5245,7 @@ var assetBuilder = (app) => {
5117
5245
  }),
5118
5246
  br()
5119
5247
  ]);
5120
- group.update((group2) => [...group2, line]);
5248
+ group.update((group2) => [...group2, line2]);
5121
5249
  const timer = createTimer();
5122
5250
  try {
5123
5251
  const data = await asset.build({
@@ -5237,7 +5365,7 @@ var shouldDeployBootstrap = async (client, stack) => {
5237
5365
  // src/formation/client.ts
5238
5366
  import { CloudFormationClient, CreateStackCommand, DeleteStackCommand, DescribeStackEventsCommand, DescribeStacksCommand, GetTemplateCommand, OnFailure, TemplateStage, UpdateStackCommand, ValidateTemplateCommand, waitUntilStackCreateComplete, waitUntilStackDeleteComplete, waitUntilStackUpdateComplete } from "@aws-sdk/client-cloudformation";
5239
5367
  import { S3Client, PutObjectCommand, ObjectCannedACL, StorageClass } from "@aws-sdk/client-s3";
5240
- import { paramCase as paramCase4 } from "change-case";
5368
+ import { paramCase as paramCase5 } from "change-case";
5241
5369
  var StackClient = class {
5242
5370
  constructor(app, account, region, credentials) {
5243
5371
  this.app = app;
@@ -5270,7 +5398,7 @@ var StackClient = class {
5270
5398
  };
5271
5399
  }
5272
5400
  stackName(stackName) {
5273
- return paramCase4(`${this.app.name}-${stackName}`);
5401
+ return paramCase5(`${this.app.name}-${stackName}`);
5274
5402
  }
5275
5403
  tags(stack) {
5276
5404
  const tags = [];
@@ -5588,13 +5716,13 @@ var bootstrap = (program2) => {
5588
5716
 
5589
5717
  // src/cli/ui/complex/deployer.ts
5590
5718
  var stacksDeployer = (deploymentLine) => {
5591
- const stackNames = deploymentLine.map((line) => line.map((stack) => stack.name)).flat();
5719
+ const stackNames = deploymentLine.map((line2) => line2.map((stack) => stack.name)).flat();
5592
5720
  const stackNameSize = Math.max(...stackNames.map((name) => name.length));
5593
5721
  return (term) => {
5594
5722
  const ui = {};
5595
5723
  term.out.gap();
5596
5724
  for (const i in deploymentLine) {
5597
- const line = flexLine(
5725
+ const line2 = flexLine(
5598
5726
  term,
5599
5727
  [" "],
5600
5728
  [
@@ -5603,7 +5731,7 @@ var stacksDeployer = (deploymentLine) => {
5603
5731
  style.placeholder(" \u2500\u2500")
5604
5732
  ]
5605
5733
  );
5606
- term.out.write(line);
5734
+ term.out.write(line2);
5607
5735
  term.out.write(br());
5608
5736
  for (const stack of deploymentLine[i]) {
5609
5737
  const icon = new Signal(" ");
@@ -5783,8 +5911,8 @@ var deploy = (program2) => {
5783
5911
  const doneDeploying = write(loadingDialog("Deploying stacks to AWS..."));
5784
5912
  const client = new StackClient(app, config.account, config.region, config.credentials);
5785
5913
  const ui = write(stacksDeployer(deploymentLine));
5786
- for (const line of deploymentLine) {
5787
- const results = await Promise.allSettled(line.map(async (stack) => {
5914
+ for (const line2 of deploymentLine) {
5915
+ const results = await Promise.allSettled(line2.map(async (stack) => {
5788
5916
  const item = ui[stack.name];
5789
5917
  item.start("deploying");
5790
5918
  try {
package/dist/index.cjs CHANGED
@@ -172,7 +172,12 @@ var getCacheProps = (name, stack = STACK) => {
172
172
  };
173
173
  var Cache = createProxy((stack) => {
174
174
  return createProxy((name) => {
175
- return getCacheProps(name, stack);
175
+ const call = () => {
176
+ };
177
+ const { host, port } = getCacheProps(name, stack);
178
+ call.host = host;
179
+ call.port = port;
180
+ return call;
176
181
  });
177
182
  });
178
183