@awsless/awsless 0.0.7 → 0.0.9

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
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var import_commander = require("commander");
28
28
 
29
29
  // src/app.ts
30
- var import_aws_cdk_lib6 = require("aws-cdk-lib");
30
+ var import_aws_cdk_lib7 = require("aws-cdk-lib");
31
31
 
32
32
  // src/stack.ts
33
33
  var import_aws_cdk_lib = require("aws-cdk-lib");
@@ -215,6 +215,8 @@ var toStack = ({ config: config2, assets, app, stackConfig, plugins }) => {
215
215
  functions.forEach((lambda) => lambda.addToRolePolicy(allowConfigParameters));
216
216
  return {
217
217
  stack,
218
+ functions,
219
+ bindings,
218
220
  depends: stackConfig.depends
219
221
  };
220
222
  };
@@ -224,10 +226,11 @@ var import_path = require("path");
224
226
  var rootDir = process.cwd();
225
227
  var outDir = (0, import_path.join)(rootDir, ".awsless");
226
228
  var assemblyDir = (0, import_path.join)(outDir, "assembly");
227
- var functionDir = (0, import_path.join)(outDir, "function");
229
+ var assetDir = (0, import_path.join)(outDir, "asset");
230
+ var cacheDir = (0, import_path.join)(outDir, "cache");
228
231
 
229
232
  // src/stack/app-bootstrap.ts
230
- var import_aws_cdk_lib5 = require("aws-cdk-lib");
233
+ var import_aws_cdk_lib6 = require("aws-cdk-lib");
231
234
 
232
235
  // src/plugin.ts
233
236
  var definePlugin = (plugin) => plugin;
@@ -280,7 +283,7 @@ var toName = (stack, id) => {
280
283
  return (0, import_change_case.paramCase)(`${stack.stackName}-${id}`);
281
284
  };
282
285
  var toEnvKey = (resource, id) => {
283
- return (0, import_change_case.constantCase)(`RESOURCE_${resource}_${id}`);
286
+ return `RESOURCE_${resource.toUpperCase()}_${id}`;
284
287
  };
