@awsless/cli 0.0.46-local.7 → 0.0.46-local.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.js +110 -15
  2. package/package.json +14 -14
package/dist/bin.js CHANGED
@@ -150257,6 +150257,16 @@ var bootstrapAwsless = async (props) => {
150257
150257
  // src/config/load/load.ts
150258
150258
  import { basename as basename2, dirname as dirname5, join as join13 } from "path";
150259
150259
 
150260
+ // src/feature/config/schema.ts
150261
+ var ConfigNameSchema = exports_external.string().regex(/^[a-z0-9-]+$/, "Invalid config name");
150262
+ var ConfigsSchema = exports_external.array(ConfigNameSchema).optional().describe("Define the config values for your app.");
150263
+ var ConfigFileSchema = exports_external.record(ConfigNameSchema, exports_external.union([
150264
+ exports_external.string().describe("A committed default value for the local dev environment."),
150265
+ exports_external.object({
150266
+ secret: exports_external.literal(true).describe("Pulled from ssm into memory on local dev boot, never stored locally.")
150267
+ }).describe("A secret config value.")
150268
+ ])).describe("The config values of your app.");
150269
+
150260
150270
  // src/config/schema/config-ref.ts
150261
150271
  var ConfigRefSchema = exports_external.string().regex(/^config:[a-z0-9-]+$/, "Invalid config reference");
150262
150272
  var isConfigRef = (value) => {
@@ -150325,10 +150335,6 @@ var AuthDefaultSchema = exports_external.record(ResourceIdSchema, exports_extern
150325
150335
  }).default({}).describe("Specifies the validity duration for every JWT token.")
150326
150336
  })).default({}).describe("Define the authenticatable users in your app.");
150327
150337
 
150328
- // src/feature/config/schema.ts
150329
- var ConfigNameSchema = exports_external.string().regex(/^[a-z0-9-]+$/, "Invalid config name");
150330
- var ConfigsSchema = exports_external.array(ConfigNameSchema).optional().describe("Define the config values for your app.");
150331
-
150332
150338
  // src/feature/domain/schema.ts
150333
150339
  var DomainNameSchema = exports_external.string().regex(/[a-z\-\_\.]/g, "Invalid domain name").describe("Enter a fully qualified domain name, for example, www.example.com. You can optionally include a trailing dot. If you omit the trailing dot, Amazon Route 53 assumes that the domain name that you specify is fully qualified. This means that Route 53 treats www.example.com (without a trailing dot) and www.example.com. (with a trailing dot) as identical.");
150334
150340
  var DNSTypeSchema = exports_external.enum(["A", "AAAA", "CAA", "CNAME", "DS", "MX", "NAPTR", "NS", "PTR", "SOA", "SPF", "SRV", "TXT"]).describe("The DNS record type.");
@@ -152482,8 +152488,32 @@ var loadAppConfig = async (options) => {
152482
152488
  debug("Validate app config file");
152483
152489
  const app = await validateConfig(AppSchema, appConfig.file, appConfig.data);
152484
152490
  app.stage = options.stage;
152491
+ await loadConfigFile(app, root3, options.stage);
152485
152492
  return app;
152486
152493
  };
