@awsless/awsless 0.0.8 → 0.0.10

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
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- __require,
4
3
  definePlugin
5
- } from "./chunk-6KILQ5DR.js";
4
+ } from "./chunk-PFTL6L4F.js";
6
5
 
7
6
  // src/cli/program.ts
8
7
  import { Command } from "commander";
@@ -196,6 +195,8 @@ var toStack = ({ config: config2, assets, app, stackConfig, plugins }) => {
196
195
  functions.forEach((lambda) => lambda.addToRolePolicy(allowConfigParameters));
197
196
  return {
198
197
  stack,
198
+ functions,
199
+ bindings,
199
200
  depends: stackConfig.depends
200
201
  };
201
202
  };
@@ -205,7 +206,8 @@ import { join } from "path";
205
206
  var rootDir = process.cwd();
206
207
  var outDir = join(rootDir, ".awsless");
207
208
  var assemblyDir = join(outDir, "assembly");
208
- var functionDir = join(outDir, "function");
209
+ var assetDir = join(outDir, "asset");
210
+ var cacheDir = join(outDir, "cache");
209
211
 
210
212
  // src/stack/app-bootstrap.ts
211
213
  import { Stack as Stack3 } from "aws-cdk-lib";
@@ -250,7 +252,7 @@ var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
250
252
  import { Rule } from "aws-cdk-lib/aws-events";
251
253
 
252
254
  // src/util/resource.ts
253
- import { constantCase, paramCase, pascalCase } from "change-case";
255
+ import { paramCase, pascalCase } from "change-case";
254
256
  var toId = (resource, id) => {
255
257
  return pascalCase(`${resource}-${id}`);
256
258
  };
@@ -258,7 +260,7 @@ var toName = (stack, id) => {
258
260
  return paramCase(`${stack.stackName}-${id}`);
259
261
  };
260
262
  var toEnvKey = (resource, id) => {
261
- return constantCase(`RESOURCE_${resource}_${id}`);
263
+ return `RESOURCE_${resource.toUpperCase()}_${id}`;
262
264
  };
263
265
  var addResourceEnvironment = (stack, resource, id, lambda) => {
264
266
  const key = toEnvKey(resource, id);
@@ -357,72 +359,6 @@ var SizeSchema = z7.custom((value) => {
357
359
  return z7.string().regex(/[0-9]+ (KB|MB|GB)/).safeParse(value).success;
358
360
  }, "Invalid size").transform(toSize);
359
361
 
360
- // src/plugins/function/util/build-worker.ts
361
- import { Worker } from "worker_threads";
362
- var cjs = typeof __require !== "undefined";
363
- var importESM = `
364
- import { bundle } from "@awsless/code";
365
- import { createHash } from "crypto";
366
- import { parentPort, workerData } from "worker_threads";
367
- `;
368
- var importCJS = `
369
- const { bundle } = require("@awsless/code");
370
- const { createHash } = require("crypto");
371
- const { parentPort, workerData } = require("worker_threads");
372
- `;
373
- var workerCode = `
374
- ${cjs ? importCJS : importESM}
375
-
376
- const build = async (file) => {
377
- const { code, map } = await bundle(file, {
378
- format: 'esm',
379
- sourceMap: true,
380
- minimize: true,
381
- onwarn: () => {},
382
- moduleSideEffects: (id) => file === id,
383
- external: (importee) => (
384
- importee.startsWith('aws-sdk') ||
385
- importee.startsWith('@aws-sdk')
386
- ),
387
- })
388
-
389
- const hash = createHash('sha1').update(code).digest('hex')
390
-
391
- parentPort.postMessage(JSON.stringify({
392
- handler: 'index.default',
393
- hash,
394
- files: [
395
- { name: 'index.js', code, map: map?.toString() }
396
- ]
397
- }))
398
- }
399
-
400
- build(workerData)
401
- `;
402
- var defaultBuild = async (file) => {
403
- return new Promise((resolve, reject) => {
404
- const worker = new Worker(workerCode, { workerData: file, eval: true });
405
- const cleanUp2 = () => {
406
- worker.removeAllListeners();
407
- worker.terminate();
408
- };
409
- worker.on("message", (data) => {
410
- resolve(JSON.parse(data.toString("utf8")));
411
- cleanUp2();
412
- });
413
- worker.on("error", (data) => {
414
- reject(data);
415
- cleanUp2();
416
- });
417
- worker.on("exit", (code) => {
418
- if (code !== 0) {
419
- reject(new Error(`Worker exited with code ${code}`));
420
- cleanUp2();
421
- }
422
- });
423
- });
424
- };
425
-
426
362
  // src/plugins/function/util/build.ts
427
363
  import JSZip from "jszip";
428
364
  import { basename, join as join2 } from "path";
@@ -442,13 +378,13 @@ var zipFiles = (files) => {
442
378
  });
