@awsless/awsless 0.0.35 → 0.0.37

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,7 @@ var hasOnFailure = (config) => {
1021
1021
  };
1022
1022
 
1023
1023
  // src/plugins/function.ts
1024
- var import_change_case3 = require("change-case");
1024
+ var import_change_case4 = require("change-case");
1025
1025
 
1026
1026
  // src/util/path.ts
1027
1027
  var import_promises2 = require("fs/promises");
@@ -1071,7 +1071,96 @@ var fileExist = async (file) => {
1071
1071
  };
1072
1072
 
1073
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");
1074
1078
  var import_path4 = require("path");
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
+ `export {}`,
1133
+ `declare module '${this.module}' {`,
1134
+ ` interface ${this.interfaceName} {`,
1135
+ ...Array.from(this.types.entries()).map(([propName, type]) => {
1136
+ return ` readonly ${(0, import_change_case3.camelCase)(propName)}: ${type}`;
1137
+ }),
1138
+ ` }`,
1139
+ `}`
1140
+ ].join("\n");
1141
+ }
1142
+ };
1143
+ var TypeObject = class {
1144
+ types = /* @__PURE__ */ new Map();
1145
+ addType(name, type) {
1146
+ this.types.set(name, type);
1147
+ return this;
1148
+ }
1149
+ toString() {
1150
+ if (!this.types.size) {
1151
+ return "";
1152
+ }
1153
+ return [
1154
+ "{",
1155
+ ...Array.from(this.types.entries()).map(([propName, type]) => {
1156
+ return ` readonly ${(0, import_change_case3.camelCase)(propName)}: ${type}`;
1157
+ }),
1158
+ " }"
1159
+ ].join("\n");
1160
+ }
1161
+ };
1162
+
1163
+ // src/plugins/function.ts
1075
1164
  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");
1076
1165
  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");
1077
1166
  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");
@@ -1206,51 +1295,33 @@ var schema = import_zod6.z.object({
1206
1295
  ).optional()
1207
1296
  }).array()
1208
1297
  });
