@awsless/awsless 0.0.35 → 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,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,95 @@ 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
+ `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
1075
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");
1076
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");
1077
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");
@@ -1206,51 +1294,33 @@ var schema = import_zod6.z.object({
1206
1294
  ).optional()
1207
1295
  }).array()
1208
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
+ }`;
1209
1305
  var functionPlugin = definePlugin({
1210
1306
  name: "function",
1211
1307
  schema,
1212
1308
  onTypeGen({ config }) {
1213
- const imports = [];
1214
- const props = [];
1309
+ const types2 = new TypeGen("@awsless/awsless", "FunctionResources");
1310
+ types2.addCode(typeGenCode);
1215
1311
  for (const stack of config.stacks) {
1216
- const functions = [];
1312
+ const list3 = new TypeObject();
1217
1313
  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}`);
1314
+ const varName = (0, import_change_case4.camelCase)(`${stack.name}-${name}`);
1315
+ const funcName = formatName(`${config.name}-${stack.name}-${name}`);
1220
1316
  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
- }`);
1317
+ const relFile = (0, import_path6.relative)(directories.types, file);
1318
+ types2.addImport(varName, relFile);
1319
+ list3.addType(name, `Invoke<'${funcName}', typeof ${varName}>`);
1229
1320
  }
1321
+ types2.addType(stack.name, list3.toString());
1230
1322
  }
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
- );
1323
+ return types2.toString();
1254
1324
  },
