@awsless/awsless 0.0.34 → 0.0.36

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
@@ -1021,7 +1021,145 @@ var hasOnFailure = (config) => {
1021
1021
  };
1022
1022
 
1023
1023
  // src/plugins/function.ts
1024
+ var import_change_case4 = require("change-case");
1025
+
1026
+ // src/util/path.ts
1027
+ var import_promises2 = require("fs/promises");
1028
+ var import_path2 = require("path");
1029
+ var root = process.cwd();
1030
+ var directories = {
1031
+ root,
1032
+ get output() {
1033
+ return (0, import_path2.join)(this.root, ".awsless");
1034
+ },
1035
+ get cache() {
1036
+ return (0, import_path2.join)(this.output, "cache");
1037
+ },
1038
+ get asset() {
1039
+ return (0, import_path2.join)(this.output, "asset");
1040
+ },
1041
+ get types() {
1042
+ return (0, import_path2.join)(this.output, "types");
1043
+ },
1044
+ get template() {
1045
+ return (0, import_path2.join)(this.output, "template");
1046
+ }
1047
+ };
1048
+ var setRoot = (path = root) => {
1049
+ directories.root = path;
1050
+ };
1051
+ var findRootDir = async (path, configFile, level = 5) => {
1052
+ if (!level) {
1053
+ throw new TypeError("No awsless project found");
1054
+ }
1055
+ const file = (0, import_path2.join)(path, configFile);
1056
+ const exists = await fileExist(file);
1057
+ if (exists) {
1058
+ return path;
1059
+ }
1060
+ return findRootDir((0, import_path2.normalize)((0, import_path2.join)(path, "..")), configFile, level - 1);
1061
+ };
1062
+ var fileExist = async (file) => {
1063
+ try {
1064
+ const stat = await (0, import_promises2.lstat)(file);
1065
+ if (stat.isFile()) {
1066
+ return true;
1067
+ }
1068
+ } catch (error) {
1069
+ }
1070
+ return false;
1071
+ };
1072
+
1073
+ // src/plugins/function.ts
1074
+ var import_path6 = require("path");
1075
+
1076
+ // src/util/type-gen.ts
1077
+ var import_promises3 = require("fs/promises");
1078
+ var import_path4 = require("path");
1024
1079
  var import_change_case3 = require("change-case");
1080
+ var generateResourceTypes = async (config) => {
1081
+ const plugins = [
1082
+ ...defaultPlugins,
1083
+ ...config.plugins || []
1084
+ ];
1085
+ const files = [];
1086
+ for (const plugin of plugins) {
1087
+ const code = plugin.onTypeGen?.({ config });
1088
+ if (code) {
1089
+ const file = (0, import_path4.join)(directories.types, `${plugin.name}.d.ts`);
1090
+ files.push((0, import_path4.relative)(directories.root, file));
1091
+ await (0, import_promises3.mkdir)(directories.types, { recursive: true });
1092
+ await (0, import_promises3.writeFile)(file, code);
1093
+ }
1094
+ }
1095
+ if (files.length) {
1096
+ const code = files.map((file) => `/// <reference path='${file}' />`).join("\n");
1097
+ await (0, import_promises3.writeFile)((0, import_path4.join)(directories.root, `awsless.d.ts`), code);
1098
+ }
1099
+ };
1100
+ var TypeGen = class {
1101
+ constructor(module2, interfaceName) {
1102
+ this.module = module2;
1103
+ this.interfaceName = interfaceName;
1104
+ }
1105
+ codes = /* @__PURE__ */ new Set();
1106
+ types = /* @__PURE__ */ new Map();
1107
+ imports = /* @__PURE__ */ new Map();
1108
+ addImport(varName, path) {
1109
+ this.imports.set(varName, path);
1110
+ return this;
1111
+ }
1112
+ addCode(code) {
1113
+ this.codes.add(code);
1114
+ return this;
1115
+ }
1116
+ addType(name, type) {
1117
+ if (type) {
1118
+ this.types.set(name, type);
1119
+ }
1120
+ return this;
1121
+ }
1122
+ toString() {
1123
+ if (this.types.size === 0) {
1124
+ return;
1125
+ }
1126
+ const imports = Array.from(this.imports.entries()).map(([varName, path]) => {
1127
+ return `import ${(0, import_change_case3.camelCase)(varName)} from '${path}'`;
1128
+ }).join("\n");
1129
+ return [
1130
+ imports,
1131
+ ...Array.from(this.codes),
1132
+ `declare module '${this.module}' {`,
1133
+ ` interface ${this.interfaceName} {`,
1134
+ ...Array.from(this.types.entries()).map(([propName, type]) => {
1135
+ return ` readonly ${(0, import_change_case3.camelCase)(propName)}: ${type}`;
1136
+ }),
1137
+ ` }`,
1138
+ `}`
1139
+ ].join("\n");
1140
+ }
1141
+ };
1142
+ var TypeObject = class {
1143
+ types = /* @__PURE__ */ new Map();
1144
+ addType(name, type) {
1145
+ this.types.set(name, type);
1146
+ return this;
1147
+ }
1148
+ toString() {
1149
+ if (!this.types.size) {
1150
+ return "";
1151
+ }
1152
+ return [
1153
+ "{",
1154
+ ...Array.from(this.types.entries()).map(([propName, type]) => {
1155
+ return ` readonly ${(0, import_change_case3.camelCase)(propName)}: ${type}`;
1156
+ }),
1157
+ " }"
1158
+ ].join("\n");
1159
+ }
1160
+ };
1161
+
1162
+ // src/plugins/function.ts
1025
1163
  var MemorySizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(128)), "Minimum memory size is 128 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum memory size is 10 GB");
