awscfn 1.1.0 → 1.1.2

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/README.md CHANGED
@@ -9,15 +9,51 @@
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
- CLI and TypeScript SDK for managing AWS CloudFormation stacks.
12
+ Deploy CloudFormation stacks without the usual suffering.
13
13
 
14
14
  ## Why awscfn?
15
15
 
16
- - **Simple YAML parameters** No more wrestling with verbose JSON. Just clean, readable YAML files.
17
- - **See what's happening** — Real-time event streaming in your terminal. No refreshing the console, no juggling `aws cloudformation create-stack` and `describe-stack-events` in another window.
18
- - **Errors that make sense** When deploys fail, you get the actual error message from CloudFormation, not a cryptic timeout.
19
- - **CI/CD friendly** Works great in GitHub Actions with auto-detected CI mode.
20
- - **CLI & SDK** Use from command line or import directly in Node.js/TypeScript projects.
16
+ If you've deployed CloudFormation stacks, you know the pain:
17
+
18
+ - You run `aws cloudformation create-stack` and get... nothing. Is it working? Who knows.
19
+ - You open the AWS console, hit refresh, scroll through events, trying to find the one that matters.
20
+ - It fails. The error says "Resource creation cancelled." The *actual* reason is buried somewhere in the event log.
21
+ - The stack is stuck in `ROLLBACK_COMPLETE`. Now you have to delete it manually before you can try again.
22
+ - Your CI job times out or exits 0 even though the deploy failed.
23
+ - You write a parameter file and remember: oh right, CloudFormation wants *that* JSON format.
24
+
25
+ **awscfn fixes this.**
26
+
27
+ - **Watch deploys happen** — Stack events stream to your terminal in real time. No refreshing. No second window.
28
+ - **See why it failed** — When a deploy fails, you get the actual failure reason, not "Resource creation cancelled."
29
+ - **Recover automatically** — Stuck in `ROLLBACK_COMPLETE`? awscfn detects it and re-creates the stack for you.
30
+ - **YAML params** — Simple YAML parameter files. No more verbose JSON.
31
+ - **CI that works** — Auto-detects CI environments. Exits non-zero when deploys fail. Compact output mode.
32
+ - **CLI + TypeScript SDK** — Use from the command line or import directly into Node.js/TypeScript projects.
33
+
34
+ It's not a CDK. It's not a framework. It's just a better way to deploy raw CloudFormation.
35
+
36
+ ## Installation
37
+
38
+ **Global install** (recommended for CLI use):
39
+
40
+ ```bash
41
+ npm i -g awscfn
42
+ ```
43
+
44
+ Then run commands directly: `awscfn create-stack ...`
45
+
46
+ **Project dependency** (for SDK/library use):
47
+
48
+ ```bash
49
+ npm i awscfn
50
+ ```
51
+
52
+ **npx** (no install):
53
+
54
+ ```bash
55
+ npx awscfn create-stack ...
56
+ ```
21
57
 
22
58
  ## CLI commands
23
59
 
@@ -25,12 +61,15 @@ CLI and TypeScript SDK for managing AWS CloudFormation stacks.
25
61
 
26
62
  ### Global Options
27
63
 
28
- | Flag | Short | Description |
29
- |------|-------|-------------|
30
- | `--ci` | — | CI mode (compact output). Auto-detected when `CI=true` or `GITHUB_ACTIONS=true`. Colors stay on in CI (e.g. GitHub Actions supports ANSI). |
31
- | `--no-color` | `-N` | Disable colored output |
32
- | `--help` | `-h` | Show help |
33
- | `--version` | `-v` | Show version |
64
+ | Flag | Description |
65
+ |------|-------------|
66
+ | `--ci`, `-C` | CI mode (compact output). Auto-detected when `CI=true` or `GITHUB_ACTIONS=true`. |
67
+ | `--no-color`, `-N` | Disable colored output |
68
+ | `--verbose`, `-V` | Show full error details on failure |
69
+ | `--help`, `-h` | Show help |
70
+ | `--version`, `-v` | Show version |
71
+
72
+ Run `awscfn --help` or `awscfn <command> --help` for full CLI usage.
34
73
 
35
74
  ### Shell Completion
36
75
 
