unoverse 0.1.103 → 0.1.104

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.
@@ -141,26 +141,43 @@ process.stdin.on("end", () => {
141
141
 
142
142
  const groups = { create: [], update: [], delete: [], replace: [] };
143
143
  const supporting = { create: 0, update: 0, delete: 0, replace: 0 };
144
+ // LOSING SOMETHING IS NEVER ANONYMOUS. Counting the plumbing is right when things are
145
+ // being built — nobody needs eleven IAM attachments enumerated. It is wrong the moment
146
+ // anything is destroyed or replaced: "plus 1 supporting resource" was a security group
147
+ // about to be deleted, and the operator hit Ctrl-C when Terraform printed "Destroying"
148
+ // for something the summary had not named. Anything being taken away is listed.
149
+ const named = { delete: [], replace: [] };
144
150
 
145
151
  for (const r of plan.resource_changes ?? []) {
146
152
  const act = action(r.change ?? {});
147
153
  if (!act) continue;
148
154
  const d = describe(r);
149
155
  if (d) groups[act].push(d);
150
- else supporting[act]++;
156
+ else if (act === "delete" || act === "replace") {
157
+ // Turn the terraform type into something readable: aws_security_group → security group
158
+ const label = r.type.replace(/^(aws|digitalocean|random|time|archive)_/, "").replace(/_/g, " ");
159
+ const v = r.change?.before ?? r.change?.after ?? {};
160
+ named[act].push({ what: label.charAt(0).toUpperCase() + label.slice(1), detail: v.name ?? v.id ?? "" });
161
+ } else supporting[act]++;
151
162
  }
152
163
 
153
- const total = Object.values(groups).flat().length + Object.values(supporting).reduce((a, b) => a + b, 0);
164
+ const total = Object.values(groups).flat().length
165
+ + Object.values(supporting).reduce((a, b) => a + b, 0)
166
+ + named.delete.length + named.replace.length;
154
167
  const out = [];
155
168
  if (total === 0) {
156
169
  console.log(`\n ${green("●")} Your infrastructure already matches. Nothing to change.\n`);
157
170
  return;
158
171
  }
159
172
 
160
- const width = Math.max(...Object.values(groups).flat().map((d) => d.what.length), 0) + 2;
173
+ const width = Math.max(
174
+ ...Object.values(groups).flat().map((d) => d.what.length),
175
+ ...named.delete.map((d) => d.what.length),
176
+ ...named.replace.map((d) => d.what.length),
177
+ 0) + 2;
161
178
 
162
179
  for (const act of ["create", "update", "replace", "delete"]) {
163
- const list = groups[act];
180
+ const list = [...groups[act], ...(named[act] ?? [])];
164
181
  const extra = supporting[act];
165
182
  if (!list.length && !extra) continue;
166
183
  const colour = act === "delete" || act === "replace" ? red : act === "update" ? yellow : green;
@@ -194,6 +211,6 @@ process.stdin.on("end", () => {
194
211
  // something is not. `process.exitCode` rather than `process.exit`, which can cut off
195
212
  // the output above while it is still draining down a pipe.
196
213
  const destructive =
197
- groups.delete.length + groups.replace.length + supporting.delete + supporting.replace;
214
+ groups.delete.length + groups.replace.length + named.delete.length + named.replace.length;
198
215
  if (destructive) process.exitCode = 3;
199
216
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unoverse",
3
- "version": "0.1.103",
3
+ "version": "0.1.104",
4
4
  "description": "The Unoverse front door — create a Studio project, a universe, or a client app, and launch Studio.",
5
5
  "license": "SEE LICENSE IN README.md",
6
6
  "type": "module",