@ted-galago/wave-cli 0.1.6 → 0.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ted-galago/wave-cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "wave": "dist/index.js"
@@ -61,7 +61,15 @@ function classify(result) {
61
61
  if (!result.parsed) {
62
62
  return { ok: false, reason: "non_json_output" };
63
63
  }
64
+ const embeddedError = findFirstEmbeddedErrors(result.parsed);
64
65
  if (result.parsed.ok === true) {
66
+ if (embeddedError) {
67
+ return {
68
+ ok: false,
69
+ reason: "embedded_errors",
70
+ details: { path: embeddedError.path, sample: embeddedError.sample }
71
+ };
72
+ }
65
73
  return { ok: true, reason: "ok" };
66
74
  }
67
75
 
@@ -97,6 +105,70 @@ function classify(result) {
97
105
  return { ok: true, reason: `reachable_${code}` };
98
106
  }
99
107
 
108
+ function isNonEmptyErrorsValue(value) {
109
+ if (value === null || value === undefined) return false;
110
+ if (Array.isArray(value)) {
111
+ if (value.length === 0) return false;
112
+ return value.some((entry) => {
113
+ if (entry === null || entry === undefined) return false;
114
+ if (typeof entry === "string") return entry.trim().length > 0;
115
+ if (typeof entry === "object") return Object.keys(entry).length > 0;
116
+ return true;
117
+ });
118
+ }
119
+ if (typeof value === "string") return value.trim().length > 0;
120
+ if (typeof value === "object") return Object.keys(value).length > 0;
121
+ return true;
122
+ }
123
+
124
+ function summarizeValue(value) {
125
+ try {
126
+ if (typeof value === "string") return value.slice(0, 160);
127
+ const serialized = JSON.stringify(value);
128
+ if (typeof serialized !== "string") return String(value);
129
+ return serialized.slice(0, 300);
130
+ } catch {
131
+ return String(value);
132
+ }
133
+ }
134
+
135
+ function findFirstEmbeddedErrors(input) {
136
+ const queue = [{ value: input, path: "$", depth: 0 }];
137
+ const maxDepth = 12;
138
+ const maxNodes = 2000;
139
+ let visited = 0;
140
+
141
+ while (queue.length > 0) {
142
+ const current = queue.shift();
143
+ if (!current) break;
144
+ visited += 1;
145
+ if (visited > maxNodes) break;
146
+
147
+ const { value, path, depth } = current;
148
+ if (!value || typeof value !== "object") continue;
149
+
150
+ if (Array.isArray(value)) {
151
+ if (depth >= maxDepth) continue;
152
+ for (let i = 0; i < value.length; i += 1) {
153
+ queue.push({ value: value[i], path: `${path}[${i}]`, depth: depth + 1 });
154
+ }
155
+ continue;
156
+ }
157
+
158
+ for (const [key, nested] of Object.entries(value)) {
159
+ const nextPath = `${path}.${key}`;
160
+ if (key === "errors" && isNonEmptyErrorsValue(nested)) {
161
+ return { path: nextPath, sample: summarizeValue(nested) };
162
+ }
163
+ if (depth < maxDepth && nested && typeof nested === "object") {
164
+ queue.push({ value: nested, path: nextPath, depth: depth + 1 });
165
+ }
166
+ }
167
+ }
168
+
169
+ return null;
170
+ }
171
+
100
172
  function payload(root, attrs) {
101
173
  return JSON.stringify({ [root]: attrs });
102
174
  }
@@ -597,7 +669,10 @@ for (const res of results) {
597
669
  const cmd = res.args.join(" ");
598
670
  const status = res.parsed?.status ?? "n/a";
599
671
  const errCode = res.parsed?.error?.code ?? "none";
600
- lines.push(`${verdict.ok ? "PASS" : "FAIL"} | status=${status} | err=${errCode} | ${cmd}`);
672
+ const reasonDetail = verdict.details ? ` (${JSON.stringify(verdict.details)})` : "";
673
+ lines.push(
674
+ `${verdict.ok ? "PASS" : "FAIL"} | status=${status} | err=${errCode} | reason=${verdict.reason}${reasonDetail} | ${cmd}`
675
+ );
601
676
  if (!verdict.ok) failures += 1;
602
677
  }
603
678