@@ -62,34 +101,32 @@ When a failure occurs, the error message includes the actual reason from CloudFo
62
101
  List all CloudFormation stacks in the current region (name, status, creation date).
63
102
 
64
103
  ```bash
65
- npx awscfn list-stacks
104
+ awscfn list-stacks
66
105
  ```
67
106
 
68
- No options. Output is a table of stack name, status, and creation date.
69
-
70
107
  ### 🚀 create-stack
71
108
 
72
109
  ```bash
73
- npx awscfn create-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
110
+ awscfn create-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
74
111
  ```
75
112
 
76
- | Flag | Short | Description |
77
- |------|-------|-------------|
78
- | `--name` | `-n` | Stack name |
79
- | `--template` | `-t` | CloudFormation template file |
80
- | `--params` | `-p` | Parameters file (YAML) |
113
+ | Flag | Description |
114
+ |------|-------------|
115
+ | `--name`, `-n` | Stack name |
116
+ | `--template`, `-t` | CloudFormation template file |
117
+ | `--params`, `-p` | Parameters file (YAML) |
81
118
 
82
119
  ### ⬆️ update-stack
83
120
 
84
121
  ```bash
85
- npx awscfn update-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
122
+ awscfn update-stack -n <STACK_NAME> -t <TEMPLATE_FILE> -p <PARAMS_FILE>
86
123
  ```
87
124
 
88
- | Flag | Short | Description |
89
- |------|-------|-------------|
90
- | `--name` | `-n` | Stack name |
91
- | `--template` | `-t` | CloudFormation template file |
92
- | `--params` | `-p` | Parameters file (YAML) |
125
+ | Flag | Description |
126
+ |------|-------------|
127
+ | `--name`, `-n` | Stack name |
128
+ | `--template`, `-t` | CloudFormation template file |
129
+ | `--params`, `-p` | Parameters file (YAML) |
93
130
 
94
131
  If there are no changes to apply, the command succeeds gracefully:
95
132
  ```
@@ -99,13 +136,13 @@ If there are no changes to apply, the command succeeds gracefully:
99
136
  ### ♻️ redeploy-stack
100
137
 
101
138
  ```bash
102
- npx awscfn redeploy-stack -n <STACK_NAME> -t <TEMPLATE_FILE>
139
+ awscfn redeploy-stack -n <STACK_NAME> -t <TEMPLATE_FILE>
103
140
  ```
104
141
 
105
- | Flag | Short | Description |
106
- |------|-------|-------------|
107
- | `--name` | `-n` | Stack name |
108
- | `--template` | `-t` | CloudFormation template file |
142
+ | Flag | Description |
143
+ |------|-------------|
144
+ | `--name`, `-n` | Stack name |
145
+ | `--template`, `-t` | CloudFormation template file |
109
146
 
110
147
  Redeploys using the existing stack's parameters. Useful for updating a stack with a new template without re-specifying params, or re-deploying after a failed create.
111
148
 
@@ -114,20 +151,20 @@ Redeploys using the existing stack's parameters. Useful for updating a stack wit
114
151
  Deletes a CloudFormation stack with a confirmation safeguard.
115
152
 
116
153
  ```bash
117
- npx awscfn delete-stack -n <STACK_NAME> -c <STACK_NAME>
154
+ awscfn delete-stack -n <STACK_NAME> -c <STACK_NAME>
118
155
  ```
119
156
 
120
- | Flag | Short | Description |
121
- |------|-------|-------------|
122
- | `--name` | `-n` | Stack name |
123
- | `--confirm` | `-c` | Repeat stack name to confirm |
157
+ | Flag | Description |
158
+ |------|-------------|
159
+ | `--name`, `-n` | Stack name |
160
+ | `--confirm`, `-c` | Repeat stack name to confirm |
124
161
 
125
- `-c` must match `-n` exactly to prevent accidental deletion.
162
+ `--confirm` must match `--name` exactly to prevent accidental deletion.
126
163
 
127
164
  **Example:**
128
165
 
129
166
  ```bash
