awscfn 1.3.0 → 1.5.0

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 (55) hide show
  1. package/README.md +26 -1
  2. package/bin/awscfn +288 -20
  3. package/dist/cli/loadTemplateAndParams.d.ts +1 -1
  4. package/dist/cli/loadTemplateAndParams.d.ts.map +1 -1
  5. package/dist/cli/loadTemplateAndParams.js +11 -2
  6. package/dist/cli/loadTemplateAndParams.js.map +1 -1
  7. package/dist/cli/loadTemplateAndParams.spec.d.ts +2 -0
  8. package/dist/cli/loadTemplateAndParams.spec.d.ts.map +1 -0
  9. package/dist/cli/loadTemplateAndParams.spec.js +14 -0
  10. package/dist/cli/loadTemplateAndParams.spec.js.map +1 -0
  11. package/dist/cli/parseParamOverrides.d.ts +9 -0
  12. package/dist/cli/parseParamOverrides.d.ts.map +1 -0
  13. package/dist/cli/parseParamOverrides.js +26 -0
  14. package/dist/cli/parseParamOverrides.js.map +1 -0
  15. package/dist/cli/parseParamOverrides.spec.d.ts +2 -0
  16. package/dist/cli/parseParamOverrides.spec.d.ts.map +1 -0
  17. package/dist/cli/parseParamOverrides.spec.js +16 -0
  18. package/dist/cli/parseParamOverrides.spec.js.map +1 -0
  19. package/dist/createStack.d.ts +1 -1
  20. package/dist/createStack.d.ts.map +1 -1
  21. package/dist/createStack.js +2 -2
  22. package/dist/createStack.js.map +1 -1
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +3 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/inspectStack.d.ts +6 -0
  28. package/dist/inspectStack.d.ts.map +1 -0
  29. package/dist/inspectStack.js +187 -0
  30. package/dist/inspectStack.js.map +1 -0
  31. package/dist/lib/cfn/getStackTemplate.d.ts +2 -0
  32. package/dist/lib/cfn/getStackTemplate.d.ts.map +1 -0
  33. package/dist/lib/cfn/getStackTemplate.js +30 -0
  34. package/dist/lib/cfn/getStackTemplate.js.map +1 -0
  35. package/dist/lib/cfn/index.d.ts +2 -0
  36. package/dist/lib/cfn/index.d.ts.map +1 -1
  37. package/dist/lib/cfn/index.js +2 -0
  38. package/dist/lib/cfn/index.js.map +1 -1
  39. package/dist/lib/cfn/listStackEvents.d.ts +3 -0
  40. package/dist/lib/cfn/listStackEvents.d.ts.map +1 -0
  41. package/dist/lib/cfn/listStackEvents.js +26 -0
  42. package/dist/lib/cfn/listStackEvents.js.map +1 -0
  43. package/dist/lib/viewText.d.ts +5 -0
  44. package/dist/lib/viewText.d.ts.map +1 -0
  45. package/dist/lib/viewText.js +57 -0
  46. package/dist/lib/viewText.js.map +1 -0
  47. package/dist/previewStack.d.ts +1 -1
  48. package/dist/previewStack.d.ts.map +1 -1
  49. package/dist/previewStack.js +2 -2
  50. package/dist/previewStack.js.map +1 -1
  51. package/dist/updateStack.d.ts +1 -1
  52. package/dist/updateStack.d.ts.map +1 -1
  53. package/dist/updateStack.js +2 -2
  54. package/dist/updateStack.js.map +1 -1
  55. package/package.json +1 -1
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
10
10
  [![AutoRel](https://img.shields.io/badge/%F0%9F%9A%80%20AutoRel-2D4DDE)](https://github.com/mhweiner/autorel)
11
11
 
12
- Deploy CloudFormation stacks without the usual suffering.
12
+ Deploy CloudFormation stacks with confidence.
13
13
 
14
14
  ## Why awscfn?
15
15
 
@@ -104,6 +104,28 @@ List all CloudFormation stacks in the current region (name, status, creation dat
104
104
  awscfn list-stacks
105
105
  ```
106
106
 
107
+ ### 🔎 inspect-stack
108
+
109
+ Inspect a **deployed** stack in a **read-only pager view** (TUI-like), including:
110
+
111
+ - full deployed template body
112
+ - current parameters and outputs
113
+ - stack metadata (raw JSON details)
114
+ - event timeline (chronological)
115
+ - failure events and likely root-cause errors
116
+
117
+ ```bash
118
+ awscfn inspect-stack -n <STACK_NAME>
119
+ ```
120
+
121
+ | Flag | Description |
122
+ |------|-------------|
123
+ | `--name`, `-n` | Stack name |
124
+ | `--events`, `-e` | Max stack events to fetch (`0` = all available events). Default `500` |
125
+ | `--pager` / `--no-pager` | Use a view-only pager (default true). Disable to print directly |
126
+
127
+ This command performs read-only CloudFormation API calls (`DescribeStacks`, `GetTemplate`, `DescribeStackEvents`) and makes no stack changes.
128
+
107
129
  ### 🚀 create-stack
108
130
 
109
131
  ```bash
@@ -115,6 +137,7 @@ awscfn create-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
115
137
  | `--name`, `-n` | Stack name |
116
138
  | `--template`, `-t` | CloudFormation template file |
117
139
  | `--params`, `-p` | Parameters file (YAML) |
140
+ | `--set`, `-s` | Override one or more parameters (repeatable `Key=Value`) |
118
141
 
119
142
  ### ⬆️ update-stack
120
143
 
@@ -127,6 +150,7 @@ awscfn update-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
127
150
  | `--name`, `-n` | Stack name |
128
151
  | `--template`, `-t` | CloudFormation template file |
129
152
  | `--params`, `-p` | Parameters file (YAML) |
153
+ | `--set`, `-s` | Override one or more parameters (repeatable `Key=Value`). You can omit `--params` to override only specific values on an existing stack. |
130
154
  | `--create` | If the stack doesn't exist, create it (instead of erroring) |
131
155
  | `-m` | Shorthand for `--create` |
132
156
 
@@ -148,6 +172,7 @@ awscfn preview-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
148
172
  | `--name`, `-n` | Stack name |
149
173
  | `--template`, `-t` | CloudFormation template file |
150
174
  | `--params`, `-p` | Parameters file (YAML) |
175
+ | `--set`, `-s` | Override one or more parameters (repeatable `Key=Value`) |
151
176
 
152
177
  Use this to review Add / Modify / Remove actions (and replacement hints) before running **`create-stack`** or **`update-stack`**.
153
178
 
package/bin/awscfn CHANGED
@@ -1,12 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const fs = require('fs');
4
+ const os = require('os');
4
5
  const path = require('path');
6
+ const { spawnSync } = require('node:child_process');
5
7
  const yargs = require('yargs');
6
8
 
7
9
  const { createStack } = require('../dist/createStack');
8
10
  const { deleteStack } = require('../dist/deleteStack');
9
11
  const { listStacks } = require('../dist/listStacks');
12
+ const { inspectStack } = require('../dist/inspectStack');
10
13
  const { previewStack } = require('../dist/previewStack');
11
14
  const { redeployStack } = require('../dist/redeployStack');
12
15
  const { updateStack } = require('../dist/updateStack');
@@ -16,6 +19,9 @@ const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'
16
19
  const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
17
20
 
18
21
  const FILE_FLAGS = ['--template', '--params', '-t', '-p'];
22
+ const ASCII_LOGO = [
23
+ 'awscfn',
24
+ ];
19
25
 
20
26
  function completeFile(current) {
21
27
  const dir = path.dirname(current) || '.';
@@ -49,6 +55,65 @@ function logError(msg) {
49
55
  console.log(`\x1b[31mError: ${msg}\x1b[0m`);
50
56
  }
51
57
 
58
+ function maybeColorize(text, colorCode) {
59
+ if (!process.stdout.isTTY || process.env.NO_COLOR) {
60
+ return text;
61
+ }
62
+ return `${colorCode}${text}\x1b[0m`;
63
+ }
64
+
65
+ function runImageCommand(command, args) {
66
+ const result = spawnSync(command, args, { stdio: 'inherit' });
67
+ return !result.error && result.status === 0;
68
+ }
69
+
70
+ function tryPrintTerminalLogo() {
71
+ if (!process.stdout.isTTY || process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true') {
72
+ return false;
73
+ }
74
+
75
+ if (process.env.TERM_PROGRAM === 'vscode') {
76
+ return false;
77
+ }
78
+
79
+ const logoPath = path.resolve(__dirname, '../docs/awscfn-logo-light.svg');
80
+ if (!fs.existsSync(logoPath)) {
81
+ return false;
82
+ }
83
+
84
+ // Try native terminal image commands (best effort).
85
+ if (process.env.WEZTERM_PANE && runImageCommand('wezterm', ['imgcat', '--width', '40%', logoPath])) {
86
+ return true;
87
+ }
88
+
89
+ if (process.env.KITTY_WINDOW_ID && runImageCommand('kitty', ['+kitten', 'icat', '--align', 'left', logoPath])) {
90
+ return true;
91
+ }
92
+
93
+ if (process.env.ITERM_SESSION_ID && runImageCommand('imgcat', [logoPath])) {
94
+ return true;
95
+ }
96
+
97
+ return false;
98
+ }
99
+
100
+ function printLandingHeader() {
101
+ const boldWhite = '\x1b[1;37m';
102
+ const gray = '\x1b[90m';
103
+ const tagline = 'Deploy CloudFormation stacks with confidence.';
104
+ const hr = maybeColorize('─'.repeat(tagline.length), gray);
105
+
106
+ if (!tryPrintTerminalLogo()) {
107
+ console.log(maybeColorize(ASCII_LOGO.join('\n'), boldWhite));
108
+ }
109
+
110
+ console.log(hr);
111
+ console.log(tagline);
112
+ console.log(hr);
113
+ console.log(maybeColorize('Quick start: awscfn list-stacks | awscfn inspect-stack -n <stack-name>', gray));
114
+ console.log('');
115
+ }
116
+
52
117
  function logErrorDetails(data) {
53
118
  if (data) {
54
119
  console.log('\nError details:');
@@ -56,13 +121,162 @@ function logErrorDetails(data) {
56
121
  }
57
122
  }
58
123
 
124
+ function getProfileAwareCommand(baseCommand) {
125
+ const profile = process.env.AWS_PROFILE;
126
+ if (!profile) return baseCommand;
127
+
128
+ return `${baseCommand} --profile ${profile}`;
129
+ }
130
+
131
+ function getAwsConfigPath() {
132
+ if (process.env.AWS_CONFIG_FILE) return process.env.AWS_CONFIG_FILE;
133
+
134
+ return path.join(os.homedir(), '.aws', 'config');
135
+ }
136
+
137
+ function getAwsCredentialsPath() {
138
+ if (process.env.AWS_SHARED_CREDENTIALS_FILE) return process.env.AWS_SHARED_CREDENTIALS_FILE;
139
+
140
+ return path.join(os.homedir(), '.aws', 'credentials');
141
+ }
142
+
143
+ function readIniSections(filePath) {
144
+ try {
145
+ const content = fs.readFileSync(filePath, 'utf8');
146
+
147
+ return content
148
+ .split('\n')
149
+ .map((line) => line.trim())
150
+ .filter((line) => line.startsWith('[') && line.endsWith(']'))
151
+ .map((line) => line.slice(1, -1).trim());
152
+ } catch {
153
+ return [];
154
+ }
155
+ }
156
+
157
+ function getConfiguredProfiles() {
158
+ const configSections = readIniSections(getAwsConfigPath())
159
+ .map((section) => section.startsWith('profile ') ? section.slice('profile '.length) : section);
160
+ const credentialSections = readIniSections(getAwsCredentialsPath());
161
+
162
+ return new Set([...configSections, ...credentialSections]);
163
+ }
164
+
165
+ function hasCredentialHints() {
166
+ if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
167
+ return true;
168
+ }
169
+
170
+ const configuredProfiles = getConfiguredProfiles();
171
+ const requestedProfile = process.env.AWS_PROFILE;
172
+
173
+ if (requestedProfile) return configuredProfiles.has(requestedProfile);
174
+
175
+ return configuredProfiles.has('default');
176
+ }
177
+
178
+ function formatRegionOnlyHelp() {
179
+ const configureCmd = getProfileAwareCommand('aws configure');
180
+ const showRegionCmd = getProfileAwareCommand('aws configure get region');
181
+
182
+ return [
183
+ 'AWS region is not configured.',
184
+ [
185
+ 'Set a region:',
186
+ ' • export AWS_REGION=us-east-1',
187
+ ` • ${configureCmd}`,
188
+ ].join('\n'),
189
+ [
190
+ 'Check current region:',
191
+ ` • ${showRegionCmd}`,
192
+ ].join('\n'),
193
+ 'Tip: if you use named profiles, set AWS_PROFILE first.',
194
+ ].join('\n\n');
195
+ }
196
+
197
+ function formatAuthSetupHelp(profileMissing) {
198
+ const profile = process.env.AWS_PROFILE;
199
+ const showRegionCmd = getProfileAwareCommand('aws configure get region');
200
+ const configureSsoCmd = getProfileAwareCommand('aws configure sso');
201
+ const ssoLoginCmd = getProfileAwareCommand('aws sso login');
202
+ const stsCheckCmd = getProfileAwareCommand('aws sts get-caller-identity');
203
+ const configureCmd = getProfileAwareCommand('aws configure');
204
+ const profileHint = profile ? `Using AWS profile '${profile}'.` : 'Using default AWS profile.';
205
+
206
+ const profileSection = profileMissing && profile
207
+ ? [
208
+ `Profile '${profile}' was not found.`,
209
+ `Create it first: ${configureSsoCmd}`,
210
+ ].join('\n')
211
+ : profileHint;
212
+
213
+ return [
214
+ 'AWS authentication is not configured for this command yet.',
215
+ profileSection,
216
+ 'Choose one authentication method:',
217
+ [
218
+ 'AWS SSO:',
219
+ ` • ${configureSsoCmd}`,
220
+ ` • ${ssoLoginCmd}`,
221
+ ].join('\n'),
222
+ [
223
+ 'Access keys:',
224
+ ` • ${configureCmd} # adds keys + default region`,
225
+ ].join('\n'),
226
+ [
227
+ 'Then verify identity:',
228
+ ` • ${stsCheckCmd}`,
229
+ ].join('\n'),
230
+ [
231
+ 'If region is still missing:',
232
+ ' • export AWS_REGION=us-east-1',
233
+ ` • ${showRegionCmd}`,
234
+ ].join('\n'),
235
+ ].filter(Boolean).join('\n\n');
236
+ }
237
+
238
+ function formatAuthorizationHelp() {
239
+ const stsCheckCmd = getProfileAwareCommand('aws sts get-caller-identity');
240
+
241
+ return [
242
+ 'AWS authentication succeeded, but this identity does not have enough permissions.',
243
+ [
244
+ 'Confirm which identity is active:',
245
+ ` • ${stsCheckCmd}`,
246
+ ].join('\n'),
247
+ 'Then ask for the required CloudFormation permissions for this account/role.',
248
+ ].join('\n\n');
249
+ }
250
+
59
251
  function clarifyAwsError(msg) {
60
- if (/region\s+is\s+missing|configuration.*region|Missing required key 'region'/i.test(msg)) {
61
- return 'AWS region is not set. Set AWS_REGION or AWS_DEFAULT_REGION, or run `aws configure` (or `aws configure sso` if your org uses SSO).';
252
+ const isRegionMissing = /region\s+is\s+missing|configuration.*region|Missing required key 'region'/i.test(msg);
253
+ const isCredentialsMissing = /Unable to locate credentials|Could not load credentials|NoCredentialProviders/i.test(msg)
254
+ || /Token is expired|ExpiredToken|security token included in the request is expired/i.test(msg)
255
+ || /sso.*expired|refresh failed|SSO session.*invalid|aws sso login/i.test(msg)
256
+ || /resolved credential object is not valid|credential.*could not be loaded/i.test(msg);
257
+ const requestedProfile = process.env.AWS_PROFILE;
258
+ const requestedProfileMissing = Boolean(
259
+ requestedProfile && !getConfiguredProfiles().has(requestedProfile),
260
+ );
261
+ const isProfileMissing = /config profile .* could not be found|profile.*not found/i.test(msg)
262
+ || requestedProfileMissing;
263
+
264
+ if (isRegionMissing && hasCredentialHints() && !isProfileMissing) {
265
+ return formatRegionOnlyHelp();
62
266
  }
63
- if (/credentials|Unable to locate credentials|Token is expired/i.test(msg)) {
64
- return 'AWS credentials not found or expired. Set AWS_PROFILE, AWS_ACCESS_KEY_ID/secret, or run `aws configure` (or `aws configure sso` if your org uses SSO).';
267
+
268
+ if (
269
+ isRegionMissing
270
+ || isCredentialsMissing
271
+ || isProfileMissing
272
+ ) {
273
+ return formatAuthSetupHelp(isProfileMissing);
274
+ }
275
+
276
+ if (/AccessDenied|UnauthorizedOperation|is not authorized to perform|AccessDeniedException/i.test(msg)) {
277
+ return formatAuthorizationHelp();
65
278
  }
279
+
66
280
  return msg;
67
281
  }
68
282
 
@@ -70,11 +284,17 @@ async function runCommand(fn) {
70
284
  try {
71
285
  await fn();
72
286
  } catch (err) {
73
- const message = clarifyAwsError(err.message);
74
- logError(message);
75
- if (message !== err.message) {
76
- console.log(`\x1b[90m(original: ${err.message})\x1b[0m`);
287
+ const originalError = err?.message || String(err);
288
+ const message = clarifyAwsError(originalError);
289
+
290
+ logError(originalError);
291
+
292
+ if (message !== originalError) {
293
+ console.log('');
294
+ console.log(maybeColorize('Suggested next steps:', '\x1b[36m'));
295
+ console.log(message);
77
296
  }
297
+
78
298
  if (getOutputConfig().verbose) {
79
299
  logErrorDetails(err.data);
80
300
  }
@@ -91,6 +311,16 @@ const templateOpt = {
91
311
  const paramsOpt = {
92
312
  params: { type: 'string', alias: 'p', describe: 'Parameters file (YAML). Optional; omit to use template defaults.', demandOption: false },
93
313
  };
314
+ const setOpt = {
315
+ set: {
316
+ type: 'string',
317
+ alias: 's',
318
+ array: true,
319
+ describe: 'Override one or more parameters (repeatable). Format: Key=Value',
320
+ demandOption: false,
321
+ default: [],
322
+ },
323
+ };
94
324
  const createIfMissingOpt = {
95
325
  create: {
96
326
  type: 'boolean',
@@ -103,8 +333,31 @@ const createIfMissingOpt = {
103
333
  const confirmOpt = {
104
334
  confirm: { type: 'string', alias: 'c', describe: 'Repeat stack name to confirm deletion', demandOption: true },
105
335
  };
336
+ const eventsLimitOpt = {
337
+ events: {
338
+ type: 'number',
339
+ alias: 'e',
340
+ describe: 'Max stack events to fetch (0 means all available events)',
341
+ demandOption: false,
342
+ default: 500,
343
+ },
344
+ };
345
+ const pagerOpt = {
346
+ pager: {
347
+ type: 'boolean',
348
+ describe: 'Open output in a view-only pager (use --no-pager to print directly)',
349
+ demandOption: false,
350
+ default: true,
351
+ },
352
+ };
106
353
 
107
- yargs
354
+ const cli = yargs
355
+ .scriptName('awscfn')
356
+ .usage('Usage:\n $0 <command> [options]')
357
+ .example('$0 list-stacks', 'List active stacks in the current AWS region')
358
+ .example('$0 inspect-stack -n my-stack', 'Open a read-only stack inspection view')
359
+ .example('$0 update-stack -n my-stack -t ./template.yaml -p ./params.yaml', 'Update an existing stack')
360
+ .epilog('Tip: run `awscfn <command> --help` for command-specific help.')
108
361
  .option('ci', {
109
362
  type: 'boolean',
110
363
  alias: 'C',
@@ -141,9 +394,9 @@ yargs
141
394
  .command(
142
395
  'create-stack',
143
396
  'Create a CloudFormation stack',
144
- (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt }),
145
- ({ name, template, params }) => {
146
- runCommand(() => createStack(name, template, params));
397
+ (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt, ...setOpt }),
398
+ ({ name, template, params, set }) => {
399
+ runCommand(() => createStack(name, template, params, require('../dist/cli/parseParamOverrides').parseParamOverrides(set).overrides));
147
400
  }
148
401
  )
149
402
  .command(
@@ -165,17 +418,25 @@ yargs
165
418
  .command(
166
419
  'update-stack',
167
420
  'Update a CloudFormation stack',
168
- (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt, ...createIfMissingOpt }),
169
- ({ name, template, params, create }) => {
170
- runCommand(() => updateStack(name, template, params, Boolean(create)));
421
+ (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt, ...createIfMissingOpt, ...setOpt }),
422
+ ({ name, template, params, create, set }) => {
423
+ runCommand(() => updateStack(name, template, params, Boolean(create), require('../dist/cli/parseParamOverrides').parseParamOverrides(set).overrides));
171
424
  }
172
425
  )
173
426
  .command(
174
427
  'preview-stack',
175
428
  'Preview changes without deploying (change set only)',
176
- (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt }),
177
- ({ name, template, params }) => {
178
- runCommand(() => previewStack(name, template, params));
429
+ (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt, ...setOpt }),
430
+ ({ name, template, params, set }) => {
431
+ runCommand(() => previewStack(name, template, params, require('../dist/cli/parseParamOverrides').parseParamOverrides(set).overrides));
432
+ }
433
+ )
434
+ .command(
435
+ 'inspect-stack',
436
+ 'Inspect a deployed stack in a read-only pager view',
437
+ (cmd) => cmd.options({ ...nameOpt, ...eventsLimitOpt, ...pagerOpt }),
438
+ ({ name, events, pager }) => {
439
+ runCommand(() => inspectStack(name, { eventsLimit: Number(events), usePager: Boolean(pager) }));
179
440
  }
180
441
  )
181
442
  .completion(
@@ -200,5 +461,12 @@ yargs
200
461
  .help()
201
462
  .alias('h', 'help')
202
463
  .version(pkg.version)
203
- .alias('v', 'version')
204
- .argv;
464
+ .alias('v', 'version');
465
+
466
+ if (process.argv.length <= 2) {
467
+ printLandingHeader();
468
+ cli.showHelp();
469
+ process.exit(0);
470
+ }
471
+
472
+ cli.argv;
@@ -6,5 +6,5 @@ export interface TemplateAndParams {
6
6
  * Load template from file and optional params. If no params file is given, uses {}.
7
7
  * CloudFormation will error if a required parameter has no default.
8
8
  */
9
- export declare function loadTemplateAndParams(templatePath: string, paramsPath: string | undefined): Promise<TemplateAndParams>;
9
+ export declare function loadTemplateAndParams(templatePath: string, paramsPath: string | undefined, overrides?: Record<string, string>): Promise<TemplateAndParams>;
10
10
  //# sourceMappingURL=loadTemplateAndParams.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadTemplateAndParams.d.ts","sourceRoot":"","sources":["../../src/cli/loadTemplateAndParams.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACvC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAS5B"}
1
+ {"version":3,"file":"loadTemplateAndParams.d.ts","sourceRoot":"","sources":["../../src/cli/loadTemplateAndParams.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACvC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAwB5B"}
@@ -8,11 +8,20 @@ const templateHasParameters_1 = require("../lib/templateHasParameters");
8
8
  * Load template from file and optional params. If no params file is given, uses {}.
9
9
  * CloudFormation will error if a required parameter has no default.
10
10
  */
11
- async function loadTemplateAndParams(templatePath, paramsPath) {
11
+ async function loadTemplateAndParams(templatePath, paramsPath, overrides) {
12
12
  const template = (0, node_fs_1.readFileSync)(templatePath, 'utf-8');
13
- const params = (paramsPath && (0, templateHasParameters_1.templateHasParameters)(template))
13
+ const hasParameters = (0, templateHasParameters_1.templateHasParameters)(template);
14
+ const fileParams = (paramsPath && (0, templateHasParameters_1.templateHasParameters)(template))
14
15
  ? (await (0, getParamsFromFile_1.getParamsFromFile)(paramsPath))
15
16
  : {};
17
+ if (!hasParameters && overrides && Object.keys(overrides).length > 0) {
18
+ throw new Error('Template does not declare Parameters, but --set was provided. '
19
+ + 'Remove --set or add a Parameters section to the template.');
20
+ }
21
+ const params = {
22
+ ...fileParams,
23
+ ...(overrides ?? {}),
24
+ };
16
25
  return { template, params };
17
26
  }
18
27
  //# sourceMappingURL=loadTemplateAndParams.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadTemplateAndParams.js","sourceRoot":"","sources":["../../src/cli/loadTemplateAndParams.ts"],"names":[],"mappings":";;AAaA,sDAYC;AAzBD,qCAAqC;AACrC,gEAA2D;AAC3D,wEAAmE;AAOnE;;;GAGG;AACI,KAAK,UAAU,qBAAqB,CACvC,YAAoB,EACpB,UAA8B;IAG9B,MAAM,QAAQ,GAAG,IAAA,sBAAY,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,CAAC,UAAU,IAAI,IAAA,6CAAqB,EAAC,QAAQ,CAAC,CAAC;QAC1D,CAAC,CAAE,CAAC,MAAM,IAAA,qCAAiB,EAAC,UAAU,CAAC,CAA6B;QACpE,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAC,CAAC;AAE9B,CAAC"}
1
+ {"version":3,"file":"loadTemplateAndParams.js","sourceRoot":"","sources":["../../src/cli/loadTemplateAndParams.ts"],"names":[],"mappings":";;AAaA,sDA4BC;AAzCD,qCAAqC;AACrC,gEAA2D;AAC3D,wEAAmE;AAOnE;;;GAGG;AACI,KAAK,UAAU,qBAAqB,CACvC,YAAoB,EACpB,UAA8B,EAC9B,SAAkC;IAGlC,MAAM,QAAQ,GAAG,IAAA,sBAAY,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,IAAA,6CAAqB,EAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,CAAC,UAAU,IAAI,IAAA,6CAAqB,EAAC,QAAQ,CAAC,CAAC;QAC9D,CAAC,CAAE,CAAC,MAAM,IAAA,qCAAiB,EAAC,UAAU,CAAC,CAA6B;QACpE,CAAC,CAAC,EAAE,CAAC;IAET,IAAI,CAAC,aAAa,IAAI,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAEnE,MAAM,IAAI,KAAK,CACX,gEAAgE;cAC9D,2DAA2D,CAChE,CAAC;IAEN,CAAC;IAED,MAAM,MAAM,GAAG;QACX,GAAG,UAAU;QACb,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;KACvB,CAAC;IAEF,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAC,CAAC;AAE9B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=loadTemplateAndParams.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadTemplateAndParams.spec.d.ts","sourceRoot":"","sources":["../../src/cli/loadTemplateAndParams.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const kizu_1 = require("kizu");
4
+ const node_fs_1 = require("node:fs");
5
+ const node_os_1 = require("node:os");
6
+ const node_path_1 = require("node:path");
7
+ const loadTemplateAndParams_1 = require("./loadTemplateAndParams");
8
+ (0, kizu_1.test)('loadTemplateAndParams throws when template has no Parameters but overrides provided', async (assert) => {
9
+ const dir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'awscfn-'));
10
+ const templatePath = (0, node_path_1.join)(dir, 'template.yaml');
11
+ (0, node_fs_1.writeFileSync)(templatePath, 'Resources: {}', 'utf-8');
12
+ await assert.throws(() => (0, loadTemplateAndParams_1.loadTemplateAndParams)(templatePath, undefined, { Foo: 'bar' }), /does not declare Parameters/i);
13
+ });
14
+ //# sourceMappingURL=loadTemplateAndParams.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadTemplateAndParams.spec.js","sourceRoot":"","sources":["../../src/cli/loadTemplateAndParams.spec.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAC1B,qCAAmD;AACnD,qCAA+B;AAC/B,yCAA+B;AAC/B,mEAA8D;AAE9D,IAAA,WAAI,EAAC,qFAAqF,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;IAEzG,MAAM,GAAG,GAAG,IAAA,qBAAW,EAAC,IAAA,gBAAI,EAAC,IAAA,gBAAM,GAAE,EAAE,SAAS,CAAC,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,IAAA,gBAAI,EAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAEhD,IAAA,uBAAa,EAAC,YAAY,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;IAEtD,MAAM,MAAM,CAAC,MAAM,CACf,GAAG,EAAE,CAAC,IAAA,6CAAqB,EAAC,YAAY,EAAE,SAAS,EAAE,EAAC,GAAG,EAAE,KAAK,EAAC,CAAC,EAClE,8BAA8B,CACjC,CAAC;AAEN,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface ParamOverrideParseResult {
2
+ overrides: Record<string, string>;
3
+ }
4
+ /**
5
+ * Parse repeatable CLI overrides like:
6
+ * ["Foo=bar", "Env=prod"]
7
+ */
8
+ export declare function parseParamOverrides(values: unknown[] | undefined): ParamOverrideParseResult;
9
+ //# sourceMappingURL=parseParamOverrides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseParamOverrides.d.ts","sourceRoot":"","sources":["../../src/cli/parseParamOverrides.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACrC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,GAAG,wBAAwB,CAyB3F"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseParamOverrides = parseParamOverrides;
4
+ /**
5
+ * Parse repeatable CLI overrides like:
6
+ * ["Foo=bar", "Env=prod"]
7
+ */
8
+ function parseParamOverrides(values) {
9
+ const overrides = {};
10
+ if (!values)
11
+ return { overrides };
12
+ for (const raw of values) {
13
+ if (typeof raw !== 'string')
14
+ throw new Error(`Invalid --set value: ${String(raw)}`);
15
+ const idx = raw.indexOf('=');
16
+ if (idx <= 0)
17
+ throw new Error(`Invalid --set value (expected Key=Value): ${raw}`);
18
+ const key = raw.slice(0, idx).trim();
19
+ const value = raw.slice(idx + 1);
20
+ if (!key)
21
+ throw new Error(`Invalid --set value (empty key): ${raw}`);
22
+ overrides[key] = value;
23
+ }
24
+ return { overrides };
25
+ }
26
+ //# sourceMappingURL=parseParamOverrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseParamOverrides.js","sourceRoot":"","sources":["../../src/cli/parseParamOverrides.ts"],"names":[],"mappings":";;AAQA,kDAyBC;AA7BD;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,MAA6B;IAE7D,MAAM,SAAS,GAA2B,EAAE,CAAC;IAE7C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAC,SAAS,EAAC,CAAC;IAEhC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QAEvB,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEpF,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,GAAG,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,GAAG,EAAE,CAAC,CAAC;QAElF,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAEjC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,EAAE,CAAC,CAAC;QAErE,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAE3B,CAAC;IAED,OAAO,EAAC,SAAS,EAAC,CAAC;AAEvB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parseParamOverrides.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseParamOverrides.spec.d.ts","sourceRoot":"","sources":["../../src/cli/parseParamOverrides.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const kizu_1 = require("kizu");
4
+ const parseParamOverrides_1 = require("./parseParamOverrides");
5
+ (0, kizu_1.test)('parseParamOverrides parses repeated Key=Value pairs', (assert) => {
6
+ const { overrides } = (0, parseParamOverrides_1.parseParamOverrides)(['Foo=bar', 'Env=prod']);
7
+ assert.equal(overrides, { Foo: 'bar', Env: 'prod' });
8
+ });
9
+ (0, kizu_1.test)('parseParamOverrides last value wins for duplicate keys', (assert) => {
10
+ const { overrides } = (0, parseParamOverrides_1.parseParamOverrides)(['Foo=bar', 'Foo=baz']);
11
+ assert.equal(overrides, { Foo: 'baz' });
12
+ });
13
+ (0, kizu_1.test)('parseParamOverrides throws on invalid format', (assert) => {
14
+ assert.throws(() => (0, parseParamOverrides_1.parseParamOverrides)(['NoEquals']), /expected Key=Value/);
15
+ });
16
+ //# sourceMappingURL=parseParamOverrides.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseParamOverrides.spec.js","sourceRoot":"","sources":["../../src/cli/parseParamOverrides.spec.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAC1B,+DAA0D;AAE1D,IAAA,WAAI,EAAC,qDAAqD,EAAE,CAAC,MAAM,EAAE,EAAE;IAEnE,MAAM,EAAC,SAAS,EAAC,GAAG,IAAA,yCAAmB,EAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAEjE,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,EAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAC,CAAC,CAAC;AAEvD,CAAC,CAAC,CAAC;AAEH,IAAA,WAAI,EAAC,wDAAwD,EAAE,CAAC,MAAM,EAAE,EAAE;IAEtE,MAAM,EAAC,SAAS,EAAC,GAAG,IAAA,yCAAmB,EAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IAEhE,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,EAAC,GAAG,EAAE,KAAK,EAAC,CAAC,CAAC;AAE1C,CAAC,CAAC,CAAC;AAEH,IAAA,WAAI,EAAC,8CAA8C,EAAE,CAAC,MAAM,EAAE,EAAE;IAE5D,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,yCAAmB,EAAC,CAAC,UAAU,CAAQ,CAAC,EAAE,oBAAoB,CAAC,CAAC;AAExF,CAAC,CAAC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * CLI handler: create a new CloudFormation stack.
3
3
  */
4
- export declare function createStack(stackName: string, templatePath: string, paramsPath?: string): Promise<void>;
4
+ export declare function createStack(stackName: string, templatePath: string, paramsPath?: string, overrides?: Record<string, string>): Promise<void>;
5
5
  //# sourceMappingURL=createStack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createStack.d.ts","sourceRoot":"","sources":["../src/createStack.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,WAAW,CAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAmBf"}
1
+ {"version":3,"file":"createStack.d.ts","sourceRoot":"","sources":["../src/createStack.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,WAAW,CAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CAmBf"}
@@ -41,9 +41,9 @@ const log_1 = require("./cli/log");
41
41
  /**
42
42
  * CLI handler: create a new CloudFormation stack.
43
43
  */
44
- async function createStack(stackName, templatePath, paramsPath) {
44
+ async function createStack(stackName, templatePath, paramsPath, overrides) {
45
45
  cfn.initCloudFormationClient();
46
- const { template, params } = await (0, loadTemplateAndParams_1.loadTemplateAndParams)(templatePath, paramsPath);
46
+ const { template, params } = await (0, loadTemplateAndParams_1.loadTemplateAndParams)(templatePath, paramsPath, overrides);
47
47
  const existing = await cfn.getStackByName(stackName);
48
48
  if (existing) {
49
49
  throw new Error('stack already exists, try update command');
@@ -1 +1 @@
1
- {"version":3,"file":"createStack.js","sourceRoot":"","sources":["../src/createStack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,kCAuBC;AA/BD,+CAAiC;AACjC,uEAAkE;AAClE,6DAA8D;AAC9D,mCAAyC;AAEzC;;GAEG;AACI,KAAK,UAAU,WAAW,CAC7B,SAAiB,EACjB,YAAoB,EACpB,UAAmB;IAGnB,GAAG,CAAC,wBAAwB,EAAE,CAAC;IAE/B,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,MAAM,IAAA,6CAAqB,EAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,QAAQ,EAAE,CAAC;QAEX,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAEhE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;IAEvC,IAAA,oBAAc,EAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,CAAC,CAAC;AAE/D,CAAC"}
1
+ {"version":3,"file":"createStack.js","sourceRoot":"","sources":["../src/createStack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,kCAwBC;AAhCD,+CAAiC;AACjC,uEAAkE;AAClE,6DAA8D;AAC9D,mCAAyC;AAEzC;;GAEG;AACI,KAAK,UAAU,WAAW,CAC7B,SAAiB,EACjB,YAAoB,EACpB,UAAmB,EACnB,SAAkC;IAGlC,GAAG,CAAC,wBAAwB,EAAE,CAAC;IAE/B,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,MAAM,IAAA,6CAAqB,EAAC,YAAY,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,QAAQ,EAAE,CAAC;QAEX,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAEhE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;IAEvC,IAAA,oBAAc,EAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,CAAC,CAAC;AAE/D,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './lib/cfn';
2
2
  export * from './lib/output';
3
3
  export { previewStack } from './previewStack';
4
+ export { inspectStack } from './inspectStack';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -14,9 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.previewStack = void 0;
17
+ exports.inspectStack = exports.previewStack = void 0;
18
18
  __exportStar(require("./lib/cfn"), exports);
19
19
  __exportStar(require("./lib/output"), exports);
20
20
  var previewStack_1 = require("./previewStack");
21
21
  Object.defineProperty(exports, "previewStack", { enumerable: true, get: function () { return previewStack_1.previewStack; } });
22
+ var inspectStack_1 = require("./inspectStack");
23
+ Object.defineProperty(exports, "inspectStack", { enumerable: true, get: function () { return inspectStack_1.inspectStack; } });
22
24
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,+CAA6B;AAC7B,+CAA4C;AAApC,4GAAA,YAAY,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,+CAA6B;AAC7B,+CAA4C;AAApC,4GAAA,YAAY,OAAA;AACpB,+CAA4C;AAApC,4GAAA,YAAY,OAAA"}
@@ -0,0 +1,6 @@
1
+ export interface InspectStackOptions {
2
+ eventsLimit: number;
3
+ usePager: boolean;
4
+ }
5
+ export declare function inspectStack(stackName: string, options?: Partial<InspectStackOptions>): Promise<void>;
6
+ //# sourceMappingURL=inspectStack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspectStack.d.ts","sourceRoot":"","sources":["../src/inspectStack.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;CACpB;AAwND,wBAAsB,YAAY,CAC9B,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.inspectStack = inspectStack;
37
+ const cfn = __importStar(require("./lib/cfn"));
38
+ const viewText_1 = require("./lib/viewText");
39
+ const DEFAULT_OPTIONS = {
40
+ eventsLimit: 500,
41
+ usePager: true,
42
+ };
43
+ const GENERIC_FAILURE_PATTERNS = [
44
+ /resource creation cancelled/i,
45
+ /resource update cancelled/i,
46
+ /the following resource\(s\) failed/i,
47
+ /user initiated/i,
48
+ ];
49
+ function toIso(value) {
50
+ if (!value) {
51
+ return '—';
52
+ }
53
+ return value.toISOString();
54
+ }
55
+ function toTimestamp(event) {
56
+ return event.Timestamp?.getTime() ?? 0;
57
+ }
58
+ function toChronological(events) {
59
+ return events.slice().sort((left, right) => toTimestamp(left) - toTimestamp(right));
60
+ }
61
+ function isFailureStatus(status) {
62
+ return status.includes('FAILED') || status.includes('ROLLBACK');
63
+ }
64
+ function isGenericFailureReason(reason) {
65
+ return GENERIC_FAILURE_PATTERNS.some((pattern) => pattern.test(reason));
66
+ }
67
+ function getFailureEvents(events) {
68
+ const out = [];
69
+ for (const event of events) {
70
+ const status = event.ResourceStatus ?? '';
71
+ const reason = event.ResourceStatusReason ?? '';
72
+ if (!isFailureStatus(status) || !reason)
73
+ continue;
74
+ out.push({
75
+ timestamp: toIso(event.Timestamp),
76
+ resource: `${event.LogicalResourceId ?? 'Unknown'} (${event.ResourceType ?? 'Unknown'})`,
77
+ status,
78
+ reason,
79
+ });
80
+ }
81
+ return out;
82
+ }
83
+ function uniqueRootCauseCandidates(failures) {
84
+ const seenReasons = new Set();
85
+ const rootCauses = [];
86
+ for (const failure of failures) {
87
+ if (isGenericFailureReason(failure.reason) || seenReasons.has(failure.reason))
88
+ continue;
89
+ seenReasons.add(failure.reason);
90
+ rootCauses.push(failure);
91
+ }
92
+ return rootCauses;
93
+ }
94
+ function formatSection(title, body) {
95
+ return `${title}\n${'-'.repeat(title.length)}\n${body}`;
96
+ }
97
+ function formatParameters(stack) {
98
+ const params = stack.Parameters ?? [];
99
+ if (params.length === 0)
100
+ return 'No parameters on stack.';
101
+ return params
102
+ .map((param) => `${param.ParameterKey ?? 'Unknown'}=${param.ParameterValue ?? '(no value returned)'}`)
103
+ .join('\n');
104
+ }
105
+ function formatOutputs(stack) {
106
+ const outputs = stack.Outputs ?? [];
107
+ if (outputs.length === 0)
108
+ return 'No outputs on stack.';
109
+ return outputs.map((output) => `${output.OutputKey ?? 'Unknown'}=${output.OutputValue ?? ''}`).join('\n');
110
+ }
111
+ function formatRootCauses(failures) {
112
+ const rootCauses = uniqueRootCauseCandidates(failures).slice(0, 10);
113
+ if (rootCauses.length === 0)
114
+ return 'No specific root-cause errors detected.';
115
+ return rootCauses
116
+ .map((failure) => `[${failure.timestamp}] ${failure.status} ${failure.resource}\n Reason: ${failure.reason}`)
117
+ .join('\n\n');
118
+ }
119
+ function formatFailureEvents(failures) {
120
+ if (failures.length === 0)
121
+ return 'No failure events found.';
122
+ return failures
123
+ .slice(-50)
124
+ .map((failure) => `[${failure.timestamp}] ${failure.status} ${failure.resource}\n Reason: ${failure.reason}`)
125
+ .join('\n\n');
126
+ }
127
+ function formatEvent(event) {
128
+ const timestamp = toIso(event.Timestamp);
129
+ const status = event.ResourceStatus ?? 'UNKNOWN';
130
+ const logical = event.LogicalResourceId ?? 'Unknown';
131
+ const type = event.ResourceType ?? 'Unknown';
132
+ const reason = event.ResourceStatusReason ? `\n Reason: ${event.ResourceStatusReason}` : '';
133
+ return `[${timestamp}] ${status} ${logical} (${type})${reason}`;
134
+ }
135
+ function formatEvents(events, eventsLimit) {
136
+ if (events.length === 0)
137
+ return 'No stack events found.';
138
+ const chronological = toChronological(events);
139
+ const header = eventsLimit > 0
140
+ ? `Showing up to ${eventsLimit} events in chronological order.`
141
+ : 'Showing all events in chronological order.';
142
+ return `${header}\n\n${chronological.map((event) => formatEvent(event)).join('\n\n')}`;
143
+ }
144
+ function stackDetailsJson(stack) {
145
+ return JSON.stringify(stack, (_key, value) => value instanceof Date ? value.toISOString() : value, 2);
146
+ }
147
+ function stackSummary(stack) {
148
+ const lines = [
149
+ `StackName: ${stack.StackName ?? '—'}`,
150
+ `StackId: ${stack.StackId ?? '—'}`,
151
+ `Status: ${stack.StackStatus ?? '—'}`,
152
+ `StatusReason: ${stack.StackStatusReason ?? '—'}`,
153
+ `CreatedAt: ${toIso(stack.CreationTime)}`,
154
+ `UpdatedAt: ${toIso(stack.LastUpdatedTime)}`,
155
+ `DriftStatus: ${stack.DriftInformation?.StackDriftStatus ?? '—'}`,
156
+ `EnableTerminationProtection: ${stack.EnableTerminationProtection ?? false}`,
157
+ ];
158
+ return lines.join('\n');
159
+ }
160
+ function buildReport(stack, templateBody, events, options) {
161
+ const failures = getFailureEvents(toChronological(events));
162
+ const sections = [
163
+ formatSection('Stack Summary', stackSummary(stack)),
164
+ formatSection('Stack Details (Raw JSON)', stackDetailsJson(stack)),
165
+ formatSection('Parameters', formatParameters(stack)),
166
+ formatSection('Outputs', formatOutputs(stack)),
167
+ formatSection('Likely Root Causes', formatRootCauses(failures)),
168
+ formatSection('Failure Events', formatFailureEvents(failures)),
169
+ formatSection('Events', formatEvents(events, options.eventsLimit)),
170
+ formatSection('Full Deployed Template', templateBody || 'Template body is empty.'),
171
+ ];
172
+ return ['awscfn inspect-stack', '='.repeat(20), '', ...sections].join('\n\n');
173
+ }
174
+ async function inspectStack(stackName, options) {
175
+ cfn.initCloudFormationClient();
176
+ const resolvedOptions = { ...DEFAULT_OPTIONS, ...options };
177
+ const stack = await cfn.getStackByName(stackName, true);
178
+ if (!stack)
179
+ throw new Error(`stack ${stackName} does not exist`);
180
+ const [templateBody, events] = await Promise.all([
181
+ cfn.getStackTemplateBody(stackName),
182
+ cfn.listStackEvents(stackName, resolvedOptions.eventsLimit),
183
+ ]);
184
+ const report = buildReport(stack, templateBody, events, resolvedOptions);
185
+ (0, viewText_1.viewText)(`inspect-${stackName}`, report, { usePager: resolvedOptions.usePager });
186
+ }
187
+ //# sourceMappingURL=inspectStack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspectStack.js","sourceRoot":"","sources":["../src/inspectStack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function getStackTemplateBody(stackName: string): Promise<string>;
2
+ //# sourceMappingURL=getStackTemplate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getStackTemplate.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/getStackTemplate.ts"],"names":[],"mappings":"AAiCA,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY7E"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getStackTemplateBody = getStackTemplateBody;
4
+ const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
5
+ const _1 = require(".");
6
+ function toTemplateString(templateBody) {
7
+ if (typeof templateBody === 'string') {
8
+ return templateBody;
9
+ }
10
+ if (!templateBody) {
11
+ return '';
12
+ }
13
+ return JSON.stringify(templateBody, null, 2);
14
+ }
15
+ async function fetchTemplate(stage, stackName) {
16
+ const cf = (0, _1.getCfClient)();
17
+ const response = await cf.send(new client_cloudformation_1.GetTemplateCommand({
18
+ StackName: stackName,
19
+ TemplateStage: stage,
20
+ }));
21
+ return toTemplateString(response.TemplateBody);
22
+ }
23
+ async function getStackTemplateBody(stackName) {
24
+ const original = await fetchTemplate('Original', stackName);
25
+ if (original) {
26
+ return original;
27
+ }
28
+ return fetchTemplate('Processed', stackName);
29
+ }
30
+ //# sourceMappingURL=getStackTemplate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getStackTemplate.js","sourceRoot":"","sources":["../../../src/lib/cfn/getStackTemplate.ts"],"names":[],"mappings":";;AAiCA,oDAYC;AA7CD,0EAAkE;AAClE,wBAA8B;AAE9B,SAAS,gBAAgB,CAAC,YAAqB;IAE3C,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QAEnC,OAAO,YAAY,CAAC;IAExB,CAAC;IAED,IAAI,CAAC,YAAY,EAAE,CAAC;QAEhB,OAAO,EAAE,CAAC;IAEd,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAEjD,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,KAA6B,EAAE,SAAiB;IAEzE,MAAM,EAAE,GAAG,IAAA,cAAW,GAAE,CAAC;IACzB,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,0CAAkB,CAAC;QAClD,SAAS,EAAE,SAAS;QACpB,aAAa,EAAE,KAAK;KACvB,CAAC,CAAC,CAAC;IAEJ,OAAO,gBAAgB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AAEnD,CAAC;AAEM,KAAK,UAAU,oBAAoB,CAAC,SAAiB;IAExD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAE5D,IAAI,QAAQ,EAAE,CAAC;QAEX,OAAO,QAAQ,CAAC;IAEpB,CAAC;IAED,OAAO,aAAa,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAEjD,CAAC"}
@@ -18,4 +18,6 @@ export * from './isStackTerminal';
18
18
  export * from './waitUntilStackTerminal';
19
19
  export * from './getParamFromStack';
20
20
  export * from './streamStackEvents';
21
+ export * from './getStackTemplate';
22
+ export * from './listStackEvents';
21
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,gCAAgC,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACjD,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,cAAc,IAAI;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,CAAC,CAAA;CACZ,GAAG,MAAM,CAAC;AAIX,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAED,wBAAgB,WAAW,IAAI,oBAAoB,CAMlD;AAED,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,gCAAgC,CAAC;AAEpE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACjD,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,cAAc,IAAI;IAC7C,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,CAAC,CAAA;CACZ,GAAG,MAAM,CAAC;AAIX,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAED,wBAAgB,WAAW,IAAI,oBAAoB,CAMlD;AAED,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC"}
@@ -38,4 +38,6 @@ __exportStar(require("./isStackTerminal"), exports);
38
38
  __exportStar(require("./waitUntilStackTerminal"), exports);
39
39
  __exportStar(require("./getParamFromStack"), exports);
40
40
  __exportStar(require("./streamStackEvents"), exports);
41
+ __exportStar(require("./getStackTemplate"), exports);
42
+ __exportStar(require("./listStackEvents"), exports);
41
43
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/cfn/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAUA,4DAIC;AAED,kCAMC;AAtBD,0EAAoE;AAQpE,IAAI,EAAkC,CAAC;AAEvC,SAAgB,wBAAwB;IAEpC,EAAE,GAAG,IAAI,4CAAoB,EAAE,CAAC;AAEpC,CAAC;AAED,SAAgB,WAAW;IAEvB,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAElE,OAAO,EAAE,CAAC;AAEd,CAAC;AAED,gDAA8B;AAC9B,mDAAiC;AACjC,+CAA6B;AAC7B,qDAAmC;AACnC,gDAA8B;AAC9B,gDAA8B;AAC9B,qDAAmC;AACnC,sDAAoC;AACpC,oDAAkC;AAClC,2DAAyC;AACzC,sDAAoC;AACpC,sDAAoC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/cfn/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAUA,4DAIC;AAED,kCAMC;AAtBD,0EAAoE;AAQpE,IAAI,EAAkC,CAAC;AAEvC,SAAgB,wBAAwB;IAEpC,EAAE,GAAG,IAAI,4CAAoB,EAAE,CAAC;AAEpC,CAAC;AAED,SAAgB,WAAW;IAEvB,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAElE,OAAO,EAAE,CAAC;AAEd,CAAC;AAED,gDAA8B;AAC9B,mDAAiC;AACjC,+CAA6B;AAC7B,qDAAmC;AACnC,gDAA8B;AAC9B,gDAA8B;AAC9B,qDAAmC;AACnC,sDAAoC;AACpC,oDAAkC;AAClC,2DAAyC;AACzC,sDAAoC;AACpC,sDAAoC;AACpC,qDAAmC;AACnC,oDAAkC"}
@@ -0,0 +1,3 @@
1
+ import { StackEvent } from '@aws-sdk/client-cloudformation';
2
+ export declare function listStackEvents(stackName: string, limit?: number): Promise<StackEvent[]>;
3
+ //# sourceMappingURL=listStackEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listStackEvents.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/listStackEvents.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,UAAU,EAAC,MAAM,gCAAgC,CAAC;AAetF,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAoBnG"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listStackEvents = listStackEvents;
4
+ const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
5
+ const _1 = require(".");
6
+ function trimToLimit(events, limit) {
7
+ if (limit <= 0) {
8
+ return events;
9
+ }
10
+ return events.slice(0, limit);
11
+ }
12
+ async function listStackEvents(stackName, limit = 500) {
13
+ const cf = (0, _1.getCfClient)();
14
+ const events = [];
15
+ let nextToken;
16
+ do {
17
+ const response = await cf.send(new client_cloudformation_1.DescribeStackEventsCommand({
18
+ StackName: stackName,
19
+ NextToken: nextToken,
20
+ }));
21
+ events.push(...(response.StackEvents ?? []));
22
+ nextToken = response.NextToken;
23
+ } while (nextToken && (limit <= 0 || events.length < limit));
24
+ return trimToLimit(events, limit);
25
+ }
26
+ //# sourceMappingURL=listStackEvents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listStackEvents.js","sourceRoot":"","sources":["../../../src/lib/cfn/listStackEvents.ts"],"names":[],"mappings":";;AAeA,0CAoBC;AAnCD,0EAAsF;AACtF,wBAA8B;AAE9B,SAAS,WAAW,CAAC,MAAoB,EAAE,KAAa;IAEpD,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAEb,OAAO,MAAM,CAAC;IAElB,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAElC,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,SAAiB,EAAE,QAAgB,GAAG;IAExE,MAAM,EAAE,GAAG,IAAA,cAAW,GAAE,CAAC;IACzB,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,SAA2B,CAAC;IAEhC,GAAG,CAAC;QAEA,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,kDAA0B,CAAC;YAC1D,SAAS,EAAE,SAAS;YACpB,SAAS,EAAE,SAAS;SACvB,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7C,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;IAEnC,CAAC,QAAQ,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,EAAE;IAE7D,OAAO,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAEtC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface ViewTextOptions {
2
+ usePager: boolean;
3
+ }
4
+ export declare function viewText(reportName: string, content: string, options: ViewTextOptions): void;
5
+ //# sourceMappingURL=viewText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewText.d.ts","sourceRoot":"","sources":["../../src/lib/viewText.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,OAAO,CAAA;CACpB;AA2DD,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAyB5F"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.viewText = viewText;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_child_process_1 = require("node:child_process");
11
+ function runViewerCommand(command, args) {
12
+ const result = (0, node_child_process_1.spawnSync)(command, args, { stdio: 'inherit' });
13
+ return !result.error && result.status === 0;
14
+ }
15
+ function runPagerExpression(pagerExpression, filePath) {
16
+ const result = (0, node_child_process_1.spawnSync)(`${pagerExpression} "${filePath}"`, {
17
+ shell: true,
18
+ stdio: 'inherit',
19
+ });
20
+ return !result.error && result.status === 0;
21
+ }
22
+ function openWithPager(filePath) {
23
+ const pagerExpression = process.env.GIT_PAGER ?? process.env.PAGER;
24
+ if (pagerExpression && runPagerExpression(pagerExpression, filePath)) {
25
+ return true;
26
+ }
27
+ return runViewerCommand('less', ['-R', filePath]) || runViewerCommand('more', [filePath]);
28
+ }
29
+ function writeTempReport(reportName, content) {
30
+ const tempDir = (0, node_fs_1.mkdtempSync)(node_path_1.default.join((0, node_os_1.tmpdir)(), 'awscfn-'));
31
+ const safeName = reportName.replace(/[^a-zA-Z0-9-]/g, '-');
32
+ const filePath = node_path_1.default.join(tempDir, `${safeName}.txt`);
33
+ (0, node_fs_1.writeFileSync)(filePath, content, 'utf8');
34
+ return filePath;
35
+ }
36
+ function readAndPrint(filePath) {
37
+ console.log((0, node_fs_1.readFileSync)(filePath, 'utf8'));
38
+ }
39
+ function shouldPrintInline(usePager) {
40
+ return !usePager || !process.stdout.isTTY || process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
41
+ }
42
+ function viewText(reportName, content, options) {
43
+ if (shouldPrintInline(options.usePager)) {
44
+ console.log(content);
45
+ return;
46
+ }
47
+ const filePath = writeTempReport(reportName, content);
48
+ try {
49
+ if (!openWithPager(filePath)) {
50
+ readAndPrint(filePath);
51
+ }
52
+ }
53
+ finally {
54
+ (0, node_fs_1.rmSync)(node_path_1.default.dirname(filePath), { recursive: true, force: true });
55
+ }
56
+ }
57
+ //# sourceMappingURL=viewText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewText.js","sourceRoot":"","sources":["../../src/lib/viewText.ts"],"names":[],"mappings":";;;;;AAkEA,4BAyBC;AA3FD,qCAAyE;AACzE,qCAA+B;AAC/B,0DAA6B;AAC7B,2DAA6C;AAM7C,SAAS,gBAAgB,CAAC,OAAe,EAAE,IAAc;IAErD,MAAM,MAAM,GAAG,IAAA,8BAAS,EAAC,OAAO,EAAE,IAAI,EAAE,EAAC,KAAK,EAAE,SAAS,EAAC,CAAC,CAAC;IAE5D,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAEhD,CAAC;AAED,SAAS,kBAAkB,CAAC,eAAuB,EAAE,QAAgB;IAEjE,MAAM,MAAM,GAAG,IAAA,8BAAS,EAAC,GAAG,eAAe,KAAK,QAAQ,GAAG,EAAE;QACzD,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,SAAS;KACnB,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAEhD,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IAEnC,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;IAEnE,IAAI,eAAe,IAAI,kBAAkB,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,CAAC;QAEnE,OAAO,IAAI,CAAC;IAEhB,CAAC;IAED,OAAO,gBAAgB,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,IAAI,gBAAgB,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE9F,CAAC;AAED,SAAS,eAAe,CAAC,UAAkB,EAAE,OAAe;IAExD,MAAM,OAAO,GAAG,IAAA,qBAAW,EAAC,mBAAI,CAAC,IAAI,CAAC,IAAA,gBAAM,GAAE,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,mBAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,QAAQ,MAAM,CAAC,CAAC;IAEvD,IAAA,uBAAa,EAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAEzC,OAAO,QAAQ,CAAC;AAEpB,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IAElC,OAAO,CAAC,GAAG,CAAC,IAAA,sBAAY,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAEhD,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAiB;IAExC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM,CAAC;AAEpH,CAAC;AAED,SAAgB,QAAQ,CAAC,UAAkB,EAAE,OAAe,EAAE,OAAwB;IAElF,IAAI,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAEtC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO;IAEX,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAEtD,IAAI,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;YAE3B,YAAY,CAAC,QAAQ,CAAC,CAAC;QAE3B,CAAC;IAEL,CAAC;YAAS,CAAC;QAEP,IAAA,gBAAM,EAAC,mBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC;IAEnE,CAAC;AAEL,CAAC"}
@@ -2,5 +2,5 @@
2
2
  * CLI: preview stack changes without executing (build change set, print table, delete change set).
3
3
  * CREATE vs UPDATE matches whether the stack already exists.
4
4
  */
5
- export declare function previewStack(stackName: string, templatePath: string, paramsPath?: string): Promise<void>;
5
+ export declare function previewStack(stackName: string, templatePath: string, paramsPath?: string, overrides?: Record<string, string>): Promise<void>;
6
6
  //# sourceMappingURL=previewStack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"previewStack.d.ts","sourceRoot":"","sources":["../src/previewStack.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAsB,YAAY,CAC9B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
1
+ {"version":3,"file":"previewStack.d.ts","sourceRoot":"","sources":["../src/previewStack.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAsB,YAAY,CAC9B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
@@ -43,9 +43,9 @@ const output_1 = require("./lib/output");
43
43
  * CLI: preview stack changes without executing (build change set, print table, delete change set).
44
44
  * CREATE vs UPDATE matches whether the stack already exists.
45
45
  */
46
- async function previewStack(stackName, templatePath, paramsPath) {
46
+ async function previewStack(stackName, templatePath, paramsPath, overrides) {
47
47
  cfn.initCloudFormationClient();
48
- const { template, params } = await (0, loadTemplateAndParams_1.loadTemplateAndParams)(templatePath, paramsPath);
48
+ const { template, params } = await (0, loadTemplateAndParams_1.loadTemplateAndParams)(templatePath, paramsPath, overrides);
49
49
  const existing = await cfn.getStackByName(stackName);
50
50
  if (existing?.StackStatus === client_cloudformation_1.StackStatus.ROLLBACK_COMPLETE) {
51
51
  (0, output_1.warn)(`Stack ${stackName} is in ROLLBACK_COMPLETE; update-stack would delete and recreate it. `
@@ -1 +1 @@
1
- {"version":3,"file":"previewStack.js","sourceRoot":"","sources":["../src/previewStack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,oCAiCC;AA3CD,0EAA2D;AAC3D,+CAAiC;AACjC,uEAAkE;AAClE,6DAA8D;AAC9D,yCAAuD;AAEvD;;;GAGG;AACI,KAAK,UAAU,YAAY,CAC9B,SAAiB,EACjB,YAAoB,EACpB,UAAmB;IAGnB,GAAG,CAAC,wBAAwB,EAAE,CAAC;IAE/B,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,MAAM,IAAA,6CAAqB,EAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,QAAQ,EAAE,WAAW,KAAK,mCAAW,CAAC,iBAAiB,EAAE,CAAC;QAE1D,IAAA,aAAI,EACA,SAAS,SAAS,uEAAuE;cACvF,iCAAiC,CACtC,CAAC;QAEF,MAAM,IAAI,KAAK,CACX,4GAA4G,CAC/G,CAAC;IAEN,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;IAEvC,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEjD,IAAA,aAAI,EAAC,GAAG,gBAAO,CAAC,KAAK,YAAY,IAAA,aAAI,EAAC,SAAS,CAAC,cAAc,IAAA,aAAI,EAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAEjF,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,EAAE,SAAS,CAAC,CAAC;AAE/E,CAAC"}
1
+ {"version":3,"file":"previewStack.js","sourceRoot":"","sources":["../src/previewStack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,oCAkCC;AA5CD,0EAA2D;AAC3D,+CAAiC;AACjC,uEAAkE;AAClE,6DAA8D;AAC9D,yCAAuD;AAEvD;;;GAGG;AACI,KAAK,UAAU,YAAY,CAC9B,SAAiB,EACjB,YAAoB,EACpB,UAAmB,EACnB,SAAkC;IAGlC,GAAG,CAAC,wBAAwB,EAAE,CAAC;IAE/B,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,MAAM,IAAA,6CAAqB,EAAC,YAAY,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,QAAQ,EAAE,WAAW,KAAK,mCAAW,CAAC,iBAAiB,EAAE,CAAC;QAE1D,IAAA,aAAI,EACA,SAAS,SAAS,uEAAuE;cACvF,iCAAiC,CACtC,CAAC;QAEF,MAAM,IAAI,KAAK,CACX,4GAA4G,CAC/G,CAAC;IAEN,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;IAEvC,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEjD,IAAA,aAAI,EAAC,GAAG,gBAAO,CAAC,KAAK,YAAY,IAAA,aAAI,EAAC,SAAS,CAAC,cAAc,IAAA,aAAI,EAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAEjF,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,EAAE,SAAS,CAAC,CAAC;AAE/E,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * CLI handler: update an existing CloudFormation stack.
3
3
  */
4
- export declare function updateStack(stackName: string, templatePath: string, paramsPath?: string, create?: boolean): Promise<void>;
4
+ export declare function updateStack(stackName: string, templatePath: string, paramsPath?: string, create?: boolean, overrides?: Record<string, string>): Promise<void>;
5
5
  //# sourceMappingURL=updateStack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"updateStack.d.ts","sourceRoot":"","sources":["../src/updateStack.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,WAAW,CAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,GAAE,OAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
1
+ {"version":3,"file":"updateStack.d.ts","sourceRoot":"","sources":["../src/updateStack.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,WAAW,CAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,GAAE,OAAe,EACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
@@ -41,9 +41,9 @@ const log_1 = require("./cli/log");
41
41
  /**
42
42
  * CLI handler: update an existing CloudFormation stack.
43
43
  */
44
- async function updateStack(stackName, templatePath, paramsPath, create = false) {
44
+ async function updateStack(stackName, templatePath, paramsPath, create = false, overrides) {
45
45
  cfn.initCloudFormationClient();
46
- const { template, params } = await (0, loadTemplateAndParams_1.loadTemplateAndParams)(templatePath, paramsPath);
46
+ const { template, params } = await (0, loadTemplateAndParams_1.loadTemplateAndParams)(templatePath, paramsPath, overrides);
47
47
  const existing = await cfn.getStackByName(stackName);
48
48
  if (!existing) {
49
49
  if (!create) {
@@ -1 +1 @@
1
- {"version":3,"file":"updateStack.js","sourceRoot":"","sources":["../src/updateStack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,kCAoCC;AA5CD,+CAAiC;AACjC,uEAAkE;AAClE,6DAA8D;AAC9D,mCAAyC;AAEzC;;GAEG;AACI,KAAK,UAAU,WAAW,CAC7B,SAAiB,EACjB,YAAoB,EACpB,UAAmB,EACnB,SAAkB,KAAK;IAGvB,GAAG,CAAC,wBAAwB,EAAE,CAAC;IAE/B,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,MAAM,IAAA,6CAAqB,EAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEZ,IAAI,CAAC,MAAM,EAAE,CAAC;YAEV,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAE3D,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;QAEvC,IAAA,oBAAc,EAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,CAAC,CAAC;QAE3D,OAAO;IAEX,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;IAEvC,IAAA,oBAAc,EAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,CAAC,CAAC;AAE9D,CAAC"}
1
+ {"version":3,"file":"updateStack.js","sourceRoot":"","sources":["../src/updateStack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,kCAqCC;AA7CD,+CAAiC;AACjC,uEAAkE;AAClE,6DAA8D;AAC9D,mCAAyC;AAEzC;;GAEG;AACI,KAAK,UAAU,WAAW,CAC7B,SAAiB,EACjB,YAAoB,EACpB,UAAmB,EACnB,SAAkB,KAAK,EACvB,SAAkC;IAGlC,GAAG,CAAC,wBAAwB,EAAE,CAAC;IAE/B,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,MAAM,IAAA,6CAAqB,EAAC,YAAY,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAErD,IAAI,CAAC,QAAQ,EAAE,CAAC;QAEZ,IAAI,CAAC,MAAM,EAAE,CAAC;YAEV,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAE3D,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;QAEvC,IAAA,oBAAc,EAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,CAAC,CAAC;QAE3D,OAAO;IAEX,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,IAAA,yCAAsB,EAAC,QAAQ,CAAC,CAAC;IAEvC,IAAA,oBAAc,EAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAC,CAAC,CAAC;AAE9D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "awscfn",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "CLI and TypeScript SDK for managing AWS CloudFormation stacks with simple YAML parameters and real-time event streaming.",
5
5
  "type": "commonjs",
6
6
  "main": "./dist/index.js",