1255
1325
  onStack(ctx) {
1256
1326
  const { config, stack } = ctx;
@@ -1481,7 +1551,7 @@ var Queue = class extends Resource {
1481
1551
  };
1482
1552
 
1483
1553
  // src/formation/resource/lambda/event-source-mapping.ts
1484
- var import_change_case4 = require("change-case");
1554
+ var import_change_case5 = require("change-case");
1485
1555
  var EventSourceMapping = class extends Resource {
1486
1556
  constructor(logicalId, props) {
1487
1557
  super("AWS::Lambda::EventSourceMapping", logicalId);
@@ -1503,7 +1573,7 @@ var EventSourceMapping = class extends Resource {
1503
1573
  ...this.attr("ParallelizationFactor", this.props.parallelizationFactor),
1504
1574
  ...this.attr("TumblingWindowInSeconds", this.props.tumblingWindow?.toSeconds()),
1505
1575
  ...this.attr("BisectBatchOnFunctionError", this.props.bisectBatchOnError),
1506
- ...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)),
1507
1577
  ...this.attr("StartingPositionTimestamp", this.props.startingPositionTimestamp),
1508
1578
  ...this.props.maxConcurrency ? {
1509
1579
  ScalingConfig: {
@@ -1651,6 +1721,18 @@ var queuePlugin = definePlugin({
1651
1721
  ).optional()
1652
1722
  }).array()
1653
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
+ },
1654
1736
  onStack(ctx) {
1655
1737
  const { stack, config, stackConfig, bind } = ctx;
1656
1738
  for (const [id, functionOrProps] of Object.entries(stackConfig.queues || {})) {
@@ -1679,7 +1761,7 @@ var queuePlugin = definePlugin({
1679
1761
  var import_zod9 = require("zod");
1680
1762
 
1681
1763
  // src/formation/resource/dynamodb/table.ts
1682
- var import_change_case5 = require("change-case");
1764
+ var import_change_case6 = require("change-case");
1683
1765
  var Table = class extends Resource {
1684
1766
  constructor(logicalId, props) {
1685
1767
  super("AWS::DynamoDB::Table", logicalId);
@@ -1752,7 +1834,7 @@ var Table = class extends Resource {
1752
1834
  return {
1753
1835
  TableName: this.name,
1754
1836
  BillingMode: "PAY_PER_REQUEST",
1755
- TableClass: (0, import_change_case5.constantCase)(this.props.class || "standard"),
1837
+ TableClass: (0, import_change_case6.constantCase)(this.props.class || "standard"),
1756
1838
  PointInTimeRecoverySpecification: {
1757
1839
  PointInTimeRecoveryEnabled: this.props.pointInTimeRecovery || false
1758
1840
  },
@@ -1763,7 +1845,7 @@ var Table = class extends Resource {
1763
1845
  AttributeDefinitions: this.attributeDefinitions(),
1764
1846
  ...this.props.stream ? {
1765
1847
  StreamSpecification: {
1766
- StreamViewType: (0, import_change_case5.constantCase)(this.props.stream)
1848
+ StreamViewType: (0, import_change_case6.constantCase)(this.props.stream)
1767
1849
  }
1768
1850
  } : {},
1769
1851
  ...this.props.timeToLiveAttribute ? {
@@ -1780,7 +1862,7 @@ var Table = class extends Resource {
1780
1862
  ...props.sort ? [{ KeyType: "RANGE", AttributeName: props.sort }] : []
1781
1863
  ],
1782
1864
  Projection: {
1783
- ProjectionType: (0, import_change_case5.constantCase)(props.projection || "all")
1865
+ ProjectionType: (0, import_change_case6.constantCase)(props.projection || "all")
1784
1866
  }
1785
1867
  }))
1786
1868
  } : {}
@@ -1924,6 +2006,18 @@ var tablePlugin = definePlugin({
1924
2006
  ).optional()
1925
2007
  }).array()
1926
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
+ },
1927
2021
  onStack(ctx) {
1928
2022
  const { config, stack, stackConfig, bind } = ctx;
1929
2023
  for (const [id, props] of Object.entries(stackConfig.tables || {})) {
@@ -1953,7 +2047,7 @@ var tablePlugin = definePlugin({
1953
2047
  var import_zod10 = require("zod");
1954
2048
 
1955
2049
  // src/formation/resource/s3/bucket.ts
1956
- var import_change_case6 = require("change-case");
2050
+ var import_change_case7 = require("change-case");
1957
2051
  var Bucket = class extends Resource {
1958
2052
  constructor(logicalId, props = {}) {
1959
2053
  super("AWS::S3::Bucket", logicalId);
@@ -1988,7 +2082,7 @@ var Bucket = class extends Resource {
1988
2082
  properties() {
1989
2083
  return {
1990
2084
  BucketName: this.name,
1991
- AccessControl: (0, import_change_case6.pascalCase)(this.props.accessControl ?? "private"),
2085
+ AccessControl: (0, import_change_case7.pascalCase)(this.props.accessControl ?? "private"),
1992
2086
  ...this.props.versioned ? {
1993
2087
  VersioningConfiguration: {
1994
2088
  Status: "Enabled"
@@ -2110,6 +2204,16 @@ var topicPlugin = definePlugin({
2110
2204
  topics: import_zod11.z.record(ResourceIdSchema, FunctionSchema).optional()
2111
2205
  }).array()
2112
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
+ },
2113
2217
  onApp({ config, bootstrap: bootstrap2, bind }) {
2114
2218
  const allTopicNames = config.stacks.map((stack) => {
2115
2219
  return Object.keys(stack.topics || {});
@@ -2169,12 +2273,12 @@ var extendPlugin = definePlugin({
2169
2273
  var import_zod13 = require("zod");
2170
2274
 
2171
2275
  // src/formation/resource/iot/topic-rule.ts
2172
- var import_change_case7 = require("change-case");
2276
+ var import_change_case8 = require("change-case");
2173
2277
  var TopicRule = class extends Resource {
2174
2278
  constructor(logicalId, props) {
2175
2279
  super("AWS::IoT::TopicRule", logicalId);
2176
2280
  this.props = props;
2177
- this.name = (0, import_change_case7.snakeCase)(this.props.name || logicalId);
2281
+ this.name = (0, import_change_case8.snakeCase)(this.props.name || logicalId);
2178
2282
  }
2179
2283
  name;
2180
2284
  get arn() {
@@ -2274,10 +2378,10 @@ var toArray = (value) => {
2274
2378
  };
2275
2379
 
2276
2380
  // src/plugins/graphql.ts
2277
- var import_change_case11 = require("change-case");
2381
+ var import_change_case12 = require("change-case");
2278
2382
 
2279
2383
  // src/formation/resource/appsync/graphql-api.ts
2280
- var import_change_case8 = require("change-case");
2384
+ var import_change_case9 = require("change-case");
2281
2385
  var GraphQLApi = class extends Resource {
2282
2386
  constructor(logicalId, props) {
2283
2387
  super("AWS::AppSync::GraphQLApi", logicalId);
@@ -2309,7 +2413,7 @@ var GraphQLApi = class extends Resource {
2309
2413
  properties() {
2310
2414
  return {
2311
2415
  Name: this.name,
2312
- AuthenticationType: (0, import_change_case8.constantCase)(this.props.authenticationType || "api-key"),
2416
+ AuthenticationType: (0, import_change_case9.constantCase)(this.props.authenticationType || "api-key"),
2313
2417
  AdditionalAuthenticationProviders: this.lambdaAuthProviders.map((provider) => ({
2314
2418
  AuthenticationType: "AWS_LAMBDA",
2315
2419
  LambdaAuthorizerConfig: {
@@ -2350,7 +2454,7 @@ var RecordSet = class extends Resource {
2350
2454
 
2351
2455
  // src/formation/resource/appsync/graphql-schema.ts
2352
2456
  var import_graphql = require("graphql");
2353
- var import_promises3 = require("fs/promises");
2457
+ var import_promises4 = require("fs/promises");
2354
2458
  var import_merge = require("@graphql-tools/merge");
2355
2459
  var GraphQLSchema = class extends Resource {
2356
2460
  constructor(logicalId, props) {
@@ -2375,7 +2479,7 @@ var Definition = class extends Asset {
2375
2479
  async build({ write }) {
2376
2480
  const files = [this.files].flat();
2377
2481
  const schemas = await Promise.all(files.map((file) => {
2378
- return (0, import_promises3.readFile)(file, "utf8");
2482
+ return (0, import_promises4.readFile)(file, "utf8");
2379
2483
  }));
2380
2484
  const defs = (0, import_merge.mergeTypeDefs)(schemas);
2381
2485
  const schema2 = (0, import_graphql.print)(defs);
@@ -2395,7 +2499,7 @@ var Definition = class extends Asset {
2395
2499
  };
2396
2500
 
2397
2501
  // src/formation/resource/appsync/code.ts
2398
- var import_promises4 = require("fs/promises");
2502
+ var import_promises5 = require("fs/promises");
2399
2503
  var Code2 = class {
2400
2504
  static fromFile(id, file) {
2401
2505
  return new FileCode2(id, file);
@@ -2422,7 +2526,7 @@ var FileCode2 = class extends Asset {
2422
2526
  }
2423
2527
  code;
2424
2528
  async build() {
2425
- const code = await (0, import_promises4.readFile)(this.file);
2529
+ const code = await (0, import_promises5.readFile)(this.file);
2426
2530
  this.code = code.toString("utf8");
2427
2531
  return {
2428
2532
  size: formatByteSize(code.byteLength)
@@ -2436,12 +2540,12 @@ var FileCode2 = class extends Asset {
2436
2540
  };
2437
2541
 
2438
2542
  // src/formation/resource/appsync/data-source.ts
2439
- var import_change_case9 = require("change-case");
2543
+ var import_change_case10 = require("change-case");
2440
2544
  var DataSource = class extends Resource {
2441
2545
  constructor(logicalId, props) {
2442
2546
  super("AWS::AppSync::DataSource", logicalId);
2443
2547
  this.props = props;
2444
- this.name = (0, import_change_case9.snakeCase)(this.props.name || logicalId);
2548
+ this.name = (0, import_change_case10.snakeCase)(this.props.name || logicalId);
2445
2549
  }
2446
2550
  static fromLambda(logicalId, apiId, props) {
2447
2551
  return new DataSource(logicalId, {
@@ -2481,14 +2585,14 @@ var DataSource = class extends Resource {
2481
2585
  };
2482
2586
 
2483
2587
  // src/formation/resource/appsync/function-configuration.ts
2484
- var import_change_case10 = require("change-case");
2588
+ var import_change_case11 = require("change-case");
2485
2589
  var FunctionConfiguration = class extends Resource {
2486
2590
  constructor(logicalId, props) {
2487
2591
  super("AWS::AppSync::FunctionConfiguration", logicalId, [
2488
2592
  props.code
2489
2593
  ]);
2490
2594
  this.props = props;
2491
- this.name = (0, import_change_case10.snakeCase)(this.props.name || logicalId);
2595
+ this.name = (0, import_change_case11.snakeCase)(this.props.name || logicalId);
2492
2596
  }
2493
2597
  name;
2494
2598
  get id() {
@@ -2707,7 +2811,7 @@ var graphqlPlugin = definePlugin({
2707
2811
  const apiId = bootstrap2.import(`graphql-${id}`);
2708
2812
  for (const [typeAndField, functionProps] of Object.entries(props.resolvers || {})) {
2709
2813
  const [typeName, fieldName] = typeAndField.split(/[\s]+/g);
2710
- const entryId = (0, import_change_case11.paramCase)(`${id}-${typeName}-${fieldName}`);
2814
+ const entryId = (0, import_change_case12.paramCase)(`${id}-${typeName}-${fieldName}`);
2711
2815
  const lambda = toLambdaFunction(ctx, `graphql-${entryId}`, functionProps);
2712
2816
  const source = new AppsyncEventSource(entryId, lambda, {
2713
2817
  apiId,
@@ -3391,7 +3495,7 @@ var LoadBalancer = class extends Resource {
3391
3495
  };
3392
3496
 
3393
3497
  // src/formation/resource/elb/listener.ts
3394
- var import_change_case12 = require("change-case");
3498
+ var import_change_case13 = require("change-case");
3395
3499
  var Listener = class extends Resource {
3396
3500
  constructor(logicalId, props) {
3397
3501
  super("AWS::ElasticLoadBalancingV2::Listener", logicalId);
@@ -3407,7 +3511,7 @@ var Listener = class extends Resource {
3407
3511
  return {
3408
3512
  LoadBalancerArn: this.props.loadBalancerArn,
3409
3513
  Port: this.props.port,
3410
- Protocol: (0, import_change_case12.constantCase)(this.props.protocol),
3514
+ Protocol: (0, import_change_case13.constantCase)(this.props.protocol),
3411
3515
  Certificates: this.props.certificates.map((arn) => ({
3412
3516
  CertificateArn: arn
3413
3517
  })),
@@ -4164,7 +4268,7 @@ var toApp = async (config, filters) => {
4164
4268
  };
4165
4269
 
4166
4270
  // src/config.ts
4167
- var import_path7 = require("path");
4271
+ var import_path9 = require("path");
4168
4272
 
4169
4273
  // src/util/account.ts
4170
4274
  var import_client_sts = require("@aws-sdk/client-sts");
@@ -4251,8 +4355,9 @@ var AppSchema = import_zod23.z.object({
4251
4355
  var import_rollup3 = require("rollup");
4252
4356
  var import_rollup_plugin_swc32 = require("rollup-plugin-swc3");
4253
4357
  var import_rollup_plugin_replace = __toESM(require("rollup-plugin-replace"), 1);
4254
- var import_path5 = require("path");
4255
- var import_promises5 = require("fs/promises");
4358
+ var import_event_iterator = require("event-iterator");
4359
+ var import_path7 = require("path");
4360
+ var import_promises6 = require("fs/promises");
4256
4361
  var importFile = async (path) => {
4257
4362
  const bundle = await (0, import_rollup3.rollup)({
4258
4363
  input: path,
@@ -4261,28 +4366,83 @@ var importFile = async (path) => {
4261
4366
  },
4262
4367
  plugins: [
4263
4368
  (0, import_rollup_plugin_replace.default)({
4264
- __dirname: (id) => `'${(0, import_path5.dirname)(id)}'`
4369
+ __dirname: (id) => `'${(0, import_path7.dirname)(id)}'`
4265
4370
  }),
4266
4371
  (0, import_rollup_plugin_swc32.swc)({
4267
4372
  minify: false,
4268
4373
  jsc: {
4269
- baseUrl: (0, import_path5.dirname)(path)
4374
+ baseUrl: (0, import_path7.dirname)(path)
4270
4375
  }
4271
4376
  })
4272
4377
  ]
4273
4378
  });
4274
- const outputFile = (0, import_path5.join)(directories.cache, "config.js");
4379
+ const outputFile = (0, import_path7.join)(directories.cache, "config.js");
4275
4380
  const result = await bundle.generate({
4276
4381
  format: "esm",
4277
4382
  exports: "default"
4278
4383
  });
4279
4384
  const output = result.output[0];
4280
4385
  const code = output.code;
4281
- await (0, import_promises5.mkdir)(directories.cache, { recursive: true });
4282
- 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);
4283
4388
  debug("Save config file:", style.info(outputFile));
4284
4389
  return import(outputFile);
4285
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
+ };
4286
4446
 
4287
4447
  // src/config.ts
4288
4448
  var importConfig = async (options) => {
@@ -4292,7 +4452,7 @@ var importConfig = async (options) => {
4292
4452
  setRoot(root2);
4293
4453
  debug("CWD:", style.info(root2));
4294
4454
  debug("Import config file");
4295
- const fileName = (0, import_path7.join)(root2, configFile);
4455
+ const fileName = (0, import_path9.join)(root2, configFile);
4296
4456
  const module2 = await importFile(fileName);
4297
4457
  const appConfig = typeof module2.default === "function" ? await module2.default(options) : module2.default;
4298
4458
  debug("Validate config file");
@@ -4318,6 +4478,40 @@ var importConfig = async (options) => {
4318
4478
  credentials
4319
4479
  };
4320
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
+ };
4321
4515
 
4322
4516
  // src/cli/ui/layout/basic.ts
4323
4517
  var br = () => {
@@ -4793,7 +4987,7 @@ var layout = async (cb) => {
4793
4987
  };
4794
4988
 
4795
4989
  // src/cli/ui/complex/builder.ts
4796
- var import_promises6 = require("fs/promises");
4990
+ var import_promises7 = require("fs/promises");
4797
4991
 
4798
4992
  // src/cli/ui/layout/flex-line.ts
4799
4993
  var stripEscapeCode = (str) => {
@@ -4816,7 +5010,7 @@ var flexLine = (term, left, right, reserveSpace = 0) => {
4816
5010
  };
4817
5011
 
4818
5012
  // src/cli/ui/complex/builder.ts
4819
- var import_path10 = require("path");
5013
+ var import_path12 = require("path");
4820
5014
  var assetBuilder = (app) => {
4821
5015
  return async (term) => {
4822
5016
  const assets = [];
@@ -4879,10 +5073,10 @@ var assetBuilder = (app) => {
4879
5073
  try {
4880
5074
  const data = await asset.build({
4881
5075
  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);
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);
4886
5080
  }
4887
5081
  });
4888
5082
  details.set({
@@ -4906,7 +5100,7 @@ var assetBuilder = (app) => {
4906
5100
  };
4907
5101
 
4908
5102
  // src/util/cleanup.ts
4909
- var import_promises7 = require("fs/promises");
5103
+ var import_promises8 = require("fs/promises");
4910
5104
  var cleanUp = async () => {
4911
5105
  debug("Clean up template, cache, and asset files");
4912
5106
  const paths = [
@@ -4915,57 +5109,33 @@ var cleanUp = async () => {
4915
5109
  directories.types,
4916
5110
  directories.template
4917
5111
  ];
4918
- await Promise.all(paths.map((path) => (0, import_promises7.rm)(path, {
5112
+ await Promise.all(paths.map((path) => (0, import_promises8.rm)(path, {
4919
5113
  recursive: true,
4920
5114
  force: true,
4921
5115
  maxRetries: 2
4922
5116
  })));
4923
- await Promise.all(paths.map((path) => (0, import_promises7.mkdir)(path, {
5117
+ await Promise.all(paths.map((path) => (0, import_promises8.mkdir)(path, {
4924
5118
  recursive: true
4925
5119
  })));
4926
5120
  };
4927
5121
 
4928
5122
  // src/cli/ui/complex/template.ts
4929
- var import_promises8 = require("fs/promises");
4930
- var import_path13 = require("path");
5123
+ var import_promises9 = require("fs/promises");
5124
+ var import_path15 = require("path");
4931
5125
  var templateBuilder = (app) => {
4932
5126
  return async (term) => {
4933
5127
  const done = term.out.write(loadingDialog("Building stack templates..."));
4934
5128
  await Promise.all(app.stacks.map(async (stack) => {
4935
5129
  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);
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);
4940
5134
  }));
4941
5135
  done("Done building stack templates");
4942
5136
  };
4943
5137
  };
4944
5138
 
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
5139
  // src/cli/ui/complex/types.ts
4970
5140
  var typesGenerator = (config) => {
4971
5141
  return async (term) => {
@@ -5018,7 +5188,7 @@ var shouldDeployBootstrap = async (client, stack) => {
5018
5188
  // src/formation/client.ts
5019
5189
  var import_client_cloudformation = require("@aws-sdk/client-cloudformation");
5020
5190
  var import_client_s3 = require("@aws-sdk/client-s3");
5021
- var import_change_case13 = require("change-case");
5191
+ var import_change_case14 = require("change-case");
5022
5192
  var StackClient = class {
5023
5193
  constructor(app, account, region, credentials) {
5024
5194
  this.app = app;
@@ -5051,7 +5221,7 @@ var StackClient = class {
5051
5221
  };
5052
5222
  }
5053
5223
  stackName(stackName) {
5054
- return (0, import_change_case13.paramCase)(`${this.app.name}-${stackName}`);
5224
+ return (0, import_change_case14.paramCase)(`${this.app.name}-${stackName}`);
5055
5225
  }
5056
5226
  tags(stack) {
5057
5227
  const tags = [];
@@ -5757,6 +5927,19 @@ var types = (program2) => {
5757
5927
  });
5758
5928
  };
5759
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
+
5760
5943
  // src/cli/program.ts
5761
5944
  var program = new import_commander.Command();
5762
5945
  program.name(logo().join("").replace(/\s+/, ""));
@@ -5778,6 +5961,7 @@ var commands2 = [
5778
5961
  types,
5779
5962
  build,
5780
5963
  deploy,
5964
+ dev,
5781
5965
  secrets,
5782
5966
  test
5783
5967
  // diff,