1298
+ var typeGenCode = `
1299
+ import { InvokeOptions } from '@awsless/lambda'
1300
+
1301
+ type Invoke<Name extends string, Func extends (...args: any[]) => any> = {
1302
+ name: Name
1303
+ invoke: (event: Parameters<Func>[0], options?: Omit<InvokeOptions, 'name' | 'payload'>) => ReturnType<Func>
1304
+ async: (event: Parameters<Func>[0], options?: Omit<InvokeOptions, 'name' | 'payload' | 'type'>) => ReturnType<Func>
1305
+ }`;
1209
1306
  var functionPlugin = definePlugin({
1210
1307
  name: "function",
1211
1308
  schema,
1212
1309
  onTypeGen({ config }) {
1213
- const imports = [];
1214
- const props = [];
1310
+ const types2 = new TypeGen("@awsless/awsless", "FunctionResources");
1311
+ types2.addCode(typeGenCode);
1215
1312
  for (const stack of config.stacks) {
1216
- const functions = [];
1313
+ const list3 = new TypeObject();
1217
1314
  for (const [name, fileOrProps] of Object.entries(stack.functions || {})) {
1218
- const varName = (0, import_change_case3.camelCase)(`${stack.name}-${name}`);
1219
- const funcName = (0, import_change_case3.paramCase)(`${config.name}-${stack.name}--${name}`);
1315
+ const varName = (0, import_change_case4.camelCase)(`${stack.name}-${name}`);
1316
+ const funcName = formatName(`${config.name}-${stack.name}-${name}`);
1220
1317
  const file = typeof fileOrProps === "string" ? fileOrProps : fileOrProps.file;
1221
- const relFile = (0, import_path4.relative)(directories.types, file);
1222
- imports.push(`import ${varName} from '${relFile}'`);
1223
- functions.push(` readonly ${(0, import_change_case3.camelCase)(name)}: Invoke<'${funcName}', typeof ${varName}>`);
1224
- }
1225
- if (functions.length > 0) {
1226
- props.push(` readonly ${(0, import_change_case3.camelCase)(stack.name)}: {
1227
- ${functions.join("\n")}
1228
- }`);
1318
+ const relFile = (0, import_path6.relative)(directories.types, file);
1319
+ types2.addImport(varName, relFile);
1320
+ list3.addType(name, `Invoke<'${funcName}', typeof ${varName}>`);
1229
1321
  }
1322
+ types2.addType(stack.name, list3.toString());
1230
1323
  }
1231
- if (imports.length === 0) {
1232
- return;
1233
- }
1234
- return (
1235
- /* TS */
1236
- `
1237
- ${imports.join("\n")}
1238
-
1239
- import { InvokeOptions } from '@awsless/lambda'
1240
-
1241
- type Options = Omit<InvokeOptions, 'name' | 'payload'>
1242
-
1243
- type Invoke<Name extends string, Func extends (...args: any[]) => any> = {
1244
- name: Name
1245
- invoke: (event: Parameters<Func>[0], options?: Options) => ReturnType<Func>
1246
- }
1247
-
1248
- declare module '@awsless/awsless' {
1249
- interface FunctionResources {
1250
- ${props.join("\n")}
1251
- }
1252
- }`
1253
- );
1324
+ return types2.toString();
1254
1325
  },
1255
1326
  onStack(ctx) {
1256
1327
  const { config, stack } = ctx;
@@ -1481,7 +1552,7 @@ var Queue = class extends Resource {
1481
1552
  };
1482
1553
 
1483
1554
  // src/formation/resource/lambda/event-source-mapping.ts
1484
- var import_change_case4 = require("change-case");
1555
+ var import_change_case5 = require("change-case");
1485
1556
  var EventSourceMapping = class extends Resource {
1486
1557
  constructor(logicalId, props) {
1487
1558
  super("AWS::Lambda::EventSourceMapping", logicalId);
@@ -1503,7 +1574,7 @@ var EventSourceMapping = class extends Resource {
1503
1574
  ...this.attr("ParallelizationFactor", this.props.parallelizationFactor),
1504
1575
  ...this.attr("TumblingWindowInSeconds", this.props.tumblingWindow?.toSeconds()),
1505
1576
  ...this.attr("BisectBatchOnFunctionError", this.props.bisectBatchOnError),
1506
- ...this.attr("StartingPosition", this.props.startingPosition && (0, import_change_case4.constantCase)(this.props.startingPosition)),
1577
+ ...this.attr("StartingPosition", this.props.startingPosition && (0, import_change_case5.constantCase)(this.props.startingPosition)),
1507
1578
  ...this.attr("StartingPositionTimestamp", this.props.startingPositionTimestamp),
1508
1579
  ...this.props.maxConcurrency ? {
1509
1580
  ScalingConfig: {
@@ -1651,6 +1722,18 @@ var queuePlugin = definePlugin({
1651
1722
  ).optional()
1652
1723
  }).array()
1653
1724
  }),
1725
+ onTypeGen({ config }) {
1726
+ const types2 = new TypeGen("@awsless/awsless", "QueueResources");
1727
+ for (const stack of config.stacks) {
1728
+ const list3 = new TypeObject();
1729
+ for (const name of Object.keys(stack.queues || {})) {
1730
+ const queueName = formatName(`${config.name}-${stack.name}-${name}`);
1731
+ list3.addType(name, `{ name: '${queueName}' }`);
1732
+ }
1733
+ types2.addType(stack.name, list3.toString());
1734
+ }
1735
+ return types2.toString();
1736
+ },
1654
1737
  onStack(ctx) {
1655
1738
  const { stack, config, stackConfig, bind } = ctx;
1656
1739
  for (const [id, functionOrProps] of Object.entries(stackConfig.queues || {})) {
@@ -1679,7 +1762,7 @@ var queuePlugin = definePlugin({
1679
1762
  var import_zod9 = require("zod");
1680
1763
 
1681
1764
  // src/formation/resource/dynamodb/table.ts
1682
- var import_change_case5 = require("change-case");
1765
+ var import_change_case6 = require("change-case");
1683
1766
  var Table = class extends Resource {
1684
1767
  constructor(logicalId, props) {
1685
1768
  super("AWS::DynamoDB::Table", logicalId);
@@ -1752,7 +1835,7 @@ var Table = class extends Resource {
1752
1835
  return {
1753
1836
  TableName: this.name,
1754
1837
  BillingMode: "PAY_PER_REQUEST",
1755
- TableClass: (0, import_change_case5.constantCase)(this.props.class || "standard"),
1838
+ TableClass: (0, import_change_case6.constantCase)(this.props.class || "standard"),
1756
1839
  PointInTimeRecoverySpecification: {
1757
1840
  PointInTimeRecoveryEnabled: this.props.pointInTimeRecovery || false
1758
1841
  },
@@ -1763,7 +1846,7 @@ var Table = class extends Resource {
1763
1846
  AttributeDefinitions: this.attributeDefinitions(),
1764
1847
  ...this.props.stream ? {
1765
1848
  StreamSpecification: {
1766
- StreamViewType: (0, import_change_case5.constantCase)(this.props.stream)
1849
+ StreamViewType: (0, import_change_case6.constantCase)(this.props.stream)
1767
1850
  }
1768
1851
  } : {},
1769
1852
  ...this.props.timeToLiveAttribute ? {
@@ -1780,7 +1863,7 @@ var Table = class extends Resource {
1780
1863
  ...props.sort ? [{ KeyType: "RANGE", AttributeName: props.sort }] : []
1781
1864
  ],
1782
1865
  Projection: {
1783
- ProjectionType: (0, import_change_case5.constantCase)(props.projection || "all")
1866
+ ProjectionType: (0, import_change_case6.constantCase)(props.projection || "all")
1784
1867
  }
1785
1868
  }))
1786
1869
  } : {}
@@ -1924,6 +2007,18 @@ var tablePlugin = definePlugin({
1924
2007
  ).optional()
1925
2008
  }).array()
1926
2009
  }),
2010
+ onTypeGen({ config }) {
2011
+ const types2 = new TypeGen("@awsless/awsless", "TableResources");
2012
+ for (const stack of config.stacks) {
2013
+ const list3 = new TypeObject();
2014
+ for (const name of Object.keys(stack.tables || {})) {
2015
+ const tableName = formatName(`${config.name}-${stack.name}-${name}`);
2016
+ list3.addType(name, `{ name: '${tableName}' }`);
2017
+ }
2018
+ types2.addType(stack.name, list3.toString());
2019
+ }
2020
+ return types2.toString();
2021
+ },
1927
2022
  onStack(ctx) {
1928
2023
  const { config, stack, stackConfig, bind } = ctx;
1929
2024
  for (const [id, props] of Object.entries(stackConfig.tables || {})) {
@@ -1953,7 +2048,7 @@ var tablePlugin = definePlugin({
1953
2048
  var import_zod10 = require("zod");
1954
2049
 
1955
2050
  // src/formation/resource/s3/bucket.ts
1956
- var import_change_case6 = require("change-case");
2051
+ var import_change_case7 = require("change-case");
1957
2052
  var Bucket = class extends Resource {
1958
2053
  constructor(logicalId, props = {}) {
1959
2054
  super("AWS::S3::Bucket", logicalId);
@@ -1988,7 +2083,7 @@ var Bucket = class extends Resource {
1988
2083
  properties() {
1989
2084
  return {
1990
2085
  BucketName: this.name,
1991
- AccessControl: (0, import_change_case6.pascalCase)(this.props.accessControl ?? "private"),
2086
+ AccessControl: (0, import_change_case7.pascalCase)(this.props.accessControl ?? "private"),
1992
2087
  ...this.props.versioned ? {
1993
2088
  VersioningConfiguration: {
1994
2089
  Status: "Enabled"
@@ -2110,6 +2205,16 @@ var topicPlugin = definePlugin({
2110
2205
  topics: import_zod11.z.record(ResourceIdSchema, FunctionSchema).optional()
2111
2206
  }).array()
2112
2207
  }),
2208
+ onTypeGen({ config }) {
2209
+ const gen = new TypeGen("@awsless/awsless", "TopicResources");
2210
+ for (const stack of config.stacks) {
2211
+ for (const topic of Object.keys(stack.topics || {})) {
2212
+ const name = formatName(`${config.name}-${topic}`);
2213
+ gen.addType(topic, `{ name: '${name}' }`);
2214
+ }
2215
+ }
2216
+ return gen.toString();
2217
+ },
2113
2218
  onApp({ config, bootstrap: bootstrap2, bind }) {
2114
2219
  const allTopicNames = config.stacks.map((stack) => {
2115
2220
  return Object.keys(stack.topics || {});
@@ -2169,12 +2274,12 @@ var extendPlugin = definePlugin({
2169
2274
  var import_zod13 = require("zod");
2170
2275
 
2171
2276
  // src/formation/resource/iot/topic-rule.ts
2172
- var import_change_case7 = require("change-case");
2277
+ var import_change_case8 = require("change-case");
2173
2278
  var TopicRule = class extends Resource {
2174
2279
  constructor(logicalId, props) {
2175
2280
  super("AWS::IoT::TopicRule", logicalId);
2176
2281
  this.props = props;
2177
- this.name = (0, import_change_case7.snakeCase)(this.props.name || logicalId);
2282
+ this.name = (0, import_change_case8.snakeCase)(this.props.name || logicalId);
2178
2283
  }
2179
2284
  name;
2180
2285
  get arn() {
@@ -2274,10 +2379,10 @@ var toArray = (value) => {
2274
2379
  };
2275
2380
 
2276
2381
  // src/plugins/graphql.ts
2277
- var import_change_case11 = require("change-case");
2382
+ var import_change_case12 = require("change-case");
2278
2383
 
2279
2384
  // src/formation/resource/appsync/graphql-api.ts
2280
- var import_change_case8 = require("change-case");
2385
+ var import_change_case9 = require("change-case");
2281
2386
  var GraphQLApi = class extends Resource {
2282
2387
  constructor(logicalId, props) {
2283
2388
  super("AWS::AppSync::GraphQLApi", logicalId);
@@ -2309,7 +2414,7 @@ var GraphQLApi = class extends Resource {
2309
2414
  properties() {
2310
2415
  return {
2311
2416
  Name: this.name,
2312
- AuthenticationType: (0, import_change_case8.constantCase)(this.props.authenticationType || "api-key"),
2417
+ AuthenticationType: (0, import_change_case9.constantCase)(this.props.authenticationType || "api-key"),
2313
2418
  AdditionalAuthenticationProviders: this.lambdaAuthProviders.map((provider) => ({
2314
2419
  AuthenticationType: "AWS_LAMBDA",
2315
2420
  LambdaAuthorizerConfig: {
@@ -2350,7 +2455,7 @@ var RecordSet = class extends Resource {
2350
2455
 
2351
2456
  // src/formation/resource/appsync/graphql-schema.ts
2352
2457
  var import_graphql = require("graphql");
2353
- var import_promises3 = require("fs/promises");
2458
+ var import_promises4 = require("fs/promises");
2354
2459
  var import_merge = require("@graphql-tools/merge");
2355
2460
  var GraphQLSchema = class extends Resource {
2356
2461
  constructor(logicalId, props) {
@@ -2375,7 +2480,7 @@ var Definition = class extends Asset {
2375
2480
  async build({ write }) {
2376
2481
  const files = [this.files].flat();
2377
2482
  const schemas = await Promise.all(files.map((file) => {
2378
- return (0, import_promises3.readFile)(file, "utf8");
2483
+ return (0, import_promises4.readFile)(file, "utf8");
2379
2484
  }));
2380
2485
  const defs = (0, import_merge.mergeTypeDefs)(schemas);
2381
2486
  const schema2 = (0, import_graphql.print)(defs);
@@ -2395,7 +2500,7 @@ var Definition = class extends Asset {
2395
2500
  };
2396
2501
 
2397
2502
  // src/formation/resource/appsync/code.ts
2398
- var import_promises4 = require("fs/promises");
2503
+ var import_promises5 = require("fs/promises");
2399
2504
  var Code2 = class {
2400
2505
  static fromFile(id, file) {
2401
2506
  return new FileCode2(id, file);
@@ -2422,7 +2527,7 @@ var FileCode2 = class extends Asset {
2422
2527
  }
2423
2528
  code;
2424
2529
  async build() {
2425
- const code = await (0, import_promises4.readFile)(this.file);
2530
+ const code = await (0, import_promises5.readFile)(this.file);
2426
2531
  this.code = code.toString("utf8");
2427
2532
  return {
2428
2533
  size: formatByteSize(code.byteLength)
@@ -2436,12 +2541,12 @@ var FileCode2 = class extends Asset {
2436
2541
  };
2437
2542
 
2438
2543
  // src/formation/resource/appsync/data-source.ts
2439
- var import_change_case9 = require("change-case");
2544
+ var import_change_case10 = require("change-case");
2440
2545
  var DataSource = class extends Resource {
2441
2546
  constructor(logicalId, props) {
2442
2547
  super("AWS::AppSync::DataSource", logicalId);
2443
2548
  this.props = props;
2444
- this.name = (0, import_change_case9.snakeCase)(this.props.name || logicalId);
2549
+ this.name = (0, import_change_case10.snakeCase)(this.props.name || logicalId);
2445
2550
  }
2446
2551
  static fromLambda(logicalId, apiId, props) {
2447
2552
  return new DataSource(logicalId, {
@@ -2481,14 +2586,14 @@ var DataSource = class extends Resource {
2481
2586
  };
2482
2587
 
2483
2588
  // src/formation/resource/appsync/function-configuration.ts
2484
- var import_change_case10 = require("change-case");
2589
+ var import_change_case11 = require("change-case");
2485
2590
  var FunctionConfiguration = class extends Resource {
2486
2591
  constructor(logicalId, props) {
2487
2592
  super("AWS::AppSync::FunctionConfiguration", logicalId, [
2488
2593
  props.code
2489
2594
  ]);
2490
2595
  this.props = props;
2491
- this.name = (0, import_change_case10.snakeCase)(this.props.name || logicalId);
2596
+ this.name = (0, import_change_case11.snakeCase)(this.props.name || logicalId);
2492
2597
  }
2493
2598
  name;
2494
2599
  get id() {
@@ -2707,7 +2812,7 @@ var graphqlPlugin = definePlugin({
2707
2812
  const apiId = bootstrap2.import(`graphql-${id}`);
2708
2813
  for (const [typeAndField, functionProps] of Object.entries(props.resolvers || {})) {
2709
2814
  const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
2710
- const entryId = (0, import_change_case11.paramCase)(`${id}-${typeName}-${fieldName}`);
2815
+ const entryId = (0, import_change_case12.paramCase)(`${id}-${typeName}-${fieldName}`);
2711
2816
  const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
2712
2817
  const source = new AppsyncEventSource(entryId, lambda, {
2713
2818
  apiId,
@@ -3391,7 +3496,7 @@ var LoadBalancer = class extends Resource {
3391
3496
  };
3392
3497
 
3393
3498
  // src/formation/resource/elb/listener.ts
3394
- var import_change_case12 = require("change-case");
3499
+ var import_change_case13 = require("change-case");
3395
3500
  var Listener = class extends Resource {
3396
3501
  constructor(logicalId, props) {
3397
3502
  super("AWS::ElasticLoadBalancingV2::Listener", logicalId);
@@ -3407,7 +3512,7 @@ var Listener = class extends Resource {
3407
3512
  return {
3408
3513
  LoadBalancerArn: this.props.loadBalancerArn,
3409
3514
  Port: this.props.port,
3410
- Protocol: (0, import_change_case12.constantCase)(this.props.protocol),
3515
+ Protocol: (0, import_change_case13.constantCase)(this.props.protocol),
3411
3516
  Certificates: this.props.certificates.map((arn) => ({
3412
3517
  CertificateArn: arn
3413
3518
  })),
@@ -4164,7 +4269,7 @@ var toApp = async (config, filters) => {
4164
4269
  };
4165
4270
 
4166
4271
  // src/config.ts
4167
- var import_path7 = require("path");
4272
+ var import_path9 = require("path");
4168
4273
 
4169
4274
  // src/util/account.ts
4170
4275
  var import_client_sts = require("@aws-sdk/client-sts");
@@ -4251,8 +4356,9 @@ var AppSchema = import_zod23.z.object({
4251
4356
  var import_rollup3 = require("rollup");
4252
4357
  var import_rollup_plugin_swc32 = require("rollup-plugin-swc3");
4253
4358
  var import_rollup_plugin_replace = __toESM(require("rollup-plugin-replace"), 1);
4254
- var import_path5 = require("path");
4255
- var import_promises5 = require("fs/promises");
4359
+ var import_event_iterator = require("event-iterator");
4360
+ var import_path7 = require("path");
4361
+ var import_promises6 = require("fs/promises");
4256
4362
  var importFile = async (path) => {
4257
4363
  const bundle = await (0, import_rollup3.rollup)({
4258
4364
  input: path,
@@ -4261,28 +4367,83 @@ var importFile = async (path) => {
4261
4367
  },
4262
4368
  plugins: [
4263
4369
  (0, import_rollup_plugin_replace.default)({
4264
- __dirname: (id) => `'${(0, import_path5.dirname)(id)}'`
4370
+ __dirname: (id) => `'${(0, import_path7.dirname)(id)}'`
4265
4371
  }),
4266
4372
  (0, import_rollup_plugin_swc32.swc)({
4267
4373
  minify: false,
4268
4374
  jsc: {
4269
- baseUrl: (0, import_path5.dirname)(path)
4375
+ baseUrl: (0, import_path7.dirname)(path)
4270
4376
  }
4271
4377
  })
4272
4378
  ]
4273
4379
  });
4274
- const outputFile = (0, import_path5.join)(directories.cache, "config.js");
4380
+ const outputFile = (0, import_path7.join)(directories.cache, "config.js");
4275
4381
  const result = await bundle.generate({
4276
4382
  format: "esm",
4277
4383
  exports: "default"
4278
4384
  });
4279
4385
  const output = result.output[0];
4280
4386
  const code = output.code;
4281
- await (0, import_promises5.mkdir)(directories.cache, { recursive: true });
4282
- await (0, import_promises5.writeFile)(outputFile, code);
4387
+ await (0, import_promises6.mkdir)(directories.cache, { recursive: true });
4388
+ await (0, import_promises6.writeFile)(outputFile, code);
4283
4389
  debug("Save config file:", style.info(outputFile));
4284
4390
  return import(outputFile);
4285
4391
  };
4392
+ var watchFile = (path) => {
4393
+ return new import_event_iterator.EventIterator((queue2) => {
4394
+ const watcher = (0, import_rollup3.watch)({
4395
+ watch: {
4396
+ skipWrite: true
4397
+ },
4398
+ input: path,
4399
+ onwarn: (error) => {
4400
+ debugError(error.message);
4401
+ },
4402
+ plugins: [
4403
+ (0, import_rollup_plugin_replace.default)({
4404
+ __dirname: (id) => `'${(0, import_path7.dirname)(id)}'`
4405
+ }),
4406
+ (0, import_rollup_plugin_swc32.swc)({
4407
+ minify: false,
4408
+ jsc: {
4409
+ baseUrl: (0, import_path7.dirname)(path)
4410
+ }
4411
+ })
4412
+ ]
4413
+ });
4414
+ let resume;
4415
+ queue2.on("lowWater", () => {
4416
+ resume?.(true);
4417
+ });
4418
+ watcher.on("close", queue2.stop);
4419
+ watcher.on("event", async (event) => {
4420
+ if (event.code === "ERROR") {
4421
+ queue2.fail(new Error(event.error.message));
4422
+ }
4423
+ if (event.code === "BUNDLE_END") {
4424
+ const result = await event.result.generate({
4425
+ format: "esm",
4426
+ exports: "default"
4427
+ });
4428
+ event.result.close();
4429
+ const output = result.output[0];
4430
+ const code = output.code;
4431
+ const outputFile = (0, import_path7.join)(directories.cache, "config.js");
4432
+ await (0, import_promises6.mkdir)(directories.cache, { recursive: true });
4433
+ await (0, import_promises6.writeFile)(outputFile, code);
4434
+ debug("Save config file:", style.info(outputFile));
4435
+ const config = await import(`${outputFile}?${Date.now()}`);
4436
+ queue2.push(config);
4437
+ }
4438
+ });
4439
+ return () => {
4440
+ watcher.close();
4441
+ };
4442
+ }, {
4443
+ highWaterMark: 1,
4444
+ lowWaterMark: 0
4445
+ });
4446
+ };
4286
4447
 
4287
4448
  // src/config.ts
4288
4449
  var importConfig = async (options) => {
@@ -4292,7 +4453,7 @@ var importConfig = async (options) => {
4292
4453
  setRoot(root2);
4293
4454
  debug("CWD:", style.info(root2));
4294
4455
  debug("Import config file");
4295
- const fileName = (0, import_path7.join)(root2, configFile);
4456
+ const fileName = (0, import_path9.join)(root2, configFile);
4296
4457
  const module2 = await importFile(fileName);
4297
4458
  const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
4298
4459
  debug("Validate config file");
@@ -4318,6 +4479,40 @@ var importConfig = async (options) => {
4318
4479
  credentials
4319
4480
  };
4320
4481
  };
4482
+ var watchConfig = async function* (options) {
4483
+ debug("Find the root directory");
4484
+ const configFile = options.configFile || "awsless.config.ts";
4485
+ const root2 = await findRootDir(process.cwd(), configFile);
4486
+ setRoot(root2);
4487
+ debug("CWD:", style.info(root2));
4488
+ debug("Import config file");
4489
+ const fileName = (0, import_path9.join)(root2, configFile);
4490
+ for await (const module2 of watchFile(fileName)) {
4491
+ const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
4492
+ debug("Validate config file");
4493
+ const plugins = [
4494
+ ...defaultPlugins,
4495
+ ...appConfig.plugins || []
4496
+ ];
4497
+ let schema2 = AppSchema;
4498
+ for (const plugin of plugins) {
4499
+ if (plugin.schema) {
4500
+ schema2 = schema2.and(plugin.schema);
4501
+ }
4502
+ }
4503
+ const config = await schema2.parseAsync(appConfig);
4504
+ debug("Load credentials", style.info(config.profile));
4505
+ const credentials = getCredentials(config.profile);
4506
+ debug("Load AWS account ID");
4507
+ const account = await getAccountId(credentials, config.region);
4508
+ debug("Account ID:", style.info(account));
4509
+ yield {
4510
+ ...config,
4511
+ account,
4512
+ credentials
4513
+ };
4514
+ }
4515
+ };
4321
4516
 
4322
4517
  // src/cli/ui/layout/basic.ts
4323
4518
  var br = () => {
@@ -4793,7 +4988,7 @@ var layout = async (cb) => {
4793
4988
  };
4794
4989
 
4795
4990
  // src/cli/ui/complex/builder.ts
4796
- var import_promises6 = require("fs/promises");
4991
+ var import_promises7 = require("fs/promises");
4797
4992
 
4798
4993
  // src/cli/ui/layout/flex-line.ts
4799
4994
  var stripEscapeCode = (str) => {
@@ -4816,7 +5011,7 @@ var flexLine = (term, left, right, reserveSpace = 0) => {
4816
5011
  };
4817
5012
 
4818
5013
  // src/cli/ui/complex/builder.ts
4819
- var import_path10 = require("path");
5014
+ var import_path12 = require("path");
4820
5015
  var assetBuilder = (app) => {
4821
5016
  return async (term) => {
4822
5017
  const assets = [];
@@ -4879,10 +5074,10 @@ var assetBuilder = (app) => {
4879
5074
  try {
4880
5075
  const data = await asset.build({
4881
5076
  async write(file, data2) {
4882
- const fullpath = (0, import_path10.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
4883
- const basepath = (0, import_path10.dirname)(fullpath);
4884
- await (0, import_promises6.mkdir)(basepath, { recursive: true });
4885
- await (0, import_promises6.writeFile)(fullpath, data2);
5077
+ const fullpath = (0, import_path12.join)(directories.asset, asset.type, app.name, stack.name, asset.id, file);
5078
+ const basepath = (0, import_path12.dirname)(fullpath);
5079
+ await (0, import_promises7.mkdir)(basepath, { recursive: true });
5080
+ await (0, import_promises7.writeFile)(fullpath, data2);
4886
5081
  }
4887
5082
  });
4888
5083
  details.set({
@@ -4906,7 +5101,7 @@ var assetBuilder = (app) => {
4906
5101
  };
4907
5102
 
4908
5103
  // src/util/cleanup.ts
4909
- var import_promises7 = require("fs/promises");
5104
+ var import_promises8 = require("fs/promises");
4910
5105
  var cleanUp = async () => {
4911
5106
  debug("Clean up template, cache, and asset files");
4912
5107
  const paths = [
@@ -4915,57 +5110,33 @@ var cleanUp = async () => {
4915
5110
  directories.types,
4916
5111
  directories.template
4917
5112
  ];
4918
- await Promise.all(paths.map((path) => (0, import_promises7.rm)(path, {
5113
+ await Promise.all(paths.map((path) => (0, import_promises8.rm)(path, {
4919
5114
  recursive: true,
4920
5115
  force: true,
4921
5116
  maxRetries: 2
4922
5117
  })));
4923
- await Promise.all(paths.map((path) => (0, import_promises7.mkdir)(path, {
5118
+ await Promise.all(paths.map((path) => (0, import_promises8.mkdir)(path, {
4924
5119
  recursive: true
4925
5120
  })));
4926
5121
  };
4927
5122
 
4928
5123
  // src/cli/ui/complex/template.ts
4929
- var import_promises8 = require("fs/promises");
4930
- var import_path13 = require("path");
5124
+ var import_promises9 = require("fs/promises");
5125
+ var import_path15 = require("path");
4931
5126
  var templateBuilder = (app) => {
4932
5127
  return async (term) => {
4933
5128
  const done = term.out.write(loadingDialog("Building stack templates..."));
4934
5129
  await Promise.all(app.stacks.map(async (stack) => {
4935
5130
  const template = stack.toString(true);
4936
- const path = (0, import_path13.join)(directories.template, app.name);
4937
- const file = (0, import_path13.join)(path, `${stack.name}.json`);
4938
- await (0, import_promises8.mkdir)(path, { recursive: true });
4939
- await (0, import_promises8.writeFile)(file, template);
5131
+ const path = (0, import_path15.join)(directories.template, app.name);
5132
+ const file = (0, import_path15.join)(path, `${stack.name}.json`);
5133
+ await (0, import_promises9.mkdir)(path, { recursive: true });
5134
+ await (0, import_promises9.writeFile)(file, template);
4940
5135
  }));
4941
5136
  done("Done building stack templates");
4942
5137
  };
4943
5138
  };
4944
5139
 
4945
- // src/util/type-gen.ts
4946
- var import_promises9 = require("fs/promises");
4947
- var import_path15 = require("path");
4948
- var generateResourceTypes = async (config) => {
4949
- const plugins = [
4950
- ...defaultPlugins,
4951
- ...config.plugins || []
4952
- ];
4953
- const files = [];
4954
- for (const plugin of plugins) {
4955
- const code = plugin.onTypeGen?.({ config });
4956
- if (code) {
4957
- const file = (0, import_path15.join)(directories.types, `${plugin.name}.d.ts`);
4958
- files.push((0, import_path15.relative)(directories.root, file));
4959
- await (0, import_promises9.mkdir)(directories.types, { recursive: true });
4960
- await (0, import_promises9.writeFile)(file, code);
4961
- }
4962
- }
4963
- if (files.length) {
4964
- const code = files.map((file) => `import '${file}';`).join("\n");
4965
- await (0, import_promises9.writeFile)((0, import_path15.join)(directories.root, `awsless.d.ts`), code);
4966
- }
4967
- };
4968
-
4969
5140
  // src/cli/ui/complex/types.ts
4970
5141
  var typesGenerator = (config) => {
4971
5142
  return async (term) => {
@@ -5018,7 +5189,7 @@ var shouldDeployBootstrap = async (client, stack) => {
5018
5189
  // src/formation/client.ts
5019
5190
  var import_client_cloudformation = require("@aws-sdk/client-cloudformation");
5020
5191
  var import_client_s3 = require("@aws-sdk/client-s3");
5021
- var import_change_case13 = require("change-case");
5192
+ var import_change_case14 = require("change-case");
5022
5193
  var StackClient = class {
5023
5194
  constructor(app, account, region, credentials) {
5024
5195
  this.app = app;
@@ -5051,7 +5222,7 @@ var StackClient = class {
5051
5222
  };
5052
5223
  }
5053
5224
  stackName(stackName) {
5054
- return (0, import_change_case13.paramCase)(`${this.app.name}-${stackName}`);
5225
+ return (0, import_change_case14.paramCase)(`${this.app.name}-${stackName}`);
5055
5226
  }
5056
5227
  tags(stack) {
5057
5228
  const tags = [];
@@ -5757,6 +5928,19 @@ var types = (program2) => {
5757
5928
  });
5758
5929
  };
5759
5930
 
5931
+ // src/cli/command/dev.ts
5932
+ var dev = (program2) => {
5933
+ program2.command("dev").description("Start the development service").action(async () => {
5934
+ await layout(async (_, write) => {
5935
+ const options = program2.optsWithGlobals();
5936
+ for await (const config of watchConfig(options)) {
5937
+ await cleanUp();
5938
+ await write(typesGenerator(config));
5939
+ }
5940
+ });
5941
+ });
5942
+ };
5943
+
5760
5944
  // src/cli/program.ts
5761
5945
  var program = new import_commander.Command();
5762
5946
  program.name(logo().join("").replace(/\s+/, ""));
@@ -5778,6 +5962,7 @@ var commands2 = [
5778
5962
  types,
5779
5963
  build,
5780
5964
  deploy,
5965
+ dev,
5781
5966
  secrets,
5782
5967
  test
5783
5968
  // diff,