1026
1164
  var TimeoutSchema = DurationSchema.refine(durationMin(Duration.seconds(10)), "Minimum timeout duration is 10 seconds").refine(durationMax(Duration.minutes(15)), "Maximum timeout duration is 15 minutes");
1027
1165
  var EphemeralStorageSizeSchema = SizeSchema.refine(sizeMin(Size.megaBytes(512)), "Minimum ephemeral storage size is 512 MB").refine(sizeMax(Size.gigaBytes(10)), "Minimum ephemeral storage size is 10 GB");
@@ -1156,48 +1294,33 @@ var schema = import_zod6.z.object({
1156
1294
  ).optional()
1157
1295
  }).array()
1158
1296
  });
1297
+ var typeGenCode = `
1298
+ import { InvokeOptions } from '@awsless/lambda'
1299
+
1300
+ type Invoke<Name extends string, Func extends (...args: any[]) => any> = {
1301
+ name: Name
1302
+ invoke: (event: Parameters<Func>[0], options?: Omit<InvokeOptions, 'name' | 'payload'>) => ReturnType<Func>
1303
+ async: (event: Parameters<Func>[0], options?: Omit<InvokeOptions, 'name' | 'payload' | 'type'>) => ReturnType<Func>
1304
+ }`;
1159
1305
  var functionPlugin = definePlugin({
1160
1306
  name: "function",
1161
1307
  schema,
1162
1308
  onTypeGen({ config }) {
1163
- const imports = [];
1164
- const props = [];
1309
+ const types2 = new TypeGen("@awsless/awsless", "FunctionResources");
1310
+ types2.addCode(typeGenCode);
1165
1311
  for (const stack of config.stacks) {
1166
- const functions = [];
1312
+ const list3 = new TypeObject();
1167
1313
  for (const [name, fileOrProps] of Object.entries(stack.functions || {})) {
1168
- const varName = (0, import_change_case3.camelCase)(`${stack.name}-${name}`);
1314
+ const varName = (0, import_change_case4.camelCase)(`${stack.name}-${name}`);
1315
+ const funcName = formatName(`${config.name}-${stack.name}-${name}`);
1169
1316
  const file = typeof fileOrProps === "string" ? fileOrProps : fileOrProps.file;
1170
- imports.push(`import ${varName} from '${file}'`);
1171
- functions.push(` readonly ${(0, import_change_case3.camelCase)(name)}: Invoke<typeof ${varName}>`);
1317
+ const relFile = (0, import_path6.relative)(directories.types, file);
1318
+ types2.addImport(varName, relFile);
1319
+ list3.addType(name, `Invoke<'${funcName}', typeof ${varName}>`);
1172
1320
  }
1173
- if (functions.length > 0) {
1174
- props.push(` readonly ${(0, import_change_case3.camelCase)(stack.name)}: {
1175
- ${functions.join("\n")}
1176
- }`);
1177
- }
1178
- }
1179
- if (imports.length === 0) {
1180
- return;
1321
+ types2.addType(stack.name, list3.toString());
1181
1322
  }
1182
- return (
1183
- /* TS */
1184
- `
1185
- ${imports.join("\n")}
1186
-
1187
- import { InvokeOptions } from '@awsless/lambda'
1188
-
1189
- type Options = Omit<InvokeOptions, 'name' | 'payload'>
1190
-
1191
- type Invoke<Func extends (...args: any[]) => any> = {
1192
- (event: Parameters<Func>[0], options?: Options): ReturnType<Func>
1193
- }
1194
-
1195
- declare module '@awsless/awsless' {
1196
- interface FunctionResources {
1197
- ${props.join("\n")}
1198
- }
1199
- }`
1200
- );
1323
+ return types2.toString();
1201
1324
  },
1202
1325
  onStack(ctx) {
1203
1326
  const { config, stack } = ctx;
@@ -1428,7 +1551,7 @@ var Queue = class extends Resource {
1428
1551
  };
1429
1552
 
1430
1553
  // src/formation/resource/lambda/event-source-mapping.ts
1431
- var import_change_case4 = require("change-case");
1554
+ var import_change_case5 = require("change-case");
1432
1555
  var EventSourceMapping = class extends Resource {
1433
1556
  constructor(logicalId, props) {
1434
1557
  super("AWS::Lambda::EventSourceMapping", logicalId);
@@ -1450,7 +1573,7 @@ var EventSourceMapping = class extends Resource {
1450
1573
  ...this.attr("ParallelizationFactor", this.props.parallelizationFactor),
1451
1574
  ...this.attr("TumblingWindowInSeconds", this.props.tumblingWindow?.toSeconds()),
1452
1575
  ...this.attr("BisectBatchOnFunctionError", this.props.bisectBatchOnError),
1453
- ...this.attr("StartingPosition", this.props.startingPosition && (0, import_change_case4.constantCase)(this.props.startingPosition)),
1576
+ ...this.attr("StartingPosition", this.props.startingPosition && (0, import_change_case5.constantCase)(this.props.startingPosition)),
1454
1577
  ...this.attr("StartingPositionTimestamp", this.props.startingPositionTimestamp),
1455
1578
  ...this.props.maxConcurrency ? {
1456
1579
  ScalingConfig: {
@@ -1598,6 +1721,18 @@ var queuePlugin = definePlugin({
1598
1721
  ).optional()
1599
1722
  }).array()
1600
1723
  }),
1724
+ onTypeGen({ config }) {
1725
+ const types2 = new TypeGen("@awsless/awsless", "QueueResources");
1726
+ for (const stack of config.stacks) {
1727
+ const list3 = new TypeObject();
1728
+ for (const name of Object.keys(stack.queues || {})) {
1729
+ const queueName = formatName(`${config.name}-${stack.name}-${name}`);
1730
+ list3.addType(name, `{ name: '${queueName}' }`);
1731
+ }
1732
+ types2.addType(stack.name, list3.toString());
1733
+ }
1734
+ return types2.toString();
1735
+ },
1601
1736
  onStack(ctx) {
1602
1737
  const { stack, config, stackConfig, bind } = ctx;
1603
1738
  for (const [id, functionOrProps] of Object.entries(stackConfig.queues || {})) {
@@ -1626,7 +1761,7 @@ var queuePlugin = definePlugin({
1626
1761
  var import_zod9 = require("zod");
1627
1762
 
1628
1763
  // src/formation/resource/dynamodb/table.ts
1629
- var import_change_case5 = require("change-case");
1764
+ var import_change_case6 = require("change-case");
1630
1765
  var Table = class extends Resource {
1631
1766
  constructor(logicalId, props) {
1632
1767
  super("AWS::DynamoDB::Table", logicalId);
@@ -1699,7 +1834,7 @@ var Table = class extends Resource {
1699
1834
  return {
1700
1835
  TableName: this.name,
1701
1836
  BillingMode: "PAY_PER_REQUEST",
1702
- TableClass: (0, import_change_case5.constantCase)(this.props.class || "standard"),
1837
+ TableClass: (0, import_change_case6.constantCase)(this.props.class || "standard"),
1703
1838
  PointInTimeRecoverySpecification: {
1704
1839
  PointInTimeRecoveryEnabled: this.props.pointInTimeRecovery || false
1705
1840
  },
@@ -1710,7 +1845,7 @@ var Table = class extends Resource {
1710
1845
  AttributeDefinitions: this.attributeDefinitions(),
1711
1846
  ...this.props.stream ? {
1712
1847
  StreamSpecification: {
1713
- StreamViewType: (0, import_change_case5.constantCase)(this.props.stream)
1848
+ StreamViewType: (0, import_change_case6.constantCase)(this.props.stream)
1714
1849
  }
1715
1850
  } : {},
1716
1851
  ...this.props.timeToLiveAttribute ? {
@@ -1727,7 +1862,7 @@ var Table = class extends Resource {
1727
1862
  ...props.sort ? [{ KeyType: "RANGE", AttributeName: props.sort }] : []
1728
1863
  ],
1729
1864
  Projection: {
1730
- ProjectionType: (0, import_change_case5.constantCase)(props.projection || "all")
1865
+ ProjectionType: (0, import_change_case6.constantCase)(props.projection || "all")
1731
1866
  }
1732
1867
  }))
1733
1868
  } : {}
@@ -1871,6 +2006,18 @@ var tablePlugin = definePlugin({
1871
2006
  ).optional()
1872
2007
  }).array()
1873
2008
  }),
2009
+ onTypeGen({ config }) {
2010
+ const types2 = new TypeGen("@awsless/awsless", "TableResources");
2011
+ for (const stack of config.stacks) {
2012
+ const list3 = new TypeObject();
2013
+ for (const name of Object.keys(stack.tables || {})) {
2014
+ const tableName = formatName(`${config.name}-${stack.name}-${name}`);
2015
+ list3.addType(name, `{ name: '${tableName}' }`);
2016
+ }
2017
+ types2.addType(stack.name, list3.toString());
2018
+ }
2019
+ return types2.toString();
2020
+ },
1874
2021
  onStack(ctx) {
1875
2022
  const { config, stack, stackConfig, bind } = ctx;
1876
2023
  for (const [id, props] of Object.entries(stackConfig.tables || {})) {
@@ -1900,7 +2047,7 @@ var tablePlugin = definePlugin({
1900
2047
  var import_zod10 = require("zod");
1901
2048
 
1902
2049
  // src/formation/resource/s3/bucket.ts
1903
- var import_change_case6 = require("change-case");
2050
+ var import_change_case7 = require("change-case");
1904
2051
  var Bucket = class extends Resource {
1905
2052
  constructor(logicalId, props = {}) {
1906
2053
  super("AWS::S3::Bucket", logicalId);
@@ -1935,7 +2082,7 @@ var Bucket = class extends Resource {
1935
2082
  properties() {
1936
2083
  return {
1937
2084
  BucketName: this.name,
1938
- AccessControl: (0, import_change_case6.pascalCase)(this.props.accessControl ?? "private"),
2085
+ AccessControl: (0, import_change_case7.pascalCase)(this.props.accessControl ?? "private"),
1939
2086
  ...this.props.versioned ? {
1940
2087
  VersioningConfiguration: {
1941
2088
  Status: "Enabled"
@@ -2057,6 +2204,16 @@ var topicPlugin = definePlugin({
2057
2204
  topics: import_zod11.z.record(ResourceIdSchema, FunctionSchema).optional()
2058
2205
  }).array()
2059
2206
  }),
2207
+ onTypeGen({ config }) {
2208
+ const gen = new TypeGen("@awsless/awsless", "TopicResources");
2209
+ for (const stack of config.stacks) {
2210
+ for (const topic of Object.keys(stack.topics || {})) {
2211
+ const name = formatName(`${config.name}-${topic}`);
2212
+ gen.addType(topic, `{ name: '${name}' }`);
2213
+ }
2214
+ }
2215
+ return gen.toString();
2216
+ },
2060
2217
  onApp({ config, bootstrap: bootstrap2, bind }) {
2061
2218
  const allTopicNames = config.stacks.map((stack) => {
2062
2219
  return Object.keys(stack.topics || {});
@@ -2116,12 +2273,12 @@ var extendPlugin = definePlugin({
2116
2273
  var import_zod13 = require("zod");
2117
2274
 
2118
2275
  // src/formation/resource/iot/topic-rule.ts
2119
- var import_change_case7 = require("change-case");
2276
+ var import_change_case8 = require("change-case");
2120
2277
  var TopicRule = class extends Resource {
2121
2278
  constructor(logicalId, props) {
2122
2279
  super("AWS::IoT::TopicRule", logicalId);
2123
2280
  this.props = props;
2124
- this.name = (0, import_change_case7.snakeCase)(this.props.name || logicalId);
2281
+ this.name = (0, import_change_case8.snakeCase)(this.props.name || logicalId);
2125
2282
  }
2126
2283
  name;
2127
2284
  get arn() {
@@ -2221,10 +2378,10 @@ var toArray = (value) => {
2221
2378
  };
2222
2379
 
2223
2380
  // src/plugins/graphql.ts
2224
- var import_change_case11 = require("change-case");
2381
+ var import_change_case12 = require("change-case");
2225
2382
 
2226
2383
  // src/formation/resource/appsync/graphql-api.ts
2227
- var import_change_case8 = require("change-case");
2384
+ var import_change_case9 = require("change-case");
2228
2385
  var GraphQLApi = class extends Resource {
2229
2386
  constructor(logicalId, props) {
2230
2387
  super("AWS::AppSync::GraphQLApi", logicalId);
@@ -2256,7 +2413,7 @@ var GraphQLApi = class extends Resource {
2256
2413
  properties() {
2257
2414
  return {
2258
2415
  Name: this.name,
2259
- AuthenticationType: (0, import_change_case8.constantCase)(this.props.authenticationType || "api-key"),
2416
+ AuthenticationType: (0, import_change_case9.constantCase)(this.props.authenticationType || "api-key"),
2260
2417
  AdditionalAuthenticationProviders: this.lambdaAuthProviders.map((provider) => ({
2261
2418
  AuthenticationType: "AWS_LAMBDA",
2262
2419
  LambdaAuthorizerConfig: {
@@ -2297,7 +2454,7 @@ var RecordSet = class extends Resource {
2297
2454
 
2298
2455
  // src/formation/resource/appsync/graphql-schema.ts
2299
2456
  var import_graphql = require("graphql");
2300
- var import_promises2 = require("fs/promises");
2457
+ var import_promises4 = require("fs/promises");
2301
2458
  var import_merge = require("@graphql-tools/merge");
2302
2459
  var GraphQLSchema = class extends Resource {
2303
2460
  constructor(logicalId, props) {
@@ -2322,7 +2479,7 @@ var Definition = class extends Asset {
2322
2479
  async build({ write }) {
2323
2480
  const files = [this.files].flat();
2324
2481
  const schemas = await Promise.all(files.map((file) => {
2325
- return (0, import_promises2.readFile)(file, "utf8");
2482
+ return (0, import_promises4.readFile)(file, "utf8");
2326
2483
  }));
2327
2484
  const defs = (0, import_merge.mergeTypeDefs)(schemas);
2328
2485
  const schema2 = (0, import_graphql.print)(defs);
@@ -2342,7 +2499,7 @@ var Definition = class extends Asset {
2342
2499
  };
2343
2500
 
2344
2501
  // src/formation/resource/appsync/code.ts
2345
- var import_promises3 = require("fs/promises");
2502
+ var import_promises5 = require("fs/promises");
2346
2503
  var Code2 = class {
2347
2504
  static fromFile(id, file) {
2348
2505
  return new FileCode2(id, file);
@@ -2369,7 +2526,7 @@ var FileCode2 = class extends Asset {
2369
2526
  }
2370
2527
  code;
2371
2528
  async build() {
2372
- const code = await (0, import_promises3.readFile)(this.file);
2529
+ const code = await (0, import_promises5.readFile)(this.file);
2373
2530
  this.code = code.toString("utf8");
2374
2531
  return {
2375
2532
  size: formatByteSize(code.byteLength)
@@ -2383,12 +2540,12 @@ var FileCode2 = class extends Asset {
2383
2540
  };
2384
2541
 
2385
2542
  // src/formation/resource/appsync/data-source.ts
2386
- var import_change_case9 = require("change-case");
2543
+ var import_change_case10 = require("change-case");
2387
2544
  var DataSource = class extends Resource {
2388
2545
  constructor(logicalId, props) {
2389
2546
  super("AWS::AppSync::DataSource", logicalId);
2390
2547
  this.props = props;
2391
- this.name = (0, import_change_case9.snakeCase)(this.props.name || logicalId);
2548
+ this.name = (0, import_change_case10.snakeCase)(this.props.name || logicalId);
2392
2549
  }
2393
2550
  static fromLambda(logicalId, apiId, props) {
2394
2551
  return new DataSource(logicalId, {
@@ -2428,14 +2585,14 @@ var DataSource = class extends Resource {
2428
2585
  };
2429
2586
 
2430
2587
  // src/formation/resource/appsync/function-configuration.ts
2431
- var import_change_case10 = require("change-case");
2588
+ var import_change_case11 = require("change-case");
2432
2589
  var FunctionConfiguration = class extends Resource {
2433
2590
  constructor(logicalId, props) {
2434
2591
  super("AWS::AppSync::FunctionConfiguration", logicalId, [
2435
2592
  props.code
2436
2593
  ]);
2437
2594
  this.props = props;
2438
- this.name = (0, import_change_case10.snakeCase)(this.props.name || logicalId);
2595
+ this.name = (0, import_change_case11.snakeCase)(this.props.name || logicalId);
2439
2596
  }
2440
2597
  name;
2441
2598
  get id() {
@@ -2654,7 +2811,7 @@ var graphqlPlugin = definePlugin({
2654
2811
  const apiId = bootstrap2.import(`graphql-${id}`);
2655
2812
  for (const [typeAndField, functionProps] of Object.entries(props.resolvers || {})) {
2656
2813
  const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
2657
- const entryId = (0, import_change_case11.paramCase)(`${id}-${typeName}-${fieldName}`);
2814
+ const entryId = (0, import_change_case12.paramCase)(`${id}-${typeName}-${fieldName}`);
2658
2815
  const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
2659
2816
  const source = new AppsyncEventSource(entryId, lambda, {
2660
2817
  apiId,
@@ -3338,7 +3495,7 @@ var LoadBalancer = class extends Resource {
3338
3495
  };
3339
3496
 
3340
3497
  // src/formation/resource/elb/listener.ts
3341
- var import_change_case12 = require("change-case");
3498
+ var import_change_case13 = require("change-case");
3342
3499
  var Listener = class extends Resource {
3343
3500
  constructor(logicalId, props) {
3344
3501
  super("AWS::ElasticLoadBalancingV2::Listener", logicalId);
@@ -3354,7 +3511,7 @@ var Listener = class extends Resource {
3354
3511
  return {
3355
3512
  LoadBalancerArn: this.props.loadBalancerArn,
3356
3513
  Port: this.props.port,
3357
- Protocol: (0, import_change_case12.constantCase)(this.props.protocol),
3514
+ Protocol: (0, import_change_case13.constantCase)(this.props.protocol),
3358
3515
  Certificates: this.props.certificates.map((arn) => ({
3359
3516
  CertificateArn: arn
3360
3517
  })),
@@ -4111,7 +4268,7 @@ var toApp = async (config, filters) => {
4111
4268
  };
4112
4269
 
4113
4270
  // src/config.ts
4114
- var import_path5 = require("path");
4271
+ var import_path9 = require("path");
4115
4272
 
4116
4273
  // src/util/account.ts
4117
4274
  var import_client_sts = require("@aws-sdk/client-sts");
@@ -4198,57 +4355,9 @@ var AppSchema = import_zod23.z.object({
4198
4355
  var import_rollup3 = require("rollup");
4199
4356
  var import_rollup_plugin_swc32 = require("rollup-plugin-swc3");
4200
4357
  var import_rollup_plugin_replace = __toESM(require("rollup-plugin-replace"), 1);
4201
- var import_path3 = require("path");
4202
- var import_promises5 = require("fs/promises");
4203
-
4204
- // src/util/path.ts
4205
- var import_promises4 = require("fs/promises");
4206
- var import_path2 = require("path");
4207
- var root = process.cwd();
4208
- var directories = {
4209
- root,
4210
- get output() {
4211
- return (0, import_path2.join)(this.root, ".awsless");
4212
- },
4213
- get cache() {
4214
- return (0, import_path2.join)(this.output, "cache");
4215
- },
4216
- get asset() {
4217
- return (0, import_path2.join)(this.output, "asset");
4218
- },
4219
- get types() {
4220
- return (0, import_path2.join)(this.output, "types");
4221
- },
4222
- get template() {
4223
- return (0, import_path2.join)(this.output, "template");
4224
- }
4225
- };
4226
- var setRoot = (path = root) => {
4227
- directories.root = path;
4228
- };
4229
- var findRootDir = async (path, configFile, level = 5) => {
4230
- if (!level) {
4231
- throw new TypeError("No awsless project found");
4232
- }
4233
- const file = (0, import_path2.join)(path, configFile);
4234
- const exists = await fileExist(file);
4235
- if (exists) {
4236
- return path;
4237
- }
4238
- return findRootDir((0, import_path2.normalize)((0, import_path2.join)(path, "..")), configFile, level - 1);
4239
- };
4240
- var fileExist = async (file) => {
4241
- try {
4242
- const stat = await (0, import_promises4.lstat)(file);
4243
- if (stat.isFile()) {
4244
- return true;
4245
- }
4246
- } catch (error) {
4247
- }
4248
- return false;
4249
- };
4250
-
4251
- // src/util/import.ts
4358
+ var import_event_iterator = require("event-iterator");
4359
+ var import_path7 = require("path");
4360
+ var import_promises6 = require("fs/promises");
4252
4361
  var importFile = async (path) => {
4253
4362
  const bundle = await (0, import_rollup3.rollup)({
4254
4363
  input: path,
@@ -4257,28 +4366,83 @@ var importFile = async (path) => {
4257
4366
  },
4258
4367
  plugins: [
4259
4368
  (0, import_rollup_plugin_replace.default)({
4260
- __dirname: (id) => `'${(0, import_path3.dirname)(id)}'`
4369
+ __dirname: (id) => `'${(0, import_path7.dirname)(id)}'`
4261
4370
  }),
4262
4371
  (0, import_rollup_plugin_swc32.swc)({
4263
4372
  minify: false,
4264
4373
  jsc: {
4265
- baseUrl: (0, import_path3.dirname)(path)
4374
+ baseUrl: (0, import_path7.dirname)(path)
4266
4375
  }
4267
4376
  })
4268
4377
  ]
4269
4378
  });
4270
- const outputFile = (0, import_path3.join)(directories.cache, "config.js");
4379
+ const outputFile = (0, import_path7.join)(directories.cache, "config.js");
4271
4380
  const result = await bundle.generate({
4272
4381
  format: "esm",
4273
4382
  exports: "default"
4274
4383
  });
4275
4384
  const output = result.output[0];
4276
4385
  const code = output.code;
4277
- await (0, import_promises5.mkdir)(directories.cache, { recursive: true });
4278
- await (0, import_promises5.writeFile)(outputFile, code);
4386
+ await (0, import_promises6.mkdir)(directories.cache, { recursive: true });
4387
+ await (0, import_promises6.writeFile)(outputFile, code);
4279
4388
  debug("Save config file:", style.info(outputFile));
4280
4389
  return import(outputFile);
4281
4390
  };
4391
+ var watchFile = (path) => {
4392
+ return new import_event_iterator.EventIterator((queue2) => {
4393
+ const watcher = (0, import_rollup3.watch)({
4394
+ watch: {
4395
+ skipWrite: true
4396
+ },
4397
+ input: path,
4398
+ onwarn: (error) => {
4399
+ debugError(error.message);
4400
+ },
4401
+ plugins: [
4402
+ (0, import_rollup_plugin_replace.default)({
4403
+ __dirname: (id) => `'${(0, import_path7.dirname)(id)}'`
4404
+ }),
4405
+ (0, import_rollup_plugin_swc32.swc)({
4406
+ minify: false,
4407
+ jsc: {
4408
+ baseUrl: (0, import_path7.dirname)(path)
4409
+ }
4410
+ })
4411
+ ]
4412
+ });
4413
+ let resume;
4414
+ queue2.on("lowWater", () => {
4415
+ resume?.(true);
4416
+ });
4417
+ watcher.on("close", queue2.stop);
4418
+ watcher.on("event", async (event) => {
4419
+ if (event.code === "ERROR") {
4420
+ queue2.fail(new Error(event.error.message));
4421
+ }
4422
+ if (event.code === "BUNDLE_END") {
4423
+ const result = await event.result.generate({
4424
+ format: "esm",
4425
+ exports: "default"
4426
+ });
4427
+ event.result.close();
4428
+ const output = result.output[0];
4429
+ const code = output.code;
4430
+ const outputFile = (0, import_path7.join)(directories.cache, "config.js");
4431
+ await (0, import_promises6.mkdir)(directories.cache, { recursive: true });
4432
+ await (0, import_promises6.writeFile)(outputFile, code);
4433
+ debug("Save config file:", style.info(outputFile));
4434
+ const config = await import(`${outputFile}?${Date.now()}`);
4435
+ queue2.push(config);
4436
+ }
4437
+ });
4438
+ return () => {
4439
+ watcher.close();
4440
+ };
4441
+ }, {
4442
+ highWaterMark: 1,
4443
+ lowWaterMark: 0
4444
+ });
4445
+ };
4282
4446
 
4283
4447
  // src/config.ts
4284
4448
  var importConfig = async (options) => {
@@ -4288,7 +4452,7 @@ var importConfig = async (options) => {
4288
4452
  setRoot(root2);
4289
4453
  debug("CWD:", style.info(root2));
4290
4454
  debug("Import config file");
4291
- const fileName = (0, import_path5.join)(root2, configFile);
4455
+ const fileName = (0, import_path9.join)(root2, configFile);
4292
4456
  const module2 = await importFile(fileName);
4293
4457
  const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
4294
4458
  debug("Validate config file");
@@ -4314,6 +4478,40 @@ var importConfig = async (options) => {
4314
4478
  credentials
4315
4479
  };
4316
4480
  };
4481
+ var watchConfig = async function* (options) {
4482
+ debug("Find the root directory");
4483
+ const configFile = options.configFile || "awsless.config.ts";
4484
+ const root2 = await findRootDir(process.cwd(), configFile);
4485
+ setRoot(root2);
4486
+ debug("CWD:", style.info(root2));
4487
+ debug("Import config file");
4488
+ const fileName = (0, import_path9.join)(root2, configFile);
4489
+ for await (const module2 of watchFile(fileName)) {
4490
+ const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
4491
+ debug("Validate config file");
4492
+ const plugins = [
4493
+ ...defaultPlugins,
4494
+ ...appConfig.plugins || []
4495
+ ];
4496
+ let schema2 = AppSchema;
4497
+ for (const plugin of plugins) {
4498
+ if (plugin.schema) {
4499
+ schema2 = schema2.and(plugin.schema);
4500
+ }
4501
+ }
4502
+ const config = await schema2.parseAsync(appConfig);
4503
+ debug("Load credentials", style.info(config.profile));
4504
+ const credentials = getCredentials(config.profile);
4505
+ debug("Load AWS account ID");
4506
+ const account = await getAccountId(credentials, config.region);
4507
+ debug("Account ID:", style.info(account));
4508
+ yield {
4509
+ ...config,
4510
+ account,
4511
+ credentials
4512
+ };
4513
+ }
4514
+ };
4317
4515
 
4318
4516
  // src/cli/ui/layout/basic.ts
4319
4517
  var br = () => {
@@ -4789,7 +4987,7 @@ var layout = async (cb) => {
4789
4987
  };
4790
4988
 
4791
4989
  // src/cli/ui/complex/builder.ts
4792
- var import_promises6 = require("fs/promises");
4990
+ var import_promises7 = require("fs/promises");
4793
4991
 
4794
4992
  // src/cli/ui/layout/flex-line.ts
4795
4993
  var stripEscapeCode = (str) => {
@@ -4812,7 +5010,7 @@ var flexLine = (term, left, right, reserveSpace = 0) => {
4812
5010
  };
4813
5011
 
4814
5012
  // src/cli/ui/complex/builder.ts
4815
- var import_path8 = require("path");
5013
+ var import_path12 = require("path");
4816
5014
  var assetBuilder = (app) => {
4817
5015
  return async (term) => {
4818
5016
  const assets = [];
@@ -4875,10 +5073,10 @@ var assetBuilder = (app) => {
4875
5073
  try {
4876
5074
  const data = await asset.build({
4877
5075
  async write(file, data2) {
4878
- const fullpath = (0, import_path8.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
4879
- const basepath = (0, import_path8.dirname)(fullpath);
4880
- await (0, import_promises6.mkdir)(basepath, { recursive: true });
4881
- await (0, import_promises6.writeFile)(fullpath, data2);
5076
+ const fullpath = (0, import_path12.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5077
+ const basepath = (0, import_path12.dirname)(fullpath);
5078
+ await (0, import_promises7.mkdir)(basepath, { recursive: true });
5079
+ await (0, import_promises7.writeFile)(fullpath, data2);
4882
5080
  }
4883
5081
  });
4884
5082
  details.set({
@@ -4902,7 +5100,7 @@ var assetBuilder = (app) => {
4902
5100
  };
4903
5101
 
4904
5102
  // src/util/cleanup.ts
4905
- var import_promises7 = require("fs/promises");
5103
+ var import_promises8 = require("fs/promises");
4906
5104
  var cleanUp = async () => {
4907
5105
  debug("Clean up template, cache, and asset files");
4908
5106
  const paths = [
@@ -4911,50 +5109,33 @@ var cleanUp = async () => {
4911
5109
  directories.types,
4912
5110
  directories.template
4913
5111
  ];
4914
- await Promise.all(paths.map((path) => (0, import_promises7.rm)(path, {
5112
+ await Promise.all(paths.map((path) => (0, import_promises8.rm)(path, {
4915
5113
  recursive: true,
4916
5114
  force: true,
4917
5115
  maxRetries: 2
4918
5116
  })));
4919
- await Promise.all(paths.map((path) => (0, import_promises7.mkdir)(path, {
5117
+ await Promise.all(paths.map((path) => (0, import_promises8.mkdir)(path, {
4920
5118
  recursive: true
4921
5119
  })));
4922
5120
  };
4923
5121
 
4924
5122
  // src/cli/ui/complex/template.ts
4925
- var import_promises8 = require("fs/promises");
4926
- var import_path11 = require("path");
5123
+ var import_promises9 = require("fs/promises");
5124
+ var import_path15 = require("path");
4927
5125
  var templateBuilder = (app) => {
4928
5126
  return async (term) => {
4929
5127
  const done = term.out.write(loadingDialog("Building stack templates..."));
4930
5128
  await Promise.all(app.stacks.map(async (stack) => {
4931
5129
  const template = stack.toString(true);
4932
- const path = (0, import_path11.join)(directories.template, app.name);
4933
- const file = (0, import_path11.join)(path, `${stack.name}.json`);
4934
- await (0, import_promises8.mkdir)(path, { recursive: true });
4935
- await (0, import_promises8.writeFile)(file, template);
5130
+ const path = (0, import_path15.join)(directories.template, app.name);
5131
+ const file = (0, import_path15.join)(path, `${stack.name}.json`);
5132
+ await (0, import_promises9.mkdir)(path, { recursive: true });
5133
+ await (0, import_promises9.writeFile)(file, template);
4936
5134
  }));
4937
5135
  done("Done building stack templates");
4938
5136
  };
4939
5137
  };
4940
5138
 
4941
- // src/util/type-gen.ts
4942
- var import_promises9 = require("fs/promises");
4943
- var import_path13 = require("path");
4944
- var generateResourceTypes = async (config) => {
4945
- const plugins = [
4946
- ...defaultPlugins,
4947
- ...config.plugins || []
4948
- ];
4949
- for (const plugin of plugins) {
4950
- const code = plugin.onTypeGen?.({ config });
4951
- if (code) {
4952
- await (0, import_promises9.mkdir)(directories.types, { recursive: true });
4953
- await (0, import_promises9.writeFile)((0, import_path13.join)(directories.types, `${plugin.name}.d.ts`), code);
4954
- }
4955
- }
4956
- };
4957
-
4958
5139
  // src/cli/ui/complex/types.ts
4959
5140
  var typesGenerator = (config) => {
4960
5141
  return async (term) => {
@@ -5007,7 +5188,7 @@ var shouldDeployBootstrap = async (client, stack) => {
5007
5188
  // src/formation/client.ts
5008
5189
  var import_client_cloudformation = require("@aws-sdk/client-cloudformation");
5009
5190
  var import_client_s3 = require("@aws-sdk/client-s3");
5010
- var import_change_case13 = require("change-case");
5191
+ var import_change_case14 = require("change-case");
5011
5192
  var StackClient = class {
5012
5193
  constructor(app, account, region, credentials) {
5013
5194
  this.app = app;
@@ -5040,7 +5221,7 @@ var StackClient = class {
5040
5221
  };
5041
5222
  }
5042
5223
  stackName(stackName) {
5043
- return (0, import_change_case13.paramCase)(`${this.app.name}-${stackName}`);
5224
+ return (0, import_change_case14.paramCase)(`${this.app.name}-${stackName}`);
5044
5225
  }
5045
5226
  tags(stack) {
5046
5227
  const tags = [];
@@ -5468,7 +5649,7 @@ var status = (program2) => {
5468
5649
 
5469
5650
  // src/cli/ui/complex/publisher.ts
5470
5651
  var import_promises10 = require("fs/promises");
5471
- var import_path15 = require("path");
5652
+ var import_path17 = require("path");
5472
5653
  var import_client_s32 = require("@aws-sdk/client-s3");
5473
5654
  var assetPublisher = (config, app) => {
5474
5655
  const client = new import_client_s32.S3Client({
@@ -5481,7 +5662,7 @@ var assetPublisher = (config, app) => {
5481
5662
  await Promise.all([...stack.assets].map(async (asset) => {
5482
5663
  await asset.publish?.({
5483
5664
  async read(file) {
5484
- const path = (0, import_path15.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5665
+ const path = (0, import_path17.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5485
5666
  const data = await (0, import_promises10.readFile)(path);
5486
5667
  return data;
5487
5668
  },
@@ -5746,6 +5927,19 @@ var types = (program2) => {
5746
5927
  });
5747
5928
  };
5748
5929
 
5930
+ // src/cli/command/dev.ts
5931
+ var dev = (program2) => {
5932
+ program2.command("dev").description("Start the development service").action(async () => {
5933
+ await layout(async (_, write) => {
5934
+ const options = program2.optsWithGlobals();
5935
+ for await (const config of watchConfig(options)) {
5936
+ await cleanUp();
5937
+ await write(typesGenerator(config));
5938
+ }
5939
+ });
5940
+ });
5941
+ };
5942
+
5749
5943
  // src/cli/program.ts
5750
5944
  var program = new import_commander.Command();
5751
5945
  program.name(logo().join("").replace(/\s+/, ""));
@@ -5767,6 +5961,7 @@ var commands2 = [
5767
5961
  types,
5768
5962
  build,
5769
5963
  deploy,
5964
+ dev,
5770
5965
  secrets,
5771
5966
  test
5772
5967
  // diff,