@procedures/mark 0.33.0 → 0.35.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 +108 -0
- package/README.md +2 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/args.d.ts +5 -53
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +9 -341
- package/dist/args.js.map +1 -1
- package/dist/ask.d.ts +3 -38
- package/dist/ask.d.ts.map +1 -1
- package/dist/ask.js +3 -81
- package/dist/ask.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -64
- package/dist/cli.js.map +1 -1
- package/dist/client-mode.js +3 -3
- package/dist/client-mode.js.map +1 -1
- package/dist/failure.d.ts +3 -2
- package/dist/failure.d.ts.map +1 -1
- package/dist/failure.js +3 -33
- package/dist/failure.js.map +1 -1
- package/dist/format.d.ts +3 -25
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +3 -120
- package/dist/format.js.map +1 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +3 -9
- package/dist/manifest.js.map +1 -1
- package/dist/manifest.json +23 -21
- package/dist/parse.d.ts +4 -114
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +7 -445
- package/dist/parse.js.map +1 -1
- package/package.json +50 -50
- package/src/args.ts +14 -403
- package/src/ask.ts +14 -109
- package/src/cli.ts +16 -70
- package/src/client-mode.ts +3 -3
- package/src/failure.ts +3 -33
- package/src/format.ts +3 -172
- package/src/manifest.ts +3 -8
- package/src/parse.ts +33 -570
- package/dist/prompts.d.ts +0 -58
- package/dist/prompts.d.ts.map +0 -1
- package/dist/prompts.js +0 -124
- package/dist/prompts.js.map +0 -1
- package/src/prompts.ts +0 -181
package/src/client-mode.ts
CHANGED
|
@@ -61,7 +61,7 @@ export async function cliServerConnection(
|
|
|
61
61
|
try {
|
|
62
62
|
// Dynamic import client
|
|
63
63
|
const clientModule = await import("@procedures/client");
|
|
64
|
-
const { Client, HttpTransport } = clientModule;
|
|
64
|
+
const { Client, HttpTransport, pathToMethod } = clientModule;
|
|
65
65
|
|
|
66
66
|
// Connect to server
|
|
67
67
|
const transport = new HttpTransport({
|
|
@@ -72,8 +72,8 @@ export async function cliServerConnection(
|
|
|
72
72
|
|
|
73
73
|
// The method of the path as ProcedureServer registers it: the last segment is the operation.
|
|
74
74
|
// (Before, the first segment was the service, so a path of three segments - docker compose up -
|
|
75
|
-
// was not found on the server.)
|
|
76
|
-
method =
|
|
75
|
+
// was not found on the server.) The core mapping encodes a dot in a segment (roadmap CLI-75).
|
|
76
|
+
method = pathToMethod(path);
|
|
77
77
|
} catch {
|
|
78
78
|
// Nothing was sent to the server yet - fall back to local execution
|
|
79
79
|
return null;
|
package/src/failure.ts
CHANGED
|
@@ -10,38 +10,8 @@
|
|
|
10
10
|
* runs an external command (`vitest run`, `shell run`), so the caller sees the command's result.
|
|
11
11
|
*
|
|
12
12
|
* For a streaming procedure, each item is examined: one failed item makes the command fail.
|
|
13
|
+
*
|
|
14
|
+
* The code is in `@procedures/cli-kit` (roadmap O61).
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
export function failureOf(result: unknown): string | undefined {
|
|
17
|
-
if (!result || typeof result !== "object" || Array.isArray(result)) {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
const record = result as Record<string, unknown>;
|
|
21
|
-
const exitCode = record["exitCode"];
|
|
22
|
-
if (typeof exitCode === "number" && exitCode !== 0) {
|
|
23
|
-
return `exit code ${exitCode}`;
|
|
24
|
-
}
|
|
25
|
-
if (record["success"] === false) {
|
|
26
|
-
return firstText(record["error"]) ?? firstText(record["errors"]) ?? firstText(record["message"]) ?? "success: false";
|
|
27
|
-
}
|
|
28
|
-
return undefined;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** The first text of a value: a string, the message of an error object, or the first of a list */
|
|
32
|
-
function firstText(value: unknown): string | undefined {
|
|
33
|
-
if (typeof value === "string" && value.length > 0) {
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
if (Array.isArray(value)) {
|
|
37
|
-
for (const item of value) {
|
|
38
|
-
const text = firstText(item);
|
|
39
|
-
if (text) return text;
|
|
40
|
-
}
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
if (value && typeof value === "object" && typeof (value as { message?: unknown }).message === "string") {
|
|
44
|
-
return (value as { message: string }).message;
|
|
45
|
-
}
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
17
|
+
export { failureOf } from "@procedures/cli-kit";
|
package/src/format.ts
CHANGED
|
@@ -1,177 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Output Formatting
|
|
3
3
|
*
|
|
4
|
-
* Formats procedure results for CLI output based on metadata hints.
|
|
4
|
+
* Formats procedure results for CLI output based on metadata hints. The code is in
|
|
5
|
+
* `@procedures/cli-kit` (roadmap O61).
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
export type OutputFormat
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Print interface (used by formatOutput)
|
|
11
|
-
*/
|
|
12
|
-
export interface Print {
|
|
13
|
-
info: (message: string) => void;
|
|
14
|
-
error: (message: string) => void;
|
|
15
|
-
success: (message: string) => void;
|
|
16
|
-
warning: (message: string) => void;
|
|
17
|
-
table: (data: string[][], options?: { format?: string }) => void;
|
|
18
|
-
spin: (message: string) => Spinner;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface Spinner {
|
|
22
|
-
stop: () => void;
|
|
23
|
-
succeed: (message?: string) => void;
|
|
24
|
-
fail: (message?: string) => void;
|
|
25
|
-
text: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Format and print the result based on output format hint
|
|
30
|
-
*/
|
|
31
|
-
export function formatOutput(
|
|
32
|
-
print: Print,
|
|
33
|
-
result: unknown,
|
|
34
|
-
format: OutputFormat = "text"
|
|
35
|
-
): void {
|
|
36
|
-
if (result === undefined || result === null) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
switch (format) {
|
|
41
|
-
case "json":
|
|
42
|
-
print.info(JSON.stringify(result, null, 2));
|
|
43
|
-
break;
|
|
44
|
-
|
|
45
|
-
case "table":
|
|
46
|
-
formatTable(print, result);
|
|
47
|
-
break;
|
|
48
|
-
|
|
49
|
-
case "text":
|
|
50
|
-
case "streaming":
|
|
51
|
-
default:
|
|
52
|
-
formatText(print, result);
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Format as text - handles common result shapes
|
|
59
|
-
*/
|
|
60
|
-
function formatText(print: Print, result: unknown): void {
|
|
61
|
-
// String output
|
|
62
|
-
if (typeof result === "string") {
|
|
63
|
-
print.info(result);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Result with output field (common pattern)
|
|
68
|
-
if (isObjectWithOutput(result)) {
|
|
69
|
-
print.info(result.output);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Result with message field
|
|
74
|
-
if (isObjectWithMessage(result)) {
|
|
75
|
-
if (result.success === false) {
|
|
76
|
-
print.error(result.message);
|
|
77
|
-
} else {
|
|
78
|
-
print.success(result.message);
|
|
79
|
-
}
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Result with error field
|
|
84
|
-
if (isObjectWithError(result)) {
|
|
85
|
-
print.error(result.error);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Array of items
|
|
90
|
-
if (Array.isArray(result)) {
|
|
91
|
-
for (const item of result) {
|
|
92
|
-
formatText(print, item);
|
|
93
|
-
}
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Fallback to JSON
|
|
98
|
-
print.info(JSON.stringify(result, null, 2));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Format as table - handles arrays of objects
|
|
103
|
-
*/
|
|
104
|
-
function formatTable(print: Print, result: unknown): void {
|
|
105
|
-
// Result with rows/headers
|
|
106
|
-
if (isTableResult(result)) {
|
|
107
|
-
const headers = result.headers ?? Object.keys(result.rows[0] ?? {});
|
|
108
|
-
const data: string[][] = [headers];
|
|
109
|
-
|
|
110
|
-
for (const row of result.rows) {
|
|
111
|
-
if (Array.isArray(row)) {
|
|
112
|
-
data.push(row.map(String));
|
|
113
|
-
} else if (typeof row === "object" && row !== null) {
|
|
114
|
-
data.push(headers.map((h) => String((row as Record<string, unknown>)[h] ?? "")));
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
print.table(data);
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Plain array of objects
|
|
123
|
-
if (Array.isArray(result) && result.length > 0 && typeof result[0] === "object") {
|
|
124
|
-
const headers = Object.keys(result[0] as object);
|
|
125
|
-
const data: string[][] = [headers];
|
|
126
|
-
|
|
127
|
-
for (const row of result) {
|
|
128
|
-
if (typeof row === "object" && row !== null) {
|
|
129
|
-
data.push(headers.map((h) => String((row as Record<string, unknown>)[h] ?? "")));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
print.table(data);
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Fallback to text
|
|
138
|
-
formatText(print, result);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Type guards
|
|
142
|
-
|
|
143
|
-
function isObjectWithOutput(val: unknown): val is { output: string } {
|
|
144
|
-
return (
|
|
145
|
-
typeof val === "object" &&
|
|
146
|
-
val !== null &&
|
|
147
|
-
"output" in val &&
|
|
148
|
-
typeof (val as { output: unknown }).output === "string"
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function isObjectWithMessage(val: unknown): val is { message: string; success?: boolean } {
|
|
153
|
-
return (
|
|
154
|
-
typeof val === "object" &&
|
|
155
|
-
val !== null &&
|
|
156
|
-
"message" in val &&
|
|
157
|
-
typeof (val as { message: unknown }).message === "string"
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function isObjectWithError(val: unknown): val is { error: string } {
|
|
162
|
-
return (
|
|
163
|
-
typeof val === "object" &&
|
|
164
|
-
val !== null &&
|
|
165
|
-
"error" in val &&
|
|
166
|
-
typeof (val as { error: unknown }).error === "string"
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function isTableResult(val: unknown): val is { rows: unknown[]; headers?: string[] } {
|
|
171
|
-
return (
|
|
172
|
-
typeof val === "object" &&
|
|
173
|
-
val !== null &&
|
|
174
|
-
"rows" in val &&
|
|
175
|
-
Array.isArray((val as { rows: unknown }).rows)
|
|
176
|
-
);
|
|
177
|
-
}
|
|
8
|
+
export { formatOutput, type OutputFormat, type Print, type Spinner } from "@procedures/cli-kit";
|
package/src/manifest.ts
CHANGED
|
@@ -18,6 +18,7 @@ import * as fs from "node:fs";
|
|
|
18
18
|
import * as path from "node:path";
|
|
19
19
|
import { fileURLToPath } from "node:url";
|
|
20
20
|
import { describeProcedureEntry, jsonSchemaOf, type AnyProcedure, type ProcedureEntry } from "@procedures/client";
|
|
21
|
+
import { writeFileAtomicSync } from "@procedures/fs/files";
|
|
21
22
|
import { discoverFromEcosystem, findWorkspaceRoot } from "./ecosystem.js";
|
|
22
23
|
import { extractSchemaFields, resultFieldsOfSchema, type CLIMeta, type SchemaFieldInfo } from "./parse.js";
|
|
23
24
|
|
|
@@ -140,14 +141,8 @@ export async function writeManifest(procedures: readonly AnyProcedure[], file: s
|
|
|
140
141
|
generatedAt: new Date().toISOString(),
|
|
141
142
|
commands: await commandsOf(procedures),
|
|
142
143
|
};
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
fs.renameSync(temporary, file);
|
|
147
|
-
} catch (error) {
|
|
148
|
-
fs.rmSync(temporary, { force: true });
|
|
149
|
-
throw error;
|
|
150
|
-
}
|
|
144
|
+
// writeFileAtomicSync flushes the file, tries the rename again on Windows and removes the temporary file after a failure
|
|
145
|
+
writeFileAtomicSync(file, toJson(manifest));
|
|
151
146
|
return manifest;
|
|
152
147
|
}
|
|
153
148
|
|