285
288
  var addResourceEnvironment = (stack, resource, id, lambda) => {
286
289
  const key = toEnvKey(resource, id);
@@ -379,43 +382,45 @@ var SizeSchema = import_zod7.z.custom((value) => {
379
382
  return import_zod7.z.string().regex(/[0-9]+ (KB|MB|GB)/).safeParse(value).success;
380
383
  }, "Invalid size").transform(toSize);
381
384
 
382
- // src/plugins/function/util/build-worker.ts
383
- var import_core3 = require("@swc/core");
385
+ // src/plugins/function/util/esbuild.ts
386
+ var import_esbuild = require("esbuild");
384
387
  var import_crypto = require("crypto");
388
+ var import_path3 = require("path");
389
+ var import_promises2 = require("fs/promises");
385
390
  var defaultBuild = async (file) => {
386
- const output = await (0, import_core3.bundle)({
387
- entry: {
388
- file
389
- },
390
- mode: "production",
391
- target: "node",
392
- externalModules: [
391
+ const random = (0, import_crypto.randomUUID)();
392
+ const codeFile = (0, import_path3.join)(cacheDir, `${random}.mjs`);
393
+ const mapFile = (0, import_path3.join)(cacheDir, `${random}.mjs.map`);
394
+ await (0, import_esbuild.build)({
395
+ entryPoints: [file],
396
+ minify: true,
397
+ bundle: true,
398
+ external: [
393
399
  "@aws-sdk/*",
394
400
  "@aws-sdk",
395
401
  "aws-sdk"
396
402
  ],
397
- module: {},
398
- options: {
399
- minify: true,
400
- sourceMaps: true,
401
- jsc: {
402
- target: "es2022"
403
- }
404
- },
405
- output: {
406
- name: "output",
407
- path: ""
408
- }
403
+ sourcemap: "external",
404
+ target: "esnext",
405
+ treeShaking: true,
406
+ // jsxSideEffects:
407
+ format: "esm",
408
+ platform: "node",
409
+ outfile: codeFile
409
410
  });
410
- const hash = (0, import_crypto.createHash)("sha1").update(output.file.code).digest("hex");
411
+ const code = await (0, import_promises2.readFile)(codeFile, "utf8");
412
+ const map = await (0, import_promises2.readFile)(mapFile, "utf8");
413
+ await (0, import_promises2.rm)(codeFile);
414
+ await (0, import_promises2.rm)(mapFile);
415
+ const hash = (0, import_crypto.createHash)("sha1").update(code).digest("hex");
411
416
  return {
412
417
  handler: "index.default",
413
418
  hash,
414
419
  files: [
415
420
  {
416
- name: "index.js",
417
- code: output.file.code,
418
- map: output.file.map?.toString()
421
+ name: "index.mjs",
422
+ code,
423
+ map
419
424
  }
420
425
  ]
421
426
  };
@@ -423,8 +428,8 @@ var defaultBuild = async (file) => {
423
428
 
424
429
  // src/plugins/function/util/build.ts
425
430
  var import_jszip = __toESM(require("jszip"), 1);
426
- var import_path3 = require("path");
427
- var import_promises2 = require("fs/promises");
431
+ var import_path5 = require("path");
432
+ var import_promises3 = require("fs/promises");
428
433
  var import_filesize = require("filesize");
429
434
  var zipFiles = (files) => {
430
435
  const zip = new import_jszip.default();
@@ -440,36 +445,36 @@ var zipFiles = (files) => {
440
445
  });
441
446
  };
442
447
  var writeBuildHash = async (config2, stack, id, hash) => {
443
- const funcPath = (0, import_path3.join)(functionDir, config2.name, stack.artifactId, id);
444
- const versionFile = (0, import_path3.join)(funcPath, "HASH");
445
- await (0, import_promises2.writeFile)(versionFile, hash);
448
+ const funcPath = (0, import_path5.join)(assetDir, "function", config2.name, stack.artifactId, id);
449
+ const versionFile = (0, import_path5.join)(funcPath, "HASH");
450
+ await (0, import_promises3.writeFile)(versionFile, hash);
446
451
  };
447
452
  var writeBuildFiles = async (config2, stack, id, files) => {
448
- const bundle2 = await zipFiles(files);
449
- const funcPath = (0, import_path3.join)(functionDir, config2.name, stack.artifactId, id);
450
- const filesPath = (0, import_path3.join)(funcPath, "files");
451
- const bundleFile = (0, import_path3.join)(funcPath, "bundle.zip");
452
- debug("Bundle size of", style.info((0, import_path3.join)(config2.name, stack.artifactId, id)), "is", style.attr((0, import_filesize.filesize)(bundle2.byteLength)));
453
- await (0, import_promises2.mkdir)(filesPath, { recursive: true });
454
- await (0, import_promises2.writeFile)(bundleFile, bundle2);
453
+ const bundle = await zipFiles(files);
454
+ const funcPath = (0, import_path5.join)(assetDir, "function", config2.name, stack.artifactId, id);
455
+ const filesPath = (0, import_path5.join)(funcPath, "files");
456
+ const bundleFile = (0, import_path5.join)(funcPath, "bundle.zip");
457
+ debug("Bundle size of", style.info((0, import_path5.join)(config2.name, stack.artifactId, id)), "is", style.attr((0, import_filesize.filesize)(bundle.byteLength)));
458
+ await (0, import_promises3.mkdir)(filesPath, { recursive: true });
459
+ await (0, import_promises3.writeFile)(bundleFile, bundle);
455
460
  await Promise.all(files.map(async (file) => {
456
- const fileName = (0, import_path3.join)(filesPath, file.name);
457
- await (0, import_promises2.mkdir)((0, import_path3.basename)(fileName), { recursive: true });
458
- await (0, import_promises2.writeFile)(fileName, file.code);
461
+ const fileName = (0, import_path5.join)(filesPath, file.name);
462
+ await (0, import_promises3.mkdir)((0, import_path5.basename)(fileName), { recursive: true });
463
+ await (0, import_promises3.writeFile)(fileName, file.code);
459
464
  if (file.map) {
460
- const mapName = (0, import_path3.join)(filesPath, `${file.name}.map`);
461
- await (0, import_promises2.writeFile)(mapName, file.map);
465
+ const mapName = (0, import_path5.join)(filesPath, `${file.name}.map`);
466
+ await (0, import_promises3.writeFile)(mapName, file.map);
462
467
  }
463
468
  }));
464
469
  return {
465
470
  file: bundleFile,
466
- size: bundle2.byteLength
471
+ size: bundle.byteLength
467
472
  };
468
473
  };
469
474
 
470
475
  // src/plugins/function/util/publish.ts
471
- var import_path5 = require("path");
472
- var import_promises3 = require("fs/promises");
476
+ var import_path7 = require("path");
477
+ var import_promises4 = require("fs/promises");
473
478
  var import_client_s3 = require("@aws-sdk/client-s3");
474
479
 
475
480
  // src/stack/bootstrap.ts
@@ -509,11 +514,11 @@ var shouldDeployBootstrap = async (client, name) => {
509
514
  var publishFunctionAsset = async (config2, stack, id) => {
510
515
  const bucket = assetBucketName(config2);
511
516
  const key = `${config2.name}/${stack.artifactId}/function/${id}.zip`;
512
- const funcPath = (0, import_path5.join)(functionDir, config2.name, stack.artifactId, id);
513
- const bundleFile = (0, import_path5.join)(funcPath, "bundle.zip");
514
- const hashFile = (0, import_path5.join)(funcPath, "HASH");
515
- const hash = await (0, import_promises3.readFile)(hashFile, "utf8");
516
- const file = await (0, import_promises3.readFile)(bundleFile);
517
+ const funcPath = (0, import_path7.join)(assetDir, "function", config2.name, stack.artifactId, id);
518
+ const bundleFile = (0, import_path7.join)(funcPath, "bundle.zip");
519
+ const hashFile = (0, import_path7.join)(funcPath, "HASH");
520
+ const hash = await (0, import_promises4.readFile)(hashFile, "utf8");
521
+ const file = await (0, import_promises4.readFile)(bundleFile);
517
522
  const client = new import_client_s3.S3Client({
518
523
  credentials: config2.credentials,
519
524
  region: config2.region
@@ -599,7 +604,7 @@ var functionPlugin = definePlugin({
599
604
  });
600
605
  }
601
606
  });
602
- var toFunction = ({ config: config2, stack, stackConfig, assets }, id, fileOrProps) => {
607
+ var toFunction = ({ config: config2, stack, assets }, id, fileOrProps) => {
603
608
  const props = typeof fileOrProps === "string" ? { ...config2.defaults?.function, file: fileOrProps } : { ...config2.defaults?.function, ...fileOrProps };
604
609
  const lambda = new import_aws_lambda3.Function(stack, toId("function", id), {
605
610
  functionName: toName(stack, id),
@@ -610,24 +615,24 @@ var toFunction = ({ config: config2, stack, stackConfig, assets }, id, fileOrPro
610
615
  });
611
616
  lambda.addEnvironment("APP", config2.name, { removeInEdge: true });
612
617
  lambda.addEnvironment("STAGE", config2.stage, { removeInEdge: true });
613
- lambda.addEnvironment("STACK", stackConfig.name, { removeInEdge: true });
618
+ lambda.addEnvironment("STACK", stack.artifactId, { removeInEdge: true });
614
619
  if (lambda.runtime.toString().startsWith("nodejs")) {
615
620
  lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1", {
616
621
  removeInEdge: true
617
622
  });
618
623
  }
619
624
  assets.add({
620
- stack: stackConfig,
625
+ stackName: stack.artifactId,
621
626
  resource: "function",
622
627
  resourceName: id,
623
628
  async build() {
624
629
  const result = await defaultBuild(props.file);
625
- const bundle2 = await writeBuildFiles(config2, stack, id, result.files);
630
+ const bundle = await writeBuildFiles(config2, stack, id, result.files);
626
631
  await writeBuildHash(config2, stack, id, result.hash);
627
632
  const func = lambda.node.defaultChild;
628
633
  func.handler = result.handler;
629
634
  return {
630
- size: formatByteSize(bundle2.size)
635
+ size: formatByteSize(bundle.size)
631
636
  };
632
637
  },
633
638
  async publish() {
@@ -863,7 +868,6 @@ var import_zod18 = require("zod");
863
868
  var import_aws_sns = require("aws-cdk-lib/aws-sns");
864
869
  var import_aws_lambda_event_sources2 = require("aws-cdk-lib/aws-lambda-event-sources");
865
870
  var import_aws_cdk_lib4 = require("aws-cdk-lib");
866
- var import_aws_iam2 = require("aws-cdk-lib/aws-iam");
867
871
  var topicPlugin = definePlugin({
868
872
  name: "topic",
869
873
  schema: import_zod18.z.object({
@@ -885,12 +889,6 @@ var topicPlugin = definePlugin({
885
889
  },
886
890
  onStack(ctx) {
887
891
  const { config: config2, stack, stackConfig, bind } = ctx;
888
- bind((lambda) => {
889
- lambda.addToRolePolicy(new import_aws_iam2.PolicyStatement({
890
- actions: ["sns:publish"],
891
- resources: ["*"]
892
- }));
893
- });
894
892
  return Object.entries(stackConfig.topics || {}).map(([id, props]) => {
895
893
  const lambda = toFunction(ctx, id, props);
896
894
  const topic = import_aws_sns.Topic.fromTopicArn(
@@ -903,6 +901,10 @@ var topicPlugin = definePlugin({
903
901
  }, stack)
904
902
  );
905
903
  lambda.addEventSource(new import_aws_lambda_event_sources2.SnsEventSource(topic));
904
+ bind((lambda2) => {
905
+ addResourceEnvironment(stack, "topic", id, lambda2);
906
+ topic.grantPublish(lambda2);
907
+ });
906
908
  return lambda;
907
909
  });
908
910
  }
@@ -911,7 +913,7 @@ var topicPlugin = definePlugin({
911
913
  // src/plugins/search.ts
912
914
  var import_zod19 = require("zod");
913
915
  var import_aws_opensearchserverless = require("aws-cdk-lib/aws-opensearchserverless");
914
- var import_aws_iam3 = require("aws-cdk-lib/aws-iam");
916
+ var import_aws_iam2 = require("aws-cdk-lib/aws-iam");
915
917
  var searchPlugin = definePlugin({
916
918
  name: "search",
917
919
  schema: import_zod19.z.object({
@@ -926,7 +928,7 @@ var searchPlugin = definePlugin({
926
928
  type: "SEARCH"
927
929
  });
928
930
  bind((lambda) => {
929
- lambda.addToRolePolicy(new import_aws_iam3.PolicyStatement({
931
+ lambda.addToRolePolicy(new import_aws_iam2.PolicyStatement({
930
932
  actions: ["aoss:APIAccessAll"],
931
933
  resources: [collection.attrArn]
932
934
  }));
@@ -935,6 +937,138 @@ var searchPlugin = definePlugin({
935
937
  }
936
938
  });
937
939
 
940
+ // src/plugins/graphql/index.ts
941
+ var import_zod21 = require("zod");
942
+ var import_aws_appsync = require("aws-cdk-lib/aws-appsync");
943
+ var import_merge = require("@graphql-tools/merge");
944
+ var import_promises5 = require("fs/promises");
945
+
946
+ // src/util/array.ts
947
+ var toArray = (value) => {
948
+ if (Array.isArray(value)) {
949
+ return value;
950
+ }
951
+ return [value];
952
+ };
953
+
954
+ // src/plugins/graphql/index.ts
955
+ var import_path8 = require("path");
956
+ var import_graphql = require("graphql");
957
+ var import_change_case2 = require("change-case");
958
+
959
+ // src/plugins/graphql/schema/resolver-field.ts
960
+ var import_zod20 = require("zod");
961
+ var ResolverFieldSchema = import_zod20.z.custom((value) => {
962
+ return import_zod20.z.string().regex(/([a-z0-9\_]+)(\s){1}([a-z0-9\_]+)/gi).safeParse(value).success;
963
+ }, `Invalid resolver field. Valid example: "Query list"`);
964
+
965
+ // src/plugins/graphql/index.ts
966
+ var import_aws_cdk_lib5 = require("aws-cdk-lib");
967
+ var graphqlPlugin = definePlugin({
968
+ name: "graphql",
969
+ schema: import_zod21.z.object({
970
+ defaults: import_zod21.z.object({
971
+ graphql: import_zod21.z.record(ResourceIdSchema, import_zod21.z.object({
972
+ authorization: import_zod21.z.object({
973
+ authorizer: FunctionSchema,
974
+ ttl: DurationSchema.default("1 hour")
975
+ }).optional(),
976
+ mappingTemplate: import_zod21.z.object({
977
+ request: LocalFileSchema.optional(),
978
+ response: LocalFileSchema.optional()
979
+ }).optional()
980
+ })).optional()
981
+ }).default({}),
982
+ stacks: import_zod21.z.object({
983
+ graphql: import_zod21.z.record(ResourceIdSchema, import_zod21.z.object({
984
+ schema: import_zod21.z.union([
985
+ LocalFileSchema,
986
+ import_zod21.z.array(LocalFileSchema).min(1)
987
+ ]).optional(),
988
+ resolvers: import_zod21.z.record(ResolverFieldSchema, FunctionSchema).optional()
989
+ })).optional()
990
+ }).array()
991
+ }),
992
+ onBootstrap({ config: config2, stack, assets }) {
993
+ const list3 = /* @__PURE__ */ new Set();
994
+ Object.values(config2.stacks).forEach((stackConfig) => {
995
+ Object.keys(stackConfig.graphql || {}).forEach((id) => {
996
+ list3.add(id);
997
+ });
998
+ });
999
+ list3.forEach((id) => {
1000
+ const file = (0, import_path8.join)(assetDir, "graphql", config2.name, id, "schema.graphql");
1001
+ const authorization = config2.defaults.graphql?.[id]?.authorization;
1002
+ const authProps = {};
1003
+ if (authorization) {
1004
+ const authorizer = toFunction({ config: config2, assets, stack }, `${id}-authorizer`, authorization.authorizer);
1005
+ authProps.additionalAuthenticationProviders = [{
1006
+ authenticationType: import_aws_appsync.AuthorizationType.LAMBDA,
1007
+ lambdaAuthorizerConfig: {
1008
+ authorizerUri: authorizer.functionArn,
1009
+ authorizerResultTtlInSeconds: authorization.ttl.toSeconds()
1010
+ }
1011
+ }];
1012
+ }
1013
+ const api = new import_aws_appsync.CfnGraphQLApi(stack, toId("graphql", id), {
1014
+ ...authProps,
1015
+ name: toName(stack, id),
1016
+ authenticationType: import_aws_appsync.AuthorizationType.API_KEY
1017
+ });
1018
+ new import_aws_cdk_lib5.CfnOutput(stack, toId("output", id), {
1019
+ exportName: toId("graphql", id),
1020
+ value: api.attrApiId
1021
+ });
1022
+ assets.add({
1023
+ stackName: stack.artifactId,
1024
+ resource: "schema",
1025
+ resourceName: id,
1026
+ async build() {
1027
+ const schemas = [];
1028
+ await Promise.all(Object.values(config2.stacks).map(async (stackConfig) => {
1029
+ const schemaFiles = toArray(stackConfig.graphql?.[id].schema || []);
1030
+ await Promise.all(schemaFiles.map(async (schemaFile) => {
1031
+ const schema3 = await (0, import_promises5.readFile)(schemaFile, "utf8");
1032
+ schemas.push(schema3);
1033
+ }));
1034
+ }));
1035
+ const schema2 = (0, import_graphql.print)((0, import_merge.mergeTypeDefs)(schemas));
1036
+ await (0, import_promises5.mkdir)((0, import_path8.dirname)(file), { recursive: true });
1037
+ await (0, import_promises5.writeFile)(file, schema2);
1038
+ new import_aws_appsync.CfnGraphQLSchema(stack, toId("schema", id), {
1039
+ apiId: api.attrApiId,
1040
+ definition: schema2
1041
+ });
1042
+ }
1043
+ });
1044
+ });
1045
+ },
1046
+ onStack(ctx) {
1047
+ const { config: config2, stack, stackConfig } = ctx;
1048
+ return Object.entries(stackConfig.graphql || {}).map(([id, props]) => {
1049
+ const defaults = config2.defaults.graphql?.[id] || {};
1050
+ return Object.entries(props.resolvers || {}).map(([typeAndField, functionProps]) => {
1051
+ const api = import_aws_appsync.GraphqlApi.fromGraphqlApiAttributes(stack, toId("graphql", id), {
1052
+ graphqlApiId: import_aws_cdk_lib5.Fn.importValue(toId("graphql", id))
1053
+ });
1054
+ const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
1055
+ const functionId = (0, import_change_case2.paramCase)(`${id}-${typeName}-${fieldName}`);
1056
+ const lambda = toFunction(ctx, functionId, functionProps);
1057
+ const source = api.addLambdaDataSource(toId("data-source", functionId), lambda, {
1058
+ name: toId("data-source", functionId)
1059
+ });
1060
+ source.createResolver(toId("resolver", functionId), {
1061
+ typeName,
1062
+ fieldName,
1063
+ requestMappingTemplate: defaults.mappingTemplate?.request ? import_aws_appsync.MappingTemplate.fromFile(defaults.mappingTemplate.request) : import_aws_appsync.MappingTemplate.lambdaRequest(),
1064
+ responseMappingTemplate: defaults.mappingTemplate?.response ? import_aws_appsync.MappingTemplate.fromFile(defaults.mappingTemplate.response) : import_aws_appsync.MappingTemplate.lambdaResult()
1065
+ });
1066
+ return lambda;
1067
+ });
1068
+ }).flat();
1069
+ }
1070
+ });
1071
+
938
1072
  // src/plugins/index.ts
939
1073
  var defaultPlugins = [
940
1074
  functionPlugin,
@@ -943,12 +1077,13 @@ var defaultPlugins = [
943
1077
  tablePlugin,
944
1078
  storePlugin,
945
1079
  topicPlugin,
946
- searchPlugin
1080
+ searchPlugin,
1081
+ graphqlPlugin
947
1082
  ];
948
1083
 
949
1084
  // src/stack/app-bootstrap.ts
950
1085
  var appBootstrapStack = ({ config: config2, app, assets }) => {
951
- const stack = new import_aws_cdk_lib5.Stack(app, "bootstrap", {
1086
+ const stack = new import_aws_cdk_lib6.Stack(app, "bootstrap", {
952
1087
  stackName: `${config2.name}-bootstrap`
953
1088
  });
954
1089
  const plugins = [
@@ -956,8 +1091,16 @@ var appBootstrapStack = ({ config: config2, app, assets }) => {
956
1091
  ...config2.plugins || []
957
1092
  ];
958
1093
  debug("Run plugin onBootstrap listeners");
959
- plugins.forEach((plugin) => plugin.onBootstrap?.({ config: config2, stack, app, assets }));
960
- return stack;
1094
+ const functions = plugins.map((plugin) => plugin.onBootstrap?.({
1095
+ config: config2,
1096
+ app,
1097
+ stack,
1098
+ assets
1099
+ })).filter(Boolean).flat().filter(Boolean);
1100
+ return {
1101
+ stack,
1102
+ functions
1103
+ };
961
1104
  };
962
1105
 
963
1106
  // src/util/deployment.ts
@@ -1023,10 +1166,10 @@ var Assets = class {
1023
1166
  assets = {};
1024
1167
  id = 0;
1025
1168
  add(opts) {
1026
- if (!this.assets[opts.stack.name]) {
1027
- this.assets[opts.stack.name] = [];
1169
+ if (!this.assets[opts.stackName]) {
1170
+ this.assets[opts.stackName] = [];
1028
1171
  }
1029
- this.assets[opts.stack.name].push({
1172
+ this.assets[opts.stackName].push({
1030
1173
  ...opts,
1031
1174
  id: this.id++
1032
1175
  });
@@ -1036,21 +1179,21 @@ var Assets = class {
1036
1179
  }
1037
1180
  forEach(cb) {
1038
1181
  Object.values(this.assets).forEach((assets) => {
1039
- cb(assets[0].stack, assets);
1182
+ cb(assets[0].stackName, assets);
1040
1183
  });
1041
1184
  }
1042
1185
  map(cb) {
1043
1186
  return Object.values(this.assets).map((assets) => {
1044
- return cb(assets[0].stack, assets);
1187
+ return cb(assets[0].stackName, assets);
1045
1188
  });
1046
1189
  }
1047
1190
  };
1048
1191
 
1049
1192
  // src/app.ts
1050
1193
  var makeApp = (config2) => {
1051
- return new import_aws_cdk_lib6.App({
1194
+ return new import_aws_cdk_lib7.App({
1052
1195
  outdir: assemblyDir,
1053
- defaultStackSynthesizer: new import_aws_cdk_lib6.DefaultStackSynthesizer({
1196
+ defaultStackSynthesizer: new import_aws_cdk_lib7.DefaultStackSynthesizer({
1054
1197
  fileAssetsBucketName: assetBucketName(config2),
1055
1198
  fileAssetPublishingRoleArn: "",
1056
1199
  generateBootstrapVersionRule: false
@@ -1079,13 +1222,14 @@ var toApp = async (config2, filters) => {
1079
1222
  debug("Plugins detected:", plugins.map((plugin) => style.info(plugin.name)).join(", "));
1080
1223
  debug("Run plugin onApp listeners");
1081
1224
  plugins.forEach((plugin) => plugin.onApp?.({ config: config2, app, assets }));
1225
+ const bootstrap2 = appBootstrapStack({ config: config2, app, assets });
1082
1226
  debug("Stack filters:", filters.map((filter) => style.info(filter)).join(", "));
1083
1227
  const filterdStacks = filters.length === 0 ? config2.stacks : getAllDepends(
1084
1228
  // config.stacks,
1085
1229
  config2.stacks.filter((stack) => filters.includes(stack.name))
1086
1230
  );
1087
1231
  for (const stackConfig of filterdStacks) {
1088
- const { stack } = toStack({
1232
+ const { stack, bindings } = toStack({
1089
1233
  config: config2,
1090
1234
  stackConfig,
1091
1235
  assets,
@@ -1093,14 +1237,14 @@ var toApp = async (config2, filters) => {
1093
1237
  app
1094
1238
  });
1095
1239
  stacks.push({ stack, config: stackConfig });
1240
+ bindings.forEach((cb) => bootstrap2.functions.forEach(cb));
1096
1241
  }
1097
1242
  let dependencyTree;
1098
- const bootstrap2 = appBootstrapStack({ config: config2, app, assets });
1099
- if (bootstrap2.node.children.length === 0) {
1243
+ if (bootstrap2.stack.node.children.length === 0) {
1100
1244
  dependencyTree = createDependencyTree(stacks, 0);
1101
1245
  } else {
1102
1246
  dependencyTree = [{
1103
- stack: bootstrap2,
1247
+ stack: bootstrap2.stack,
1104
1248
  level: 0,
1105
1249
  children: createDependencyTree(stacks, 1)
1106
1250
  }];
@@ -1172,7 +1316,7 @@ var footer = () => {
1172
1316
  };
1173
1317
 
1174
1318
  // src/config.ts
1175
- var import_path9 = require("path");
1319
+ var import_path13 = require("path");
1176
1320
 
1177
1321
  // src/util/account.ts
1178
1322
  var import_client_sts = require("@aws-sdk/client-sts");
@@ -1191,17 +1335,17 @@ var getCredentials = (profile) => {
1191
1335
  };
1192
1336
 
1193
1337
  // src/schema/app.ts
1194
- var import_zod23 = require("zod");
1338
+ var import_zod25 = require("zod");
1195
1339
 
1196
1340
  // src/schema/stack.ts
1197
- var import_zod20 = require("zod");
1198
- var StackSchema = import_zod20.z.object({
1341
+ var import_zod22 = require("zod");
1342
+ var StackSchema = import_zod22.z.object({
1199
1343
  name: ResourceIdSchema,
1200
- depends: import_zod20.z.array(import_zod20.z.lazy(() => StackSchema)).optional()
1344
+ depends: import_zod22.z.array(import_zod22.z.lazy(() => StackSchema)).optional()
1201
1345
  });
1202
1346
 
1203
1347
  // src/schema/region.ts
1204
- var import_zod21 = require("zod");
1348
+ var import_zod23 = require("zod");
1205
1349
  var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
1206
1350
  var AF = ["af-south-1"];
1207
1351
  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"];
@@ -1218,35 +1362,35 @@ var regions = [
1218
1362
  ...ME,
1219
1363
  ...SA
1220
1364
  ];
1221
- var RegionSchema = import_zod21.z.enum(regions);
1365
+ var RegionSchema = import_zod23.z.enum(regions);
1222
1366
 
1223
1367
  // src/schema/plugin.ts
1224
- var import_zod22 = require("zod");
1225
- var PluginSchema = import_zod22.z.object({
1226
- name: import_zod22.z.string(),
1227
- schema: import_zod22.z.custom().optional(),
1228
- depends: import_zod22.z.array(import_zod22.z.lazy(() => PluginSchema)).optional(),
1229
- onBootstrap: import_zod22.z.function().optional(),
1230
- onStack: import_zod22.z.function().returns(import_zod22.z.any()).optional(),
1231
- onApp: import_zod22.z.function().optional()
1368
+ var import_zod24 = require("zod");
1369
+ var PluginSchema = import_zod24.z.object({
1370
+ name: import_zod24.z.string(),
1371
+ schema: import_zod24.z.custom().optional(),
1372
+ // depends: z.array(z.lazy(() => PluginSchema)).optional(),
1373
+ onBootstrap: import_zod24.z.function().returns(import_zod24.z.any()).optional(),
1374
+ onStack: import_zod24.z.function().returns(import_zod24.z.any()).optional(),
1375
+ onApp: import_zod24.z.function().returns(import_zod24.z.void()).optional()
1232
1376
  // bind: z.function().optional(),
1233
1377
  });
1234
1378
 
1235
1379
  // src/schema/app.ts
1236
- var AppSchema = import_zod23.z.object({
1380
+ var AppSchema = import_zod25.z.object({
1237
1381
  name: ResourceIdSchema,
1238
1382
  region: RegionSchema,
1239
- profile: import_zod23.z.string(),
1240
- stage: import_zod23.z.string().regex(/[a-z]+/).default("prod"),
1241
- defaults: import_zod23.z.object({}).default({}),
1242
- stacks: import_zod23.z.array(StackSchema).min(1),
1243
- plugins: import_zod23.z.array(PluginSchema).optional()
1383
+ profile: import_zod25.z.string(),
1384
+ stage: import_zod25.z.string().regex(/[a-z]+/).default("prod"),
1385
+ defaults: import_zod25.z.object({}).default({}),
1386
+ stacks: import_zod25.z.array(StackSchema).min(1),
1387
+ plugins: import_zod25.z.array(PluginSchema).optional()
1244
1388
  });
1245
1389
 
1246
1390
  // src/util/import.ts
1247
- var import_core4 = require("@swc/core");
1248
- var import_path7 = require("path");
1249
- var import_promises4 = require("fs/promises");
1391
+ var import_core3 = require("@swc/core");
1392
+ var import_path11 = require("path");
1393
+ var import_promises6 = require("fs/promises");
1250
1394
  var resolveFileNameExtension = async (path) => {
1251
1395
  const options = [
1252
1396
  "",
@@ -1259,7 +1403,7 @@ var resolveFileNameExtension = async (path) => {
1259
1403
  const file = path + option;
1260
1404
  let stat;
1261
1405
  try {
1262
- stat = await (0, import_promises4.lstat)(file);
1406
+ stat = await (0, import_promises6.lstat)(file);
1263
1407
  } catch (error) {
1264
1408
  continue;
1265
1409
  }
@@ -1270,14 +1414,14 @@ var resolveFileNameExtension = async (path) => {
1270
1414
  throw new Error(`Failed to load file: ${path}`);
1271
1415
  };
1272
1416
  var resolveDir = (path) => {
1273
- return (0, import_path7.dirname)(path).replace(rootDir + "/", "");
1417
+ return (0, import_path11.dirname)(path).replace(rootDir + "/", "");
1274
1418
  };
1275
1419
  var importFile = async (path) => {
1276
1420
  const load = async (file) => {
1277
- let { code: code2 } = await (0, import_core4.transformFile)(file, {
1421
+ let { code: code2 } = await (0, import_core3.transformFile)(file, {
1278
1422
  isModule: true
1279
1423
  });
1280
- const path2 = (0, import_path7.dirname)(file);
1424
+ const path2 = (0, import_path11.dirname)(file);
1281
1425
  const dir = resolveDir(file);
1282
1426
  code2 = code2.replaceAll("__dirname", `"${dir}"`);
1283
1427
  const matches = code2.match(/import\s*{\s*[a-z0-9\_]+\s*}\s*from\s*('|")(\.[\/a-z0-9\_\-]+)('|");?/ig);
@@ -1286,23 +1430,23 @@ var importFile = async (path) => {
1286
1430
  await Promise.all(matches?.map(async (match) => {
1287
1431
  const parts = /('|")(\.[\/a-z0-9\_\-]+)('|")/ig.exec(match);
1288
1432
  const from = parts[2];
1289
- const file2 = await resolveFileNameExtension((0, import_path7.join)(path2, from));
1433
+ const file2 = await resolveFileNameExtension((0, import_path11.join)(path2, from));
1290
1434
  const result = await load(file2);
1291
1435
  code2 = code2.replace(match, result);
1292
1436
  }));
1293
1437
  return code2;
1294
1438
  };
1295
1439
  const code = await load(path);
1296
- const outputFile = (0, import_path7.join)(outDir, "config.js");
1297
- await (0, import_promises4.mkdir)(outDir, { recursive: true });
1298
- await (0, import_promises4.writeFile)(outputFile, code);
1440
+ const outputFile = (0, import_path11.join)(outDir, "config.js");
1441
+ await (0, import_promises6.mkdir)(outDir, { recursive: true });
1442
+ await (0, import_promises6.writeFile)(outputFile, code);
1299
1443
  return import(outputFile);
1300
1444
  };
1301
1445
 
1302
1446
  // src/config.ts
1303
1447
  var importConfig = async (options) => {
1304
1448
  debug("Import config file");
1305
- const fileName = (0, import_path9.join)(process.cwd(), options.configFile || "awsless.config.ts");
1449
+ const fileName = (0, import_path13.join)(process.cwd(), options.configFile || "awsless.config.ts");
1306
1450
  const module2 = await importFile(fileName);
1307
1451
  const appConfig = typeof module2.default === "function" ? await module2.default({
1308
1452
  profile: options.profile,
@@ -1516,6 +1660,13 @@ var Interface = class {
1516
1660
  if (this.input.isTTY) {
1517
1661
  this.input.setRawMode(true);
1518
1662
  }
1663
+ this.input.on("keypress", (_, key) => {
1664
+ const action = parseAction(key);
1665
+ if (action === "abort") {
1666
+ this.unref();
1667
+ process.exit(1);
1668
+ }
1669
+ });
1519
1670
  }
1520
1671
  // private subscriber: Actions | undefined
1521
1672
  readline;
@@ -1665,12 +1816,6 @@ var layout = async (cb) => {
1665
1816
  const term = createTerminal();
1666
1817
  term.out.clear();
1667
1818
  term.out.write(logo());
1668
- term.in.captureInput({
1669
- abort: () => {
1670
- term.in.showCursor();
1671
- process.exit(1);
1672
- }
1673
- });
1674
1819
  try {
1675
1820
  const options = program.optsWithGlobals();
1676
1821
  const config2 = await importConfig(options);
@@ -1691,7 +1836,7 @@ var layout = async (cb) => {
1691
1836
  term.in.unref();
1692
1837
  setTimeout(() => {
1693
1838
  process.exit(0);
1694
- }, 50);
1839
+ }, 100);
1695
1840
  }
1696
1841
  };
1697
1842
 
@@ -1722,7 +1867,8 @@ var assetBuilder = (assets) => {
1722
1867
  const groups = new Signal([br()]);
1723
1868
  term.out.write(groups);
1724
1869
  const stackNameSize = Math.max(...Object.keys(assets.list()).map((stack) => stack.length));
1725
- await Promise.all(assets.map(async (stack, assets2) => {
1870
+ const resourceSize = Math.max(...Object.values(assets.list()).map((assets2) => assets2.map((asset) => asset.resource.length)).flat());
1871
+ await Promise.all(assets.map(async (stackName, assets2) => {
1726
1872
  const group = new Signal([]);
1727
1873
  groups.update((groups2) => [...groups2, group]);
1728
1874
  await Promise.all(assets2.map(async (asset) => {
@@ -1731,12 +1877,13 @@ var assetBuilder = (assets) => {
1731
1877
  const line = flexLine(term, [
1732
1878
  icon,
1733
1879
  " ",
1734
- style.label(stack.name),
1735
- " ".repeat(stackNameSize - stack.name.length),
1880
+ style.label(stackName),
1881
+ " ".repeat(stackNameSize - stackName.length),
1736
1882
  " ",
1737
1883
  style.placeholder(symbol.pointerSmall),
1738
1884
  " ",
1739
1885
  style.warning(asset.resource),
1886
+ " ".repeat(resourceSize - asset.resource.length),
1740
1887
  " ",
1741
1888
  style.placeholder(symbol.pointerSmall),
1742
1889
  " ",
@@ -1767,25 +1914,26 @@ var assetBuilder = (assets) => {
1767
1914
  };
1768
1915
 
1769
1916
  // src/util/cleanup.ts
1770
- var import_promises5 = require("fs/promises");
1917
+ var import_promises7 = require("fs/promises");
1771
1918
  var cleanUp = async () => {
1772
1919
  debug("Clean up assembly & asset files");
1773
1920
  const paths = [
1774
1921
  assemblyDir,
1775
- functionDir
1922
+ assetDir,
1923
+ cacheDir
1776
1924
  ];
1777
- await Promise.all(paths.map((path) => (0, import_promises5.rm)(path, {
1925
+ await Promise.all(paths.map((path) => (0, import_promises7.rm)(path, {
1778
1926
  recursive: true,
1779
1927
  force: true,
1780
1928
  maxRetries: 2
1781
1929
  })));
1782
- await Promise.all(paths.map((path) => (0, import_promises5.mkdir)(path, {
1930
+ await Promise.all(paths.map((path) => (0, import_promises7.mkdir)(path, {
1783
1931
  recursive: true
1784
1932
  })));
1785
1933
  };
1786
1934
 
1787
1935
  // src/cli/command/build.ts
1788
- var build = (program2) => {
1936
+ var build2 = (program2) => {
1789
1937
  program2.command("build").argument("[stack...]", "Optionally filter stacks to build").description("Build your app").action(async (filters) => {
1790
1938
  await layout(async (config2, write) => {
1791
1939
  const { app, assets } = await toApp(config2, filters);
@@ -1903,7 +2051,7 @@ var StackClient = class {
1903
2051
  stack.Outputs?.forEach((output) => {
1904
2052
  outputs[output.OutputKey] = output.OutputValue;
1905
2053
  });
1906
- debug("Status for: ", style.info(name), "is", stack.StackStatus);
2054
+ debug("Status for:", style.info(name), "is", style.attr(stack.StackStatus));
1907
2055
  return {
1908
2056
  status: stack.StackStatus,
1909
2057
  reason: stack.StackStatusReason,
@@ -2169,6 +2317,7 @@ var deploy = (program2) => {
2169
2317
  await cleanUp();
2170
2318
  await write(assetBuilder(assets));
2171
2319
  write(br());
2320
+ write(br());
2172
2321
  const donePublishing = write(loadingDialog("Publishing stack assets to AWS..."));
2173
2322
  await Promise.all(assets.map(async (_, assets2) => {
2174
2323
  await Promise.all(assets2.map(async (asset) => {
@@ -2184,21 +2333,28 @@ var deploy = (program2) => {
2184
2333
  const doneDeploying = write(loadingDialog("Deploying stacks to AWS..."));
2185
2334
  write(br());
2186
2335
  write(stackTree(dependencyTree, statuses));
2336
+ write(br());
2187
2337
  const client = new StackClient(config2);
2188
2338
  const deploymentLine = createDeploymentLine(dependencyTree);
2189
2339
  for (const stacks of deploymentLine) {
2190
- await Promise.allSettled(stacks.map(async (stack) => {
2340
+ const results = await Promise.allSettled(stacks.map(async (stack) => {
2341
+ const signal = statuses[stack.artifactId];
2191
2342
  const stackArtifect = assembly.stacks.find((item) => item.id === stack.artifactId);
2192
- statuses[stack.artifactId].set(style.warning("deploying"));
2343
+ signal.set(style.warning("deploying"));
2193
2344
  try {
2194
2345
  await client.deploy(stackArtifect);
2195
2346
  } catch (error) {
2196
2347
  debugError(error);
2197
- statuses[stack.artifactId].set(style.error("failed"));
2348
+ signal.set(style.error("failed"));
2198
2349
  throw error;
2199
2350
  }
2200
- statuses[stack.artifactId].set(style.success("deployed"));
2351
+ signal.set(style.success("deployed"));
2201
2352
  }));
2353
+ for (const result of results) {
2354
+ if (result.status === "rejected") {
2355
+ throw result.reason;
2356
+ }
2357
+ }
2202
2358
  }
2203
2359
  doneDeploying("Done deploying stacks to AWS");
2204
2360
  });
@@ -2373,7 +2529,7 @@ program.on("option:verbose", () => {
2373
2529
  var commands2 = [
2374
2530
  bootstrap,
2375
2531
  status,
2376
- build,
2532
+ build2,
2377
2533
  deploy,
2378
2534
  config
2379
2535
  // diff,