152494
+ var loadConfigFile = async (app, root3, stage) => {
152495
+ const ext2 = ["config.json", "config.jsonc", "config.json5"];
152496
+ const files = await glob(ext2, { cwd: root3 });
152497
+ const file2 = ext2.find((name) => files.includes(name));
152498
+ if (!file2) {
152499
+ return;
152500
+ }
152501
+ debug("Load config file:", color2.info(file2));
152502
+ const config = await readConfigWithStage(join13(root3, file2), stage);
152503
+ const entries2 = await validateConfig(ConfigFileSchema, config.file, config.data);
152504
+ const defaults2 = {};
152505
+ const secrets = [];
152506
+ for (const [name, value] of Object.entries(entries2)) {
152507
+ if (typeof value === "string") {
152508
+ defaults2[name] = value;
152509
+ } else {
152510
+ secrets.push(name);
152511
+ }
152512
+ }
152513
+ app.configs = [...new Set([...app.configs ?? [], ...Object.keys(entries2)])].sort();
152514
+ app.configDefaults = defaults2;
152515
+ app.configSecrets = secrets;
152516
+ };
152487
152517
  var loadStackConfigs = async (options) => {
152488
152518
  debug("Load stacks config files");
152489
152519
  const ext2 = "{json,jsonc,json5}";
@@ -154771,6 +154801,9 @@ var createSsmServer = (props) => {
154771
154801
  let closeServer;
154772
154802
  let log;
154773
154803
  const warned2 = new Set;
154804
+ let defaults2 = {};
154805
+ let pulled = {};
154806
+ let secrets = new Set;
154774
154807
  const loadValues = async () => {
154775
154808
  try {
154776
154809
  return JSON.parse(await readFile12(props.file, "utf8"));
@@ -154782,6 +154815,11 @@ var createSsmServer = (props) => {
154782
154815
  connect(logFn) {
154783
154816
  log = logFn;
154784
154817
  },
154818
+ setValues(next) {
154819
+ defaults2 = next.defaults;
154820
+ pulled = next.pulled;
154821
+ secrets = next.secrets;
154822
+ },
154785
154823
  async listen(port = 0) {
154786
154824
  server = createServer2((req, res) => {
154787
154825
  const chunks = [];
@@ -154801,12 +154839,12 @@ var createSsmServer = (props) => {
154801
154839
  const parameters = [];
154802
154840
  for (const name of Names ?? []) {
154803
154841
  const key = name.split("/").at(-1);
154804
- const value = values[key];
154842
+ const value = values[key] ?? defaults2[key] ?? pulled[key];
154805
154843
  if (typeof value === "string") {
154806
154844
  parameters.push({ Name: name, Type: "SecureString", Value: value });
154807
154845
  } else if (!warned2.has(key)) {
154808
154846
  warned2.add(key);
154809
- log?.(`The "${key}" config has no local value yet. Set it on the dashboard or in ${props.file}`);
154847
+ log?.(secrets.has(key) ? `The "${key}" config secret has no value - the ssm pull didn't provide one. Set it with "awsless config set ${key}" or override it on the dashboard.` : `The "${key}" config has no local value yet. Set it on the dashboard or add a default in config.jsonc`);
154810
154848
  }
154811
154849
  }
154812
154850
  res.writeHead(200, { "content-type": "application/x-amz-json-1.1" });
@@ -154992,9 +155030,10 @@ var configFeature = defineFeature({
154992
155030
  if (names.size === 0) {
154993
155031
  return;
154994
155032
  }
155033
+ const secrets = new Set(ctx.appConfig.configSecrets ?? []);
154995
155034
  for (const name of names) {
154996
155035
  ctx.addEnv(`CONFIG_${constantCase(name)}`, name);
154997
- ctx.registerResource({ kind: "config", id: name });
155036
+ ctx.registerResource({ kind: "config", id: name, detail: secrets.has(name) ? "secret" : "" });
154998
155037
  }
154999
155038
  const file2 = join18(directories.output, "local", "config.json");
155000
155039
  const { server, port } = await ctx.keep("shim:ssm", file2, async () => {
@@ -155003,6 +155042,38 @@ var configFeature = defineFeature({
155003
155042
  return { value: { server: server2, port: port2 }, stop: () => server2.stop() };
155004
155043
  });
155005
155044
  ctx.addEnv("AWS_ENDPOINT_URL_SSM", `http://127.0.0.1:${port}`);
155045
+ let pulled = {};
155046
+ if (secrets.size > 0) {
155047
+ pulled = await ctx.keep("config:pull", [...secrets].sort().join(","), async () => {
155048
+ const values = {};
155049
+ try {
155050
+ ctx.log(`Pulling ${secrets.size} config secret${secrets.size === 1 ? "" : "s"} from SSM...`);
155051
+ const credentials2 = await getCredentials(ctx.appConfig.profile);
155052
+ const store = new SsmStore({ credentials: credentials2, appConfig: ctx.appConfig });
155053
+ let timer;
155054
+ const all5 = await Promise.race([
155055
+ store.list(),
155056
+ new Promise((_3, reject) => {
155057
+ timer = setTimeout(() => reject(new Error("the pull timed out after 15s")), 15000);
155058
+ })
155059
+ ]).finally(() => clearTimeout(timer));
155060
+ for (const name of secrets) {
155061
+ if (typeof all5[name] === "string") {
155062
+ values[name] = all5[name];
155063
+ }
155064
+ }
155065
+ } catch (error3) {
155066
+ debug("Config secret pull failed", error3);
155067
+ ctx.log(`Couldn't pull the config secrets from SSM (${error3 instanceof Error ? error3.message : String(error3)}) - secret-backed features will fail when called.`);
155068
+ }
155069
+ return { value: values, stop: () => {} };
155070
+ });
155071
+ }
155072
+ server.setValues({
155073
+ defaults: ctx.appConfig.configDefaults ?? {},
155074
+ pulled,
155075
+ secrets
155076
+ });
155006
155077
  ctx.restartOnChange(file2);
155007
155078
  ctx.registerServer({
155008
155079
  name: "config",
@@ -165788,7 +165859,7 @@ var watchConfig = async (options, resolve5, reject) => {
165788
165859
  await loadAppConfig(options);
165789
165860
  debug("Start watching...");
165790
165861
  const ext2 = "{json,jsonc,json5}";
165791
- const watcher = $watch([`app.${ext2}`, `**/stack.${ext2}`, `**/*.stack.${ext2}`], {
165862
+ const watcher = $watch([`app.${ext2}`, `config.${ext2}`, `**/stack.${ext2}`, `**/*.stack.${ext2}`], {
165792
165863
  cwd: directories.root,
165793
165864
  ignored: ["**/node_modules/**", "**/dist/**"],
165794
165865
  awaitWriteFinish: true
@@ -167120,12 +167191,25 @@ const configPanel = async (main) => {
167120
167191
  const names = [...new Set(state.resources.filter(r => r.kind === 'config').map(r => r.id))].sort()
167121
167192
  const data = await api('/api/config')
167122
167193
  const values = data.values ?? {}
167194
+ const defaults = data.defaults ?? {}
167195
+ const secrets = new Set(data.secrets ?? [])
167123
167196
 
167124
167197
  const inputs = new Map()
167125
167198
  const form = $('div', { className: 'config-form' })
167126
167199
 
167127
167200
  for (const name of names) {
167128
- const input = $('input', { value: values[name] ?? '', placeholder: 'not set', spellcheck: false })
167201
+ // An empty input falls through to the committed default or the
167202
+ // pulled ssm secret - the placeholder shows which one carries.
167203
+ const placeholder = secrets.has(name)
167204
+ ? 'pulled from ssm'
167205
+ : defaults[name] !== undefined ? 'default: ' + defaults[name] : 'not set'
167206
+
167207
+ const input = $('input', {
167208
+ value: values[name] ?? '',
167209
+ placeholder,
167210
+ spellcheck: false,
167211
+ ...(secrets.has(name) ? { type: 'password' } : {}),
167212
+ })
167129
167213
  inputs.set(name, input)
167130
167214
  form.append($('label', { className: 'field' }, [$('span', { className: 'name' }, name), input]))
167131
167215
  }
@@ -167567,7 +167651,14 @@ var createDashboardServer = (props) => {
167567
167651
  try {
167568
167652
  values = JSON.parse(await readFile21(props.configFile, "utf8"));
167569
167653
  } catch (_4) {}
167570
- return { status: 200, body: JSON.stringify({ values }) };
167654
+ return {
167655
+ status: 200,
167656
+ body: JSON.stringify({
167657
+ values,
167658
+ defaults: props.configMeta?.defaults ?? {},
167659
+ secrets: props.configMeta?.secrets ?? []
167660
+ })
167661
+ };
167571
167662
  }
167572
167663
  return { status: 404, body: JSON.stringify({ error: `Unknown dashboard path: ${url.pathname}` }) };
167573
167664
  };
@@ -167990,6 +168081,10 @@ var startDev = async (props) => {
167990
168081
  env: env4,
167991
168082
  storeRoot: join53(directories.output, "local", "store"),
167992
168083
  configFile: join53(directories.output, "local", "config.json"),
168084
+ configMeta: {
168085
+ defaults: appConfig.configDefaults ?? {},
168086
+ secrets: appConfig.configSecrets ?? []
168087
+ },
167993
168088
  events: dev.events
167994
168089
  });
167995
168090
  dashboard.connect(dispatch);
@@ -168250,7 +168345,7 @@ import { DynamoDBClient as DynamoDBClient6, dynamoDBClient } from "@awsless/dyna
168250
168345
 
168251
168346
  // ../../node_modules/.pnpm/@aws-sdk+client-iot-data-plane@3.1023.0_aws-crt@1.30.0_supports-color@8.1.1_/node_modules/@aws-sdk/client-iot-data-plane/dist-es/IoTDataPlaneClient.js
168252
168347
  var import_core50 = __toESM(require_dist_cjs2(), 1);
168253
- var import_schema67 = __toESM(require_schema(), 1);
168348
+ var import_schema68 = __toESM(require_schema(), 1);
168254
168349
 
168255
168350
  // ../../node_modules/.pnpm/@aws-sdk+client-iot-data-plane@3.1023.0_aws-crt@1.30.0_supports-color@8.1.1_/node_modules/@aws-sdk/client-iot-data-plane/dist-es/auth/httpAuthSchemeProvider.js
168256
168351
  var import_httpAuthSchemes4 = __toESM(require_httpAuthSchemes(), 1);
@@ -168456,7 +168551,7 @@ var defaultEndpointResolver3 = (endpointParams, context = {}) => {
168456
168551
  customEndpointFunctions.aws = awsEndpointFunctions;
168457
168552
 
168458
168553
  // ../../node_modules/.pnpm/@aws-sdk+client-iot-data-plane@3.1023.0_aws-crt@1.30.0_supports-color@8.1.1_/node_modules/@aws-sdk/client-iot-data-plane/dist-es/schemas/schemas_0.js
168459
- var import_schema66 = __toESM(require_schema(), 1);
168554
+ var import_schema67 = __toESM(require_schema(), 1);
168460
168555
 
168461
168556
  // ../../node_modules/.pnpm/@aws-sdk+client-iot-data-plane@3.1023.0_aws-crt@1.30.0_supports-color@8.1.1_/node_modules/@aws-sdk/client-iot-data-plane/dist-es/models/IoTDataPlaneServiceException.js
168462
168557
  class IoTDataPlaneServiceException extends ServiceException {
@@ -168686,10 +168781,10 @@ var _xamcd = "x-amz-mqtt5-correlation-data";
168686
168781
  var _xampfi = "x-amz-mqtt5-payload-format-indicator";
168687
168782
  var _xamup = "x-amz-mqtt5-user-properties";
168688
168783
  var n03 = "com.amazonaws.iotdataplane";
168689
- var _s_registry3 = import_schema66.TypeRegistry.for(_s3);
168784
+ var _s_registry3 = import_schema67.TypeRegistry.for(_s3);
168690
168785
  var IoTDataPlaneServiceException$ = [-3, _s3, "IoTDataPlaneServiceException", 0, [], []];
168691
168786
  _s_registry3.registerError(IoTDataPlaneServiceException$, IoTDataPlaneServiceException);
168692
- var n0_registry3 = import_schema66.TypeRegistry.for(n03);
168787
+ var n0_registry3 = import_schema67.TypeRegistry.for(n03);
168693
168788
  var ConflictException$ = [
168694
168789
  -3,
168695
168790
  n03,
@@ -169125,7 +169220,7 @@ class IoTDataPlaneClient extends Client {
169125
169220
  const _config_7 = resolveHttpAuthSchemeConfig3(_config_6);
169126
169221
  const _config_8 = resolveRuntimeExtensions3(_config_7, configuration?.extensions || []);
169127
169222
  this.config = _config_8;
169128
- this.middlewareStack.use(import_schema67.getSchemaSerdePlugin(this.config));
169223
+ this.middlewareStack.use(import_schema68.getSchemaSerdePlugin(this.config));
169129
169224
  this.middlewareStack.use(getUserAgentPlugin(this.config));
169130
169225
  this.middlewareStack.use(getRetryPlugin(this.config));
169131
169226
  this.middlewareStack.use(getContentLengthPlugin(this.config));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/cli",
3
- "version": "0.0.46-local.7",
3
+ "version": "0.0.46-local.9",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -43,14 +43,14 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@awsless/big-float": "^0.1.7",
46
- "@awsless/dynamodb": "^0.3.22",
47
- "@awsless/lambda": "^0.0.47",
48
46
  "@awsless/duration": "^0.0.4",
49
47
  "@awsless/json": "^0.0.11",
48
+ "@awsless/dynamodb": "^0.3.22",
50
49
  "@awsless/s3": "^0.0.22",
51
- "awsless": "^0.0.15-local.3",
50
+ "@awsless/lambda": "^0.0.47",
52
51
  "@awsless/weak-cache": "^0.0.1",
53
- "@awsless/validate": "^0.1.7"
52
+ "@awsless/validate": "^0.1.7",
53
+ "awsless": "^0.0.15-local.3"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@aws-sdk/client-cloudformation": "^3.369.0",
@@ -120,25 +120,25 @@
120
120
  "zip-a-folder": "^3.1.6",
121
121
  "zod": "^3.24.2",
122
122
  "zod-to-json-schema": "^3.24.3",
123
+ "@awsless/big-float": "^0.1.7",
123
124
  "@awsless/cloudwatch": "^0.0.1",
124
125
  "@awsless/clui": "^0.0.9",
125
- "@awsless/big-float": "^0.1.7",
126
- "@awsless/dynamodb": "^0.3.22",
127
126
  "@awsless/json": "^0.0.11",
128
127
  "@awsless/lambda": "^0.0.47",
129
- "@awsless/open-search": "^0.0.24",
128
+ "@awsless/iot": "^0.0.5",
130
129
  "@awsless/duration": "^0.0.4",
130
+ "@awsless/open-search": "^0.0.24",
131
131
  "@awsless/redis": "^0.1.13",
132
- "@awsless/size": "^0.0.2",
133
- "@awsless/iot": "^0.0.5",
134
- "@awsless/sqs": "^0.0.24",
135
- "@awsless/ssm": "^0.0.8",
136
- "@awsless/sns": "^0.0.11",
137
132
  "@awsless/s3": "^0.0.22",
133
+ "@awsless/scheduler": "^0.0.5",
134
+ "@awsless/sqs": "^0.0.24",
138
135
  "@awsless/validate": "^0.1.7",
136
+ "@awsless/sns": "^0.0.11",
137
+ "@awsless/ssm": "^0.0.8",
139
138
  "@awsless/weak-cache": "^0.0.1",
139
+ "@awsless/size": "^0.0.2",
140
140
  "awsless": "^0.0.15-local.3",
141
- "@awsless/scheduler": "^0.0.5"
141
+ "@awsless/dynamodb": "^0.3.22"
142
142
  },
143
143
  "scripts": {
144
144
  "test": "bun cli/build-handlers.ts && pnpm vitest",