130
- npx awscfn delete-stack -n my-app-prod -c my-app-prod
167
+ awscfn delete-stack -n my-app-prod -c my-app-prod
131
168
  ```
132
169
 
133
170
  If the stack doesn't exist, the command will exit with an error.
@@ -141,7 +178,7 @@ If the names don't match, the deletion will be aborted.
141
178
 
142
179
  ### 📋 `listStacks(): Promise<StackSummary[]>`
143
180
 
144
- Returns all CloudFormation stacks in the current region (paginated). Excludes `DELETE_COMPLETE` (AWS default). Each item is an AWS SDK `StackSummary` (e.g. `StackName`, `StackStatus`, `CreationTime`).
181
+ Returns all CloudFormation stacks in the current region (paginated). Excludes deleted stacks (`DELETE_COMPLETE`, `DELETE_IN_PROGRESS`) via `StackStatusFilter`. Each item is an AWS SDK `StackSummary` (e.g. `StackName`, `StackStatus`, `CreationTime`).
145
182
 
146
183
  ```ts
147
184
  import { listStacks } from 'awscfn';
package/bin/awscfn CHANGED
@@ -9,7 +9,7 @@ const { deleteStack } = require('../dist/deleteStack');
9
9
  const { listStacks } = require('../dist/listStacks');
10
10
  const { redeployStack } = require('../dist/redeployStack');
11
11
  const { updateStack } = require('../dist/updateStack');
12
- const { setOutputConfig } = require('../dist/lib/output');
12
+ const { getOutputConfig, setOutputConfig } = require('../dist/lib/output');
13
13
 
14
14
  const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8'));
15
15
  const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
@@ -74,7 +74,9 @@ async function runCommand(fn) {
74
74
  if (message !== err.message) {
75
75
  console.log(`\x1b[90m(original: ${err.message})\x1b[0m`);
76
76
  }
77
- logErrorDetails(err.data);
77
+ if (getOutputConfig().verbose) {
78
+ logErrorDetails(err.data);
79
+ }
78
80
  process.exit(1);
79
81
  }
80
82
  }
@@ -95,6 +97,7 @@ const confirmOpt = {
95
97
  yargs
96
98
  .option('ci', {
97
99
  type: 'boolean',
100
+ alias: 'C',
98
101
  description: 'CI mode (compact output). Auto-detected when CI=true or GITHUB_ACTIONS=true. Colors remain enabled in CI.',
99
102
  default: isCI,
100
103
  })
@@ -104,10 +107,17 @@ yargs
104
107
  description: 'Disable colored output',
105
108
  default: false,
106
109
  })
110
+ .option('verbose', {
111
+ type: 'boolean',
112
+ alias: 'V',
113
+ description: 'Show full error details (e.g. err.data JSON) on failure',
114
+ default: false,
115
+ })
107
116
  .middleware((argv) => {
108
117
  setOutputConfig({
109
118
  ci: argv.ci,
110
119
  color: !argv.noColor && (process.stdout.isTTY || argv.ci),
120
+ verbose: argv.verbose,
111
121
  });
112
122
  })
113
123
  .command(
@@ -123,7 +133,6 @@ yargs
123
133
  'Create a CloudFormation stack',
124
134
  (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt }),
125
135
  ({ name, template, params }) => {
126
- console.log(`Creating stack: ${name}...`);
127
136
  runCommand(() => createStack(name, template, params));
128
137
  }
129
138
  )
@@ -132,7 +141,6 @@ yargs
132
141
  'Delete a CloudFormation stack',
133
142
  (cmd) => cmd.options({ ...nameOpt, ...confirmOpt }),
134
143
  ({ name, confirm }) => {
135
- console.log(`Deleting stack: ${name}...`);
136
144
  runCommand(() => deleteStack(name, confirm));
137
145
  }
138
146
  )
@@ -141,7 +149,6 @@ yargs
141
149
  'Redeploy a CloudFormation stack (uses existing params)',
142
150
  (cmd) => cmd.options({ ...nameOpt, ...templateOpt }),
143
151
  ({ name, template }) => {
144
- console.log(`Redeploying stack: ${name}...`);
145
152
  runCommand(() => redeployStack(name, template));
146
153
  }
147
154
  )
@@ -150,7 +157,6 @@ yargs
150
157
  'Update a CloudFormation stack',
151
158
  (cmd) => cmd.options({ ...nameOpt, ...templateOpt, ...paramsOpt }),
152
159
  ({ name, template, params }) => {
153
- console.log(`Updating stack: ${name}...`);
154
160
  runCommand(() => updateStack(name, template, params));
155
161
  }
156
162
  )
