@davidorex/pi-context-cli 0.30.0 → 0.31.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.
- package/CHANGELOG.md +37 -0
- package/README.md +127 -7
- package/dist/bin.js +0 -0
- package/dist/cli.d.ts +118 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +584 -30
- package/dist/cli.js.map +1 -1
- package/dist/pi-bound.d.ts +119 -0
- package/dist/pi-bound.d.ts.map +1 -0
- package/dist/pi-bound.js +257 -0
- package/dist/pi-bound.js.map +1 -0
- package/dist/render.d.ts +57 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +95 -0
- package/dist/render.js.map +1 -0
- package/package.json +4 -3
package/dist/render.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural guard for a pi-context {@link ValidationError}.
|
|
3
|
+
*
|
|
4
|
+
* `instanceof ValidationError` is UNRELIABLE across this package boundary: the op
|
|
5
|
+
* registry reaches `schema-validator` through one module-resolution path and the
|
|
6
|
+
* CLI imports the class through the `@davidorex/pi-context/schema-validator`
|
|
7
|
+
* subpath export — Node can give these two distinct class objects, so a real
|
|
8
|
+
* ValidationError thrown by an op fails `instanceof` here (observed: `e.name` ===
|
|
9
|
+
* "ValidationError" yet `e instanceof ValidationError` === false). Detect by the
|
|
10
|
+
* stable shape instead: a `name` of "ValidationError" carrying the `errors`
|
|
11
|
+
* (AJV `ErrorObject[]`) and `label` fields `formatAjvError` reads.
|
|
12
|
+
*/
|
|
13
|
+
export function isValidationError(err) {
|
|
14
|
+
return (err instanceof Error &&
|
|
15
|
+
err.name === "ValidationError" &&
|
|
16
|
+
Array.isArray(err.errors) &&
|
|
17
|
+
typeof err.label === "string");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render an array of objects as a compact markdown table.
|
|
21
|
+
*
|
|
22
|
+
* Lifted from `scripts/orchestrator/filter-block-items.ts`'s `renderTable` so the
|
|
23
|
+
* `--format table` CLI surface produces the same projection the script twin does.
|
|
24
|
+
* Column selection is best-effort terse: `id` first when present, then up to three
|
|
25
|
+
* more keys from the first row (≤4 columns total); if the first row has no `id`,
|
|
26
|
+
* the first four keys. Cells: null/undefined → empty; strings verbatim; non-string
|
|
27
|
+
* values `JSON.stringify`'d; internal newlines collapsed to a single space; capped
|
|
28
|
+
* at 80 chars (>80 → first 77 + "...").
|
|
29
|
+
*
|
|
30
|
+
* Non-array / empty inputs are NOT a table: an empty array (or any non-array) yields
|
|
31
|
+
* the sentinel `"(no rows)"` so the dispatch layer can fall back to text rather than
|
|
32
|
+
* emit a degenerate table.
|
|
33
|
+
*/
|
|
34
|
+
export function renderTable(rows) {
|
|
35
|
+
if (!Array.isArray(rows) || rows.length === 0)
|
|
36
|
+
return "(no rows)";
|
|
37
|
+
const first = rows[0];
|
|
38
|
+
const keys = Object.keys(first);
|
|
39
|
+
const hasId = keys.includes("id");
|
|
40
|
+
const others = keys.filter((k) => k !== "id").slice(0, 3);
|
|
41
|
+
const cols = hasId ? ["id", ...others] : keys.slice(0, 4);
|
|
42
|
+
const header = `| ${cols.join(" | ")} |`;
|
|
43
|
+
const sep = `| ${cols.map(() => "---").join(" | ")} |`;
|
|
44
|
+
const body = rows.map((raw) => {
|
|
45
|
+
const it = raw;
|
|
46
|
+
return `| ${cols
|
|
47
|
+
.map((c) => {
|
|
48
|
+
const v = it[c];
|
|
49
|
+
if (v === undefined || v === null)
|
|
50
|
+
return "";
|
|
51
|
+
const s = typeof v === "string" ? v : JSON.stringify(v);
|
|
52
|
+
const oneLine = s.replace(/\s*\n\s*/g, " ");
|
|
53
|
+
return oneLine.length > 80 ? `${oneLine.slice(0, 77)}...` : oneLine;
|
|
54
|
+
})
|
|
55
|
+
.join(" | ")} |`;
|
|
56
|
+
});
|
|
57
|
+
return [header, sep, ...body].join("\n");
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Translate an AJV {@link ValidationError} into field-named guidance.
|
|
61
|
+
*
|
|
62
|
+
* The raw `ValidationError.message` concatenates AJV's terse `instancePath: message`
|
|
63
|
+
* fragments (e.g. "must have required property 'package'"), which name the JSON
|
|
64
|
+
* pointer but bury the actionable field name and constraint. This re-shapes each
|
|
65
|
+
* `err.errors[]` AJV `ErrorObject` into one guidance line per error, keyword-aware:
|
|
66
|
+
* - required → `<path>`: missing required field `<missingProperty>`
|
|
67
|
+
* - type → `<path>`: expected <type>
|
|
68
|
+
* - enum → `<path>`: must be one of <allowedValues…>
|
|
69
|
+
* - additionalProperties → `<path>`: unexpected property `<additionalProperty>`
|
|
70
|
+
* - (any other keyword) → `<path>`: <raw message>
|
|
71
|
+
* Segments join with "; " — one segment per error, so the error COUNT is never
|
|
72
|
+
* dropped — and the whole is prefixed `validation failed for <label>: …`.
|
|
73
|
+
*/
|
|
74
|
+
export function formatAjvError(err) {
|
|
75
|
+
const segments = err.errors.map((e) => {
|
|
76
|
+
const at = e.instancePath || "/";
|
|
77
|
+
const params = (e.params ?? {});
|
|
78
|
+
switch (e.keyword) {
|
|
79
|
+
case "required":
|
|
80
|
+
return `\`${at}\`: missing required field \`${String(params.missingProperty)}\``;
|
|
81
|
+
case "type":
|
|
82
|
+
return `\`${at}\`: expected ${String(params.type)}`;
|
|
83
|
+
case "enum": {
|
|
84
|
+
const allowed = Array.isArray(params.allowedValues) ? params.allowedValues.join(", ") : "";
|
|
85
|
+
return `\`${at}\`: must be one of ${allowed}`;
|
|
86
|
+
}
|
|
87
|
+
case "additionalProperties":
|
|
88
|
+
return `\`${at}\`: unexpected property \`${String(params.additionalProperty)}\``;
|
|
89
|
+
default:
|
|
90
|
+
return `\`${at}\`: ${e.message ?? "invalid"}`;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return `validation failed for ${err.label}: ${segments.join("; ")}`;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@davidorex/pi-context-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -28,12 +28,13 @@
|
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
30
|
"clean": "rm -rf dist",
|
|
31
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
31
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && chmod +x dist/bin.js",
|
|
32
32
|
"prepublishOnly": "npm run clean && npm run build",
|
|
33
33
|
"test": "tsx --test src/*.test.ts"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@davidorex/pi-context": "^0.
|
|
36
|
+
"@davidorex/pi-context": "^0.31.0",
|
|
37
|
+
"@davidorex/pi-project-workflows": "^0.31.0",
|
|
37
38
|
"typebox": "^1.1.24"
|
|
38
39
|
},
|
|
39
40
|
"engines": {
|