443
379
  };
444
380
  var writeBuildHash = async (config2, stack, id, hash) => {
445
- const funcPath = join2(functionDir, config2.name, stack.artifactId, id);
381
+ const funcPath = join2(assetDir, "function", config2.name, stack.artifactId, id);
446
382
  const versionFile = join2(funcPath, "HASH");
447
383
  await writeFile(versionFile, hash);
448
384
  };
449
385
  var writeBuildFiles = async (config2, stack, id, files) => {
450
386
  const bundle = await zipFiles(files);
451
- const funcPath = join2(functionDir, config2.name, stack.artifactId, id);
387
+ const funcPath = join2(assetDir, "function", config2.name, stack.artifactId, id);
452
388
  const filesPath = join2(funcPath, "files");
453
389
  const bundleFile = join2(funcPath, "bundle.zip");
454
390
  debug("Bundle size of", style.info(join2(config2.name, stack.artifactId, id)), "is", style.attr(filesize(bundle.byteLength)));
@@ -511,7 +447,7 @@ var shouldDeployBootstrap = async (client, name) => {
511
447
  var publishFunctionAsset = async (config2, stack, id) => {
512
448
  const bucket = assetBucketName(config2);
513
449
  const key = `${config2.name}/${stack.artifactId}/function/${id}.zip`;
514
- const funcPath = join3(functionDir, config2.name, stack.artifactId, id);
450
+ const funcPath = join3(assetDir, "function", config2.name, stack.artifactId, id);
515
451
  const bundleFile = join3(funcPath, "bundle.zip");
516
452
  const hashFile = join3(funcPath, "HASH");
517
453
  const hash = await readFile(hashFile, "utf8");
@@ -559,6 +495,53 @@ var formatByteSize = (size) => {
559
495
  return style.attr(number) + style.attr.dim(unit);
560
496
  };
561
497
 
498
+ // src/plugins/function/util/bundler/rollup.ts
499
+ import { rollup } from "rollup";
500
+ import { createHash } from "crypto";
501
+ import { swc } from "rollup-plugin-swc3";
502
+ import commonjs from "@rollup/plugin-commonjs";
503
+ import nodeResolve from "@rollup/plugin-node-resolve";
504
+ var rollupBuild = async (input) => {
505
+ const bundle = await rollup({
506
+ input,
507
+ external: (importee) => {
508
+ return importee.startsWith("@aws-sdk") || importee.startsWith("aws-sdk");
509
+ },
510
+ onwarn: (error) => {
511
+ debugError(error.message);
512
+ },
513
+ treeshake: {
514
+ moduleSideEffects: (id) => input === id
515
+ },
516
+ plugins: [
517
+ commonjs({ sourceMap: true }),
518
+ nodeResolve({
519
+ preferBuiltins: true
520
+ }),
521
+ swc({
522
+ minify: true,
523
+ jsc: { minify: { sourceMap: true } },
524
+ sourceMaps: true
525
+ })
526
+ ]
527
+ });
528
+ const { output: [output] } = await bundle.generate({
529
+ format: "esm",
530
+ sourcemap: "hidden",
531
+ exports: "default"
532
+ });
533
+ const hash = createHash("sha1").update(output.code).digest("hex");
534
+ return {
535
+ handler: "index.default",
536
+ hash,
537
+ files: [{
538
+ name: "index.mjs",
539
+ code: output.code,
540
+ map: output.map?.toString()
541
+ }]
542
+ };
543
+ };
544
+
562
545
  // src/plugins/function/index.ts
563
546
  var FunctionSchema = z9.union([
564
547
  LocalFileSchema,
@@ -601,7 +584,7 @@ var functionPlugin = definePlugin({
601
584
  });
602
585
  }
603
586
  });
604
- var toFunction = ({ config: config2, stack, stackConfig, assets }, id, fileOrProps) => {
587
+ var toFunction = ({ config: config2, stack, assets }, id, fileOrProps) => {
605
588
  const props = typeof fileOrProps === "string" ? { ...config2.defaults?.function, file: fileOrProps } : { ...config2.defaults?.function, ...fileOrProps };
606
589
  const lambda = new Function(stack, toId("function", id), {
607
590
  functionName: toName(stack, id),
@@ -612,18 +595,18 @@ var toFunction = ({ config: config2, stack, stackConfig, assets }, id, fileOrPro
612
595
  });
613
596
  lambda.addEnvironment("APP", config2.name, { removeInEdge: true });
614
597
  lambda.addEnvironment("STAGE", config2.stage, { removeInEdge: true });
615
- lambda.addEnvironment("STACK", stackConfig.name, { removeInEdge: true });
598
+ lambda.addEnvironment("STACK", stack.artifactId, { removeInEdge: true });
616
599
  if (lambda.runtime.toString().startsWith("nodejs")) {
617
600
  lambda.addEnvironment("AWS_NODEJS_CONNECTION_REUSE_ENABLED", "1", {
618
601
  removeInEdge: true
619
602
  });
620
603
  }
621
604
  assets.add({
622
- stack: stackConfig,
605
+ stackName: stack.artifactId,
623
606
  resource: "function",
624
607
  resourceName: id,
625
608
  async build() {
626
- const result = await defaultBuild(props.file);
609
+ const result = await rollupBuild(props.file);
627
610
  const bundle = await writeBuildFiles(config2, stack, id, result.files);
628
611
  await writeBuildHash(config2, stack, id, result.hash);
629
612
  const func = lambda.node.defaultChild;
@@ -865,7 +848,6 @@ import { z as z18 } from "zod";
865
848
  import { Topic } from "aws-cdk-lib/aws-sns";
866
849
  import { SnsEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
867
850
  import { Arn as Arn2, ArnFormat } from "aws-cdk-lib";
868
- import { PolicyStatement as PolicyStatement2 } from "aws-cdk-lib/aws-iam";
869
851
  var topicPlugin = definePlugin({
870
852
  name: "topic",
871
853
  schema: z18.object({
@@ -887,12 +869,6 @@ var topicPlugin = definePlugin({
887
869
  },
888
870
  onStack(ctx) {
889
871
  const { config: config2, stack, stackConfig, bind } = ctx;
890
- bind((lambda) => {
891
- lambda.addToRolePolicy(new PolicyStatement2({
892
- actions: ["sns:publish"],
893
- resources: ["*"]
894
- }));
895
- });
896
872
  return Object.entries(stackConfig.topics || {}).map(([id, props]) => {
897
873
  const lambda = toFunction(ctx, id, props);
898
874
  const topic = Topic.fromTopicArn(
@@ -905,6 +881,10 @@ var topicPlugin = definePlugin({
905
881
  }, stack)
906
882
  );
907
883
  lambda.addEventSource(new SnsEventSource(topic));
884
+ bind((lambda2) => {
885
+ addResourceEnvironment(stack, "topic", id, lambda2);
886
+ topic.grantPublish(lambda2);
887
+ });
908
888
  return lambda;
909
889
  });
910
890
  }
@@ -913,7 +893,7 @@ var topicPlugin = definePlugin({
913
893
  // src/plugins/search.ts
914
894
  import { z as z19 } from "zod";
915
895
  import { CfnCollection } from "aws-cdk-lib/aws-opensearchserverless";
916
- import { PolicyStatement as PolicyStatement3 } from "aws-cdk-lib/aws-iam";
896
+ import { PolicyStatement as PolicyStatement2 } from "aws-cdk-lib/aws-iam";
917
897
  var searchPlugin = definePlugin({
918
898
  name: "search",
919
899
  schema: z19.object({
@@ -928,7 +908,7 @@ var searchPlugin = definePlugin({
928
908
  type: "SEARCH"
929
909
  });
930
910
  bind((lambda) => {
931
- lambda.addToRolePolicy(new PolicyStatement3({
911
+ lambda.addToRolePolicy(new PolicyStatement2({
932
912
  actions: ["aoss:APIAccessAll"],
933
913
  resources: [collection.attrArn]
934
914
  }));
@@ -937,6 +917,138 @@ var searchPlugin = definePlugin({
937
917
  }
938
918
  });
939
919
 
920
+ // src/plugins/graphql/index.ts
921
+ import { z as z21 } from "zod";
922
+ import { AuthorizationType, CfnGraphQLApi, CfnGraphQLSchema, GraphqlApi, MappingTemplate } from "aws-cdk-lib/aws-appsync";
923
+ import { mergeTypeDefs } from "@graphql-tools/merge";
924
+ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
925
+
926
+ // src/util/array.ts
927
+ var toArray = (value) => {
928
+ if (Array.isArray(value)) {
929
+ return value;
930
+ }
931
+ return [value];
932
+ };
933
+
934
+ // src/plugins/graphql/index.ts
935
+ import { dirname, join as join4 } from "path";
936
+ import { print } from "graphql";
937
+ import { paramCase as paramCase2 } from "change-case";
938
+
939
+ // src/plugins/graphql/schema/resolver-field.ts
940
+ import { z as z20 } from "zod";
941
+ var ResolverFieldSchema = z20.custom((value) => {
942
+ return z20.string().regex(/([a-z0-9\_]+)(\s){1}([a-z0-9\_]+)/gi).safeParse(value).success;
943
+ }, `Invalid resolver field. Valid example: "Query list"`);
944
+
945
+ // src/plugins/graphql/index.ts
946
+ import { CfnOutput as CfnOutput2, Fn } from "aws-cdk-lib";
947
+ var graphqlPlugin = definePlugin({
948
+ name: "graphql",
949
+ schema: z21.object({
950
+ defaults: z21.object({
951
+ graphql: z21.record(ResourceIdSchema, z21.object({
952
+ authorization: z21.object({
953
+ authorizer: FunctionSchema,
954
+ ttl: DurationSchema.default("1 hour")
955
+ }).optional(),
956
+ mappingTemplate: z21.object({
957
+ request: LocalFileSchema.optional(),
958
+ response: LocalFileSchema.optional()
959
+ }).optional()
960
+ })).optional()
961
+ }).default({}),
962
+ stacks: z21.object({
963
+ graphql: z21.record(ResourceIdSchema, z21.object({
964
+ schema: z21.union([
965
+ LocalFileSchema,
966
+ z21.array(LocalFileSchema).min(1)
967
+ ]).optional(),
968
+ resolvers: z21.record(ResolverFieldSchema, FunctionSchema).optional()
969
+ })).optional()
970
+ }).array()
971
+ }),
972
+ onBootstrap({ config: config2, stack, assets }) {
973
+ const list3 = /* @__PURE__ */ new Set();
974
+ Object.values(config2.stacks).forEach((stackConfig) => {
975
+ Object.keys(stackConfig.graphql || {}).forEach((id) => {
976
+ list3.add(id);
977
+ });
978
+ });
979
+ list3.forEach((id) => {
980
+ const file = join4(assetDir, "graphql", config2.name, id, "schema.graphql");
981
+ const authorization = config2.defaults.graphql?.[id]?.authorization;
982
+ const authProps = {};
983
+ if (authorization) {
984
+ const authorizer = toFunction({ config: config2, assets, stack }, `${id}-authorizer`, authorization.authorizer);
985
+ authProps.additionalAuthenticationProviders = [{
986
+ authenticationType: AuthorizationType.LAMBDA,
987
+ lambdaAuthorizerConfig: {
988
+ authorizerUri: authorizer.functionArn,
989
+ authorizerResultTtlInSeconds: authorization.ttl.toSeconds()
990
+ }
991
+ }];
992
+ }
993
+ const api = new CfnGraphQLApi(stack, toId("graphql", id), {
994
+ ...authProps,
995
+ name: toName(stack, id),
996
+ authenticationType: AuthorizationType.API_KEY
997
+ });
998
+ new CfnOutput2(stack, toId("output", id), {
999
+ exportName: toId("graphql", id),
1000
+ value: api.attrApiId
1001
+ });
1002
+ assets.add({
1003
+ stackName: stack.artifactId,
1004
+ resource: "schema",
1005
+ resourceName: id,
1006
+ async build() {
1007
+ const schemas = [];
1008
+ await Promise.all(Object.values(config2.stacks).map(async (stackConfig) => {
1009
+ const schemaFiles = toArray(stackConfig.graphql?.[id].schema || []);
1010
+ await Promise.all(schemaFiles.map(async (schemaFile) => {
1011
+ const schema3 = await readFile2(schemaFile, "utf8");
1012
+ schemas.push(schema3);
1013
+ }));
1014
+ }));
1015
+ const schema2 = print(mergeTypeDefs(schemas));
1016
+ await mkdir2(dirname(file), { recursive: true });
1017
+ await writeFile2(file, schema2);
1018
+ new CfnGraphQLSchema(stack, toId("schema", id), {
1019
+ apiId: api.attrApiId,
1020
+ definition: schema2
1021
+ });
1022
+ }
1023
+ });
1024
+ });
1025
+ },
1026
+ onStack(ctx) {
1027
+ const { config: config2, stack, stackConfig } = ctx;
1028
+ return Object.entries(stackConfig.graphql || {}).map(([id, props]) => {
1029
+ const defaults = config2.defaults.graphql?.[id] || {};
1030
+ return Object.entries(props.resolvers || {}).map(([typeAndField, functionProps]) => {
1031
+ const api = GraphqlApi.fromGraphqlApiAttributes(stack, toId("graphql", id), {
1032
+ graphqlApiId: Fn.importValue(toId("graphql", id))
1033
+ });
1034
+ const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
1035
+ const functionId = paramCase2(`${id}-${typeName}-${fieldName}`);
1036
+ const lambda = toFunction(ctx, functionId, functionProps);
1037
+ const source = api.addLambdaDataSource(toId("data-source", functionId), lambda, {
1038
+ name: toId("data-source", functionId)
1039
+ });
1040
+ source.createResolver(toId("resolver", functionId), {
1041
+ typeName,
1042
+ fieldName,
1043
+ requestMappingTemplate: defaults.mappingTemplate?.request ? MappingTemplate.fromFile(defaults.mappingTemplate.request) : MappingTemplate.lambdaRequest(),
1044
+ responseMappingTemplate: defaults.mappingTemplate?.response ? MappingTemplate.fromFile(defaults.mappingTemplate.response) : MappingTemplate.lambdaResult()
1045
+ });
1046
+ return lambda;
1047
+ });
1048
+ }).flat();
1049
+ }
1050
+ });
1051
+
940
1052
  // src/plugins/index.ts
941
1053
  var defaultPlugins = [
942
1054
  functionPlugin,
@@ -945,7 +1057,8 @@ var defaultPlugins = [
945
1057
  tablePlugin,
946
1058
  storePlugin,
947
1059
  topicPlugin,
948
- searchPlugin
1060
+ searchPlugin,
1061
+ graphqlPlugin
949
1062
  ];
950
1063
 
951
1064
  // src/stack/app-bootstrap.ts
@@ -958,8 +1071,16 @@ var appBootstrapStack = ({ config: config2, app, assets }) => {
958
1071
  ...config2.plugins || []
959
1072
  ];
960
1073
  debug("Run plugin onBootstrap listeners");
961
- plugins.forEach((plugin) => plugin.onBootstrap?.({ config: config2, stack, app, assets }));
962
- return stack;
1074
+ const functions = plugins.map((plugin) => plugin.onBootstrap?.({
1075
+ config: config2,
1076
+ app,
1077
+ stack,
1078
+ assets
1079
+ })).filter(Boolean).flat().filter(Boolean);
1080
+ return {
1081
+ stack,
1082
+ functions
1083
+ };
963
1084
  };
964
1085
 
965
1086
  // src/util/deployment.ts
@@ -1025,10 +1146,10 @@ var Assets = class {
1025
1146
  assets = {};
1026
1147
  id = 0;
1027
1148
  add(opts) {
1028
- if (!this.assets[opts.stack.name]) {
1029
- this.assets[opts.stack.name] = [];
1149
+ if (!this.assets[opts.stackName]) {
1150
+ this.assets[opts.stackName] = [];
1030
1151
  }
1031
- this.assets[opts.stack.name].push({
1152
+ this.assets[opts.stackName].push({
1032
1153
  ...opts,
1033
1154
  id: this.id++
1034
1155
  });
@@ -1038,12 +1159,12 @@ var Assets = class {
1038
1159
  }
1039
1160
  forEach(cb) {
1040
1161
  Object.values(this.assets).forEach((assets) => {
1041
- cb(assets[0].stack, assets);
1162
+ cb(assets[0].stackName, assets);
1042
1163
  });
1043
1164
  }
1044
1165
  map(cb) {
1045
1166
  return Object.values(this.assets).map((assets) => {
1046
- return cb(assets[0].stack, assets);
1167
+ return cb(assets[0].stackName, assets);
1047
1168
  });
1048
1169
  }
1049
1170
  };
@@ -1081,13 +1202,14 @@ var toApp = async (config2, filters) => {
1081
1202
  debug("Plugins detected:", plugins.map((plugin) => style.info(plugin.name)).join(", "));
1082
1203
  debug("Run plugin onApp listeners");
1083
1204
  plugins.forEach((plugin) => plugin.onApp?.({ config: config2, app, assets }));
1205
+ const bootstrap2 = appBootstrapStack({ config: config2, app, assets });
1084
1206
  debug("Stack filters:", filters.map((filter) => style.info(filter)).join(", "));
1085
1207
  const filterdStacks = filters.length === 0 ? config2.stacks : getAllDepends(
1086
1208
  // config.stacks,
1087
1209
  config2.stacks.filter((stack) => filters.includes(stack.name))
1088
1210
  );
1089
1211
  for (const stackConfig of filterdStacks) {
1090
- const { stack } = toStack({
1212
+ const { stack, bindings } = toStack({
1091
1213
  config: config2,
1092
1214
  stackConfig,
1093
1215
  assets,
@@ -1095,14 +1217,14 @@ var toApp = async (config2, filters) => {
1095
1217
  app
1096
1218
  });
1097
1219
  stacks.push({ stack, config: stackConfig });
1220
+ bindings.forEach((cb) => bootstrap2.functions.forEach(cb));
1098
1221
  }
1099
1222
  let dependencyTree;
1100
- const bootstrap2 = appBootstrapStack({ config: config2, app, assets });
1101
- if (bootstrap2.node.children.length === 0) {
1223
+ if (bootstrap2.stack.node.children.length === 0) {
1102
1224
  dependencyTree = createDependencyTree(stacks, 0);
1103
1225
  } else {
1104
1226
  dependencyTree = [{
1105
- stack: bootstrap2,
1227
+ stack: bootstrap2.stack,
1106
1228
  level: 0,
1107
1229
  children: createDependencyTree(stacks, 1)
1108
1230
  }];
@@ -1174,7 +1296,7 @@ var footer = () => {
1174
1296
  };
1175
1297
 
1176
1298
  // src/config.ts
1177
- import { join as join5 } from "path";
1299
+ import { join as join6 } from "path";
1178
1300
 
1179
1301
  // src/util/account.ts
1180
1302
  import { STSClient, GetCallerIdentityCommand } from "@aws-sdk/client-sts";
@@ -1193,17 +1315,17 @@ var getCredentials = (profile) => {
1193
1315
  };
1194
1316
 
1195
1317
  // src/schema/app.ts
1196
- import { z as z23 } from "zod";
1318
+ import { z as z25 } from "zod";
1197
1319
 
1198
1320
  // src/schema/stack.ts
1199
- import { z as z20 } from "zod";
1200
- var StackSchema = z20.object({
1321
+ import { z as z22 } from "zod";
1322
+ var StackSchema = z22.object({
1201
1323
  name: ResourceIdSchema,
1202
- depends: z20.array(z20.lazy(() => StackSchema)).optional()
1324
+ depends: z22.array(z22.lazy(() => StackSchema)).optional()
1203
1325
  });
1204
1326
 
1205
1327
  // src/schema/region.ts
1206
- import { z as z21 } from "zod";
1328
+ import { z as z23 } from "zod";
1207
1329
  var US = ["us-east-2", "us-east-1", "us-west-1", "us-west-2"];
1208
1330
  var AF = ["af-south-1"];
1209
1331
  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"];
@@ -1220,35 +1342,35 @@ var regions = [
1220
1342
  ...ME,
1221
1343
  ...SA
1222
1344
  ];
1223
- var RegionSchema = z21.enum(regions);
1345
+ var RegionSchema = z23.enum(regions);
1224
1346
 
1225
1347
  // src/schema/plugin.ts
1226
- import { z as z22 } from "zod";
1227
- var PluginSchema = z22.object({
1228
- name: z22.string(),
1229
- schema: z22.custom().optional(),
1230
- depends: z22.array(z22.lazy(() => PluginSchema)).optional(),
1231
- onBootstrap: z22.function().optional(),
1232
- onStack: z22.function().returns(z22.any()).optional(),
1233
- onApp: z22.function().optional()
1348
+ import { z as z24 } from "zod";
1349
+ var PluginSchema = z24.object({
1350
+ name: z24.string(),
1351
+ schema: z24.custom().optional(),
1352
+ // depends: z.array(z.lazy(() => PluginSchema)).optional(),
1353
+ onBootstrap: z24.function().returns(z24.any()).optional(),
1354
+ onStack: z24.function().returns(z24.any()).optional(),
1355
+ onApp: z24.function().returns(z24.void()).optional()
1234
1356
  // bind: z.function().optional(),
1235
1357
  });
1236
1358
 
1237
1359
  // src/schema/app.ts
1238
- var AppSchema = z23.object({
1360
+ var AppSchema = z25.object({
1239
1361
  name: ResourceIdSchema,
1240
1362
  region: RegionSchema,
1241
- profile: z23.string(),
1242
- stage: z23.string().regex(/[a-z]+/).default("prod"),
1243
- defaults: z23.object({}).default({}),
1244
- stacks: z23.array(StackSchema).min(1),
1245
- plugins: z23.array(PluginSchema).optional()
1363
+ profile: z25.string(),
1364
+ stage: z25.string().regex(/[a-z]+/).default("prod"),
1365
+ defaults: z25.object({}).default({}),
1366
+ stacks: z25.array(StackSchema).min(1),
1367
+ plugins: z25.array(PluginSchema).optional()
1246
1368
  });
1247
1369
 
1248
1370
  // src/util/import.ts
1249
1371
  import { transformFile } from "@swc/core";
1250
- import { dirname, join as join4 } from "path";
1251
- import { lstat, mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
1372
+ import { dirname as dirname2, join as join5 } from "path";
1373
+ import { lstat, mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
1252
1374
  var resolveFileNameExtension = async (path) => {
1253
1375
  const options = [
1254
1376
  "",
@@ -1272,14 +1394,14 @@ var resolveFileNameExtension = async (path) => {
1272
1394
  throw new Error(`Failed to load file: ${path}`);
1273
1395
  };
1274
1396
  var resolveDir = (path) => {
1275
- return dirname(path).replace(rootDir + "/", "");
1397
+ return dirname2(path).replace(rootDir + "/", "");
1276
1398
  };
1277
1399
  var importFile = async (path) => {
1278
1400
  const load = async (file) => {
1279
1401
  let { code: code2 } = await transformFile(file, {
1280
1402
  isModule: true
1281
1403
  });
1282
- const path2 = dirname(file);
1404
+ const path2 = dirname2(file);
1283
1405
  const dir = resolveDir(file);
1284
1406
  code2 = code2.replaceAll("__dirname", `"${dir}"`);
1285
1407
  const matches = code2.match(/import\s*{\s*[a-z0-9\_]+\s*}\s*from\s*('|")(\.[\/a-z0-9\_\-]+)('|");?/ig);
@@ -1288,23 +1410,23 @@ var importFile = async (path) => {
1288
1410
  await Promise.all(matches?.map(async (match) => {
1289
1411
  const parts = /('|")(\.[\/a-z0-9\_\-]+)('|")/ig.exec(match);
1290
1412
  const from = parts[2];
1291
- const file2 = await resolveFileNameExtension(join4(path2, from));
1413
+ const file2 = await resolveFileNameExtension(join5(path2, from));
1292
1414
  const result = await load(file2);
1293
1415
  code2 = code2.replace(match, result);
1294
1416
  }));
1295
1417
  return code2;
1296
1418
  };
1297
1419
  const code = await load(path);
1298
- const outputFile = join4(outDir, "config.js");
1299
- await mkdir2(outDir, { recursive: true });
1300
- await writeFile2(outputFile, code);
1420
+ const outputFile = join5(outDir, "config.js");
1421
+ await mkdir3(outDir, { recursive: true });
1422
+ await writeFile3(outputFile, code);
1301
1423
  return import(outputFile);
1302
1424
  };
1303
1425
 
1304
1426
  // src/config.ts
1305
1427
  var importConfig = async (options) => {
1306
1428
  debug("Import config file");
1307
- const fileName = join5(process.cwd(), options.configFile || "awsless.config.ts");
1429
+ const fileName = join6(process.cwd(), options.configFile || "awsless.config.ts");
1308
1430
  const module = await importFile(fileName);
1309
1431
  const appConfig = typeof module.default === "function" ? await module.default({
1310
1432
  profile: options.profile,
@@ -1518,6 +1640,13 @@ var Interface = class {
1518
1640
  if (this.input.isTTY) {
1519
1641
  this.input.setRawMode(true);
1520
1642
  }
1643
+ this.input.on("keypress", (_, key) => {
1644
+ const action = parseAction(key);
1645
+ if (action === "abort") {
1646
+ this.unref();
1647
+ process.exit(1);
1648
+ }
1649
+ });
1521
1650
  }
1522
1651
  // private subscriber: Actions | undefined
1523
1652
  readline;
@@ -1667,12 +1796,6 @@ var layout = async (cb) => {
1667
1796
  const term = createTerminal();
1668
1797
  term.out.clear();
1669
1798
  term.out.write(logo());
1670
- term.in.captureInput({
1671
- abort: () => {
1672
- term.in.showCursor();
1673
- process.exit(1);
1674
- }
1675
- });
1676
1799
  try {
1677
1800
  const options = program.optsWithGlobals();
1678
1801
  const config2 = await importConfig(options);
@@ -1693,7 +1816,7 @@ var layout = async (cb) => {
1693
1816
  term.in.unref();
1694
1817
  setTimeout(() => {
1695
1818
  process.exit(0);
1696
- }, 50);
1819
+ }, 100);
1697
1820
  }
1698
1821
  };
1699
1822
 
@@ -1724,7 +1847,8 @@ var assetBuilder = (assets) => {
1724
1847
  const groups = new Signal([br()]);
1725
1848
  term.out.write(groups);
1726
1849
  const stackNameSize = Math.max(...Object.keys(assets.list()).map((stack) => stack.length));
1727
- await Promise.all(assets.map(async (stack, assets2) => {
1850
+ const resourceSize = Math.max(...Object.values(assets.list()).map((assets2) => assets2.map((asset) => asset.resource.length)).flat());
1851
+ await Promise.all(assets.map(async (stackName, assets2) => {
1728
1852
  const group = new Signal([]);
1729
1853
  groups.update((groups2) => [...groups2, group]);
1730
1854
  await Promise.all(assets2.map(async (asset) => {
@@ -1733,12 +1857,13 @@ var assetBuilder = (assets) => {
1733
1857
  const line = flexLine(term, [
1734
1858
  icon,
1735
1859
  " ",
1736
- style.label(stack.name),
1737
- " ".repeat(stackNameSize - stack.name.length),
1860
+ style.label(stackName),
1861
+ " ".repeat(stackNameSize - stackName.length),
1738
1862
  " ",
1739
1863
  style.placeholder(symbol.pointerSmall),
1740
1864
  " ",
1741
1865
  style.warning(asset.resource),
1866
+ " ".repeat(resourceSize - asset.resource.length),
1742
1867
  " ",
1743
1868
  style.placeholder(symbol.pointerSmall),
1744
1869
  " ",
@@ -1769,19 +1894,20 @@ var assetBuilder = (assets) => {
1769
1894
  };
1770
1895
 
1771
1896
  // src/util/cleanup.ts
1772
- import { mkdir as mkdir3, rm } from "fs/promises";
1897
+ import { mkdir as mkdir4, rm } from "fs/promises";
1773
1898
  var cleanUp = async () => {
1774
1899
  debug("Clean up assembly & asset files");
1775
1900
  const paths = [
1776
1901
  assemblyDir,
1777
- functionDir
1902
+ assetDir,
1903
+ cacheDir
1778
1904
  ];
1779
1905
  await Promise.all(paths.map((path) => rm(path, {
1780
1906
  recursive: true,
1781
1907
  force: true,
1782
1908
  maxRetries: 2
1783
1909
  })));
1784
- await Promise.all(paths.map((path) => mkdir3(path, {
1910
+ await Promise.all(paths.map((path) => mkdir4(path, {
1785
1911
  recursive: true
1786
1912
  })));
1787
1913
  };
@@ -1905,7 +2031,7 @@ var StackClient = class {
1905
2031
  stack.Outputs?.forEach((output) => {
1906
2032
  outputs[output.OutputKey] = output.OutputValue;
1907
2033
  });
1908
- debug("Status for: ", style.info(name), "is", stack.StackStatus);
2034
+ debug("Status for:", style.info(name), "is", style.attr(stack.StackStatus));
1909
2035
  return {
1910
2036
  status: stack.StackStatus,
1911
2037
  reason: stack.StackStatusReason,
@@ -2171,6 +2297,7 @@ var deploy = (program2) => {
2171
2297
  await cleanUp();
2172
2298
  await write(assetBuilder(assets));
2173
2299
  write(br());
2300
+ write(br());
2174
2301
  const donePublishing = write(loadingDialog("Publishing stack assets to AWS..."));
2175
2302
  await Promise.all(assets.map(async (_, assets2) => {
2176
2303
  await Promise.all(assets2.map(async (asset) => {
@@ -2186,21 +2313,28 @@ var deploy = (program2) => {
2186
2313
  const doneDeploying = write(loadingDialog("Deploying stacks to AWS..."));
2187
2314
  write(br());
2188
2315
  write(stackTree(dependencyTree, statuses));
2316
+ write(br());
2189
2317
  const client = new StackClient(config2);
2190
2318
  const deploymentLine = createDeploymentLine(dependencyTree);
2191
2319
  for (const stacks of deploymentLine) {
2192
- await Promise.allSettled(stacks.map(async (stack) => {
2320
+ const results = await Promise.allSettled(stacks.map(async (stack) => {
2321
+ const signal = statuses[stack.artifactId];
2193
2322
  const stackArtifect = assembly.stacks.find((item) => item.id === stack.artifactId);
2194
- statuses[stack.artifactId].set(style.warning("deploying"));
2323
+ signal.set(style.warning("deploying"));
2195
2324
  try {
2196
2325
  await client.deploy(stackArtifect);
2197
2326
  } catch (error) {
2198
2327
  debugError(error);
2199
- statuses[stack.artifactId].set(style.error("failed"));
2328
+ signal.set(style.error("failed"));
2200
2329
  throw error;
2201
2330
  }
2202
- statuses[stack.artifactId].set(style.success("deployed"));
2331
+ signal.set(style.success("deployed"));
2203
2332
  }));
2333
+ for (const result of results) {
2334
+ if (result.status === "rejected") {
2335
+ throw result.reason;
2336
+ }
2337
+ }
2204
2338
  }
2205
2339
  doneDeploying("Done deploying stacks to AWS");
2206
2340
  });