@@ -1,6 +1,6 @@
1
1
  import { StackSummary } from '@aws-sdk/client-cloudformation';
2
2
  /**
3
- * Fetches all CloudFormation stacks (paginated). Excludes DELETE_COMPLETE by default (AWS behavior).
3
+ * Fetches all CloudFormation stacks (paginated). Excludes deleted stacks (DELETE_COMPLETE, DELETE_IN_PROGRESS).
4
4
  */
5
5
  export declare function listStacks(): Promise<StackSummary[]>;
6
6
  //# sourceMappingURL=listStacks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listStacks.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAG/E;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAkB1D"}
1
+ {"version":3,"file":"listStacks.d.ts","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAQ5F;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAqB1D"}
@@ -3,15 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listStacks = listStacks;
4
4
  const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
5
5
  const _1 = require(".");
6
+ /** All stack statuses except deleted (DELETE_COMPLETE, DELETE_IN_PROGRESS). */
7
+ const ACTIVE_STATUS_FILTER = Object.values(client_cloudformation_1.StackStatus).filter((s) => s !== client_cloudformation_1.StackStatus.DELETE_COMPLETE && s !== client_cloudformation_1.StackStatus.DELETE_IN_PROGRESS);
6
8
  /**
7
- * Fetches all CloudFormation stacks (paginated). Excludes DELETE_COMPLETE by default (AWS behavior).
9
+ * Fetches all CloudFormation stacks (paginated). Excludes deleted stacks (DELETE_COMPLETE, DELETE_IN_PROGRESS).
8
10
  */
9
11
  async function listStacks() {
10
12
  const cf = (0, _1.getCfClient)();
11
13
  const out = [];
12
14
  let nextToken;
13
15
  do {
14
- const result = await cf.send(new client_cloudformation_1.ListStacksCommand({ NextToken: nextToken }));
16
+ const result = await cf.send(new client_cloudformation_1.ListStacksCommand({
17
+ NextToken: nextToken,
18
+ StackStatusFilter: ACTIVE_STATUS_FILTER,
19
+ }));
15
20
  const summaries = result.StackSummaries ?? [];
16
21
  out.push(...summaries);
17
22
  nextToken = result.NextToken;
@@ -1 +1 @@
1
- {"version":3,"file":"listStacks.js","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":";;AAMA,gCAkBC;AAxBD,0EAA+E;AAC/E,wBAA8B;AAE9B;;GAEG;AACI,KAAK,UAAU,UAAU;IAE5B,MAAM,EAAE,GAAG,IAAA,cAAW,GAAE,CAAC;IACzB,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,IAAI,SAA6B,CAAC;IAElC,GAAG,CAAC;QAEA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,yCAAiB,CAAC,EAAC,SAAS,EAAE,SAAS,EAAC,CAAC,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;QAE9C,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QACvB,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAEjC,CAAC,QAAQ,SAAS,EAAE;IAEpB,OAAO,GAAG,CAAC;AAEf,CAAC"}
1
+ {"version":3,"file":"listStacks.js","sourceRoot":"","sources":["../../../src/lib/cfn/listStacks.ts"],"names":[],"mappings":";;AAWA,gCAqBC;AAhCD,0EAA4F;AAC5F,wBAA8B;AAE9B,+EAA+E;AAC/E,MAAM,oBAAoB,GAAmB,MAAM,CAAC,MAAM,CAAC,mCAAW,CAAmB,CAAC,MAAM,CAC5F,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,mCAAW,CAAC,eAAe,IAAI,CAAC,KAAK,mCAAW,CAAC,kBAAkB,CACnF,CAAC;AAEF;;GAEG;AACI,KAAK,UAAU,UAAU;IAE5B,MAAM,EAAE,GAAG,IAAA,cAAW,GAAE,CAAC;IACzB,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,IAAI,SAA6B,CAAC;IAElC,GAAG,CAAC;QAEA,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,yCAAiB,CAAC;YAC/C,SAAS,EAAE,SAAS;YACpB,iBAAiB,EAAE,oBAAoB;SAC1C,CAAC,CAAC,CAAC;QACJ,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;QAE9C,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QACvB,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAEjC,CAAC,QAAQ,SAAS,EAAE;IAEpB,OAAO,GAAG,CAAC;AAEf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "awscfn",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
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",