@tolinax/ayoune-cli 2026.11.1 → 2026.11.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/lib/commands/createProgram.js +11 -0
- package/lib/commands/createServicesCommand.js +9 -5
- package/lib/helpers/handleResponseFormatOptions.js +21 -9
- package/lib/operations/handleAuditOperation.js +5 -4
- package/lib/operations/handleCopySingleOperation.js +8 -6
- package/lib/operations/handleCreateSingleOperation.js +8 -7
- package/lib/operations/handleGetOperation.js +6 -2
- package/lib/operations/handleGetSingleOperation.js +5 -3
- package/lib/operations/handleListOperation.js +10 -4
- package/lib/operations/handleSingleAuditOperation.js +8 -7
- package/package.json +1 -1
|
@@ -214,6 +214,7 @@ function installPreActionHook(program) {
|
|
|
214
214
|
*/
|
|
215
215
|
function installGlobalOptions(program) {
|
|
216
216
|
program
|
|
217
|
+
.name("ay")
|
|
217
218
|
.version(pkg.version || "0.0.0")
|
|
218
219
|
.addOption(new Option("-r, --responseFormat <format>", "Set the output format")
|
|
219
220
|
.choices(["json", "csv", "yaml", "table"])
|
|
@@ -292,6 +293,16 @@ export async function createProgram(program) {
|
|
|
292
293
|
// Lightweight stubs for every command so the help listing is complete and
|
|
293
294
|
// commander can suggest similar names for typos.
|
|
294
295
|
registerStubsForHelp(program);
|
|
296
|
+
// Bare `ay` (no args) should print help and exit cleanly. Commander's
|
|
297
|
+
// default behaviour is to print help then exit with code 1, treating
|
|
298
|
+
// "no command" as a usage error. For an end-user CLI that's hostile —
|
|
299
|
+
// a user typing `ay` to discover the tool gets a non-zero exit, which
|
|
300
|
+
// breaks shell scripts that gate on `ay && ...`. Force exit 0 here for
|
|
301
|
+
// the bare invocation.
|
|
302
|
+
if (process.argv.length <= 2) {
|
|
303
|
+
program.outputHelp();
|
|
304
|
+
process.exit(0);
|
|
305
|
+
}
|
|
295
306
|
}
|
|
296
307
|
else if (kind === "cmdHelp" || kind === "command") {
|
|
297
308
|
if (spec) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
2
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
2
|
+
import { handleResponseFormatOptions, printFormattedResponse, } from "../helpers/handleResponseFormatOptions.js";
|
|
3
3
|
import { saveFile } from "../helpers/saveFile.js";
|
|
4
4
|
import { spinner } from "../../index.js";
|
|
5
5
|
import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
|
|
@@ -56,9 +56,10 @@ export function createServicesCommand(program) {
|
|
|
56
56
|
payload: services,
|
|
57
57
|
meta: { responseTime: 0, pageInfo: { totalEntries: services.length, page: 1, totalPages: 1 } },
|
|
58
58
|
};
|
|
59
|
-
handleResponseFormatOptions(opts, res);
|
|
59
|
+
const formatted = handleResponseFormatOptions(opts, res, { noPrint: true });
|
|
60
60
|
spinner.success({ text: `Found ${services.length} services` });
|
|
61
61
|
spinner.stop();
|
|
62
|
+
printFormattedResponse(opts, formatted);
|
|
62
63
|
if (opts.save)
|
|
63
64
|
await saveFile("services-list", opts, res);
|
|
64
65
|
}
|
|
@@ -104,9 +105,10 @@ Examples:
|
|
|
104
105
|
payload: endpoints,
|
|
105
106
|
meta: { responseTime: 0, pageInfo: { totalEntries: endpoints.length, page: 1, totalPages: 1 } },
|
|
106
107
|
};
|
|
107
|
-
handleResponseFormatOptions(opts, formattedRes);
|
|
108
|
+
const formatted = handleResponseFormatOptions(opts, formattedRes, { noPrint: true });
|
|
108
109
|
spinner.success({ text: `Found ${endpoints.length} endpoints on ${host}` });
|
|
109
110
|
spinner.stop();
|
|
111
|
+
printFormattedResponse(opts, formatted);
|
|
110
112
|
if (opts.save)
|
|
111
113
|
await saveFile("service-endpoints", opts, formattedRes);
|
|
112
114
|
}
|
|
@@ -168,9 +170,10 @@ Examples:
|
|
|
168
170
|
pageInfo: { totalEntries: payload.length, page: 1, totalPages: 1 },
|
|
169
171
|
},
|
|
170
172
|
};
|
|
171
|
-
handleResponseFormatOptions(opts, res);
|
|
173
|
+
const formatted = handleResponseFormatOptions(opts, res, { noPrint: true });
|
|
172
174
|
spinner.success({ text: `${healthy}/${uniqueTargets.length} services healthy` });
|
|
173
175
|
spinner.stop();
|
|
176
|
+
printFormattedResponse(opts, formatted);
|
|
174
177
|
if (opts.save)
|
|
175
178
|
await saveFile("services-health", opts, res);
|
|
176
179
|
}
|
|
@@ -216,9 +219,10 @@ Examples:
|
|
|
216
219
|
payload: description,
|
|
217
220
|
meta: { responseTime: 0 },
|
|
218
221
|
};
|
|
219
|
-
handleResponseFormatOptions(opts, formattedRes);
|
|
222
|
+
const formatted = handleResponseFormatOptions(opts, formattedRes, { noPrint: true });
|
|
220
223
|
spinner.success({ text: `Module: ${moduleName} — ${moduleActions.length} endpoints` });
|
|
221
224
|
spinner.stop();
|
|
225
|
+
printFormattedResponse(opts, formatted);
|
|
222
226
|
}
|
|
223
227
|
catch (e) {
|
|
224
228
|
cliError(e.message || "Failed to describe service", EXIT_GENERAL_ERROR);
|
|
@@ -32,7 +32,23 @@ function filterColumns(data, columns) {
|
|
|
32
32
|
}
|
|
33
33
|
return data;
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Print a previously-computed formatted response to stdout. Mirrors the
|
|
37
|
+
* print branch of `handleResponseFormatOptions` exactly. Call this AFTER
|
|
38
|
+
* `spinner.success(...)` / `spinner.stop()` so the data block appears below
|
|
39
|
+
* the spinner status line, not before it.
|
|
40
|
+
*/
|
|
41
|
+
export function printFormattedResponse(opts, formatted) {
|
|
42
|
+
if (opts.quiet)
|
|
43
|
+
return;
|
|
44
|
+
if (opts.responseFormat === "table") {
|
|
45
|
+
console.table(formatted.result);
|
|
46
|
+
}
|
|
47
|
+
else if (formatted.content !== undefined) {
|
|
48
|
+
console.log(formatted.content);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export function handleResponseFormatOptions(opts, res, formatOpts = {}) {
|
|
36
52
|
let plainResult;
|
|
37
53
|
let result;
|
|
38
54
|
let meta = {};
|
|
@@ -122,13 +138,9 @@ export function handleResponseFormatOptions(opts, res) {
|
|
|
122
138
|
else {
|
|
123
139
|
content = JSON.stringify(result, null, 4);
|
|
124
140
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
else if (content !== undefined) {
|
|
130
|
-
console.log(content);
|
|
131
|
-
}
|
|
141
|
+
const formatted = { plainResult, result, meta, content };
|
|
142
|
+
if (!formatOpts.noPrint) {
|
|
143
|
+
printFormattedResponse(opts, formatted);
|
|
132
144
|
}
|
|
133
|
-
return
|
|
145
|
+
return formatted;
|
|
134
146
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Operation handling functions
|
|
2
2
|
import { spinner } from "../../index.js";
|
|
3
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
3
|
+
import { handleResponseFormatOptions, printFormattedResponse, } from "../helpers/handleResponseFormatOptions.js";
|
|
4
4
|
import { localStorage } from "../helpers/localStorage.js";
|
|
5
5
|
import { auditCallHandler } from "../api/auditCallHandler.js";
|
|
6
6
|
export async function handleAuditOperation(collection, id, opts) {
|
|
@@ -12,11 +12,12 @@ export async function handleAuditOperation(collection, id, opts) {
|
|
|
12
12
|
responseFormat: opts.responseFormat,
|
|
13
13
|
verbosity: opts.verbosity,
|
|
14
14
|
});
|
|
15
|
-
|
|
15
|
+
const formatted = handleResponseFormatOptions({ ...opts }, res, { noPrint: true });
|
|
16
16
|
spinner.success({
|
|
17
17
|
text: `Got Audit ${id} in ${collection}`,
|
|
18
18
|
});
|
|
19
19
|
spinner.stop();
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
printFormattedResponse({ ...opts }, formatted);
|
|
21
|
+
localStorage.setItem("lastId", formatted.result._id);
|
|
22
|
+
return { data: formatted.plainResult, content: formatted.content, result: formatted.result, meta: formatted.meta };
|
|
22
23
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Operation handling functions
|
|
2
2
|
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
3
3
|
import { spinner } from "../../index.js";
|
|
4
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
4
|
+
import { handleResponseFormatOptions, printFormattedResponse, } from "../helpers/handleResponseFormatOptions.js";
|
|
5
5
|
import { localStorage } from "../helpers/localStorage.js";
|
|
6
6
|
export async function handleCopySingleOperation(module, collection, id, opts) {
|
|
7
|
+
var _a, _b;
|
|
7
8
|
spinner.start({
|
|
8
9
|
text: `Copying entry ${id} in [${collection}]`,
|
|
9
10
|
color: "magenta",
|
|
@@ -18,13 +19,14 @@ export async function handleCopySingleOperation(module, collection, id, opts) {
|
|
|
18
19
|
spinner.stop();
|
|
19
20
|
return { data: null, content: null, result: null, meta: {} };
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
const newId = (result === null ||
|
|
22
|
+
const formatted = handleResponseFormatOptions({ ...opts }, res, { noPrint: true });
|
|
23
|
+
const newId = ((_a = formatted.result) === null || _a === void 0 ? void 0 : _a._id) || "unknown";
|
|
23
24
|
spinner.success({
|
|
24
25
|
text: `Copied entry ${id} in ${collection}: New ID [${newId}]`,
|
|
25
26
|
});
|
|
26
27
|
spinner.stop();
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
printFormattedResponse({ ...opts }, formatted);
|
|
29
|
+
if ((_b = formatted.result) === null || _b === void 0 ? void 0 : _b._id)
|
|
30
|
+
localStorage.setItem("lastId", formatted.result._id);
|
|
31
|
+
return { data: formatted.plainResult, content: formatted.content, result: formatted.result, meta: formatted.meta };
|
|
30
32
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Operation handling functions
|
|
2
2
|
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
3
3
|
import { spinner } from "../../index.js";
|
|
4
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
4
|
+
import { handleResponseFormatOptions, printFormattedResponse, } from "../helpers/handleResponseFormatOptions.js";
|
|
5
5
|
import { localStorage } from "../helpers/localStorage.js";
|
|
6
6
|
import { getContextCreateFields } from "../helpers/contextInjector.js";
|
|
7
7
|
export async function handleCreateSingleOperation(module, collection, name, opts) {
|
|
8
|
-
var _a;
|
|
8
|
+
var _a, _b, _c;
|
|
9
9
|
spinner.start({
|
|
10
10
|
text: `Creating entry in [${collection}]`,
|
|
11
11
|
color: "magenta",
|
|
@@ -26,13 +26,14 @@ export async function handleCreateSingleOperation(module, collection, name, opts
|
|
|
26
26
|
spinner.stop();
|
|
27
27
|
return { data: null, content: null, result: null, meta: (_a = res === null || res === void 0 ? void 0 : res.meta) !== null && _a !== void 0 ? _a : {} };
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
const formatted = handleResponseFormatOptions({ ...opts }, res, { noPrint: true });
|
|
30
30
|
spinner.success({
|
|
31
|
-
text: `Created entry [${result === null ||
|
|
31
|
+
text: `Created entry [${(_b = formatted.result) === null || _b === void 0 ? void 0 : _b._id}] in ${collection}`,
|
|
32
32
|
});
|
|
33
33
|
spinner.stop();
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
printFormattedResponse({ ...opts }, formatted);
|
|
35
|
+
if ((_c = formatted.result) === null || _c === void 0 ? void 0 : _c._id) {
|
|
36
|
+
localStorage.setItem("lastId", formatted.result._id);
|
|
36
37
|
}
|
|
37
|
-
return { data: plainResult, content, result, meta };
|
|
38
|
+
return { data: formatted.plainResult, content: formatted.content, result: formatted.result, meta: formatted.meta };
|
|
38
39
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Operation handling functions
|
|
2
2
|
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
3
3
|
import { spinner } from "../../index.js";
|
|
4
|
-
import { handleResponseFormatOptions, getApiResponseFormat } from "../helpers/handleResponseFormatOptions.js";
|
|
4
|
+
import { handleResponseFormatOptions, printFormattedResponse, getApiResponseFormat, } from "../helpers/handleResponseFormatOptions.js";
|
|
5
5
|
import { sanitizeFields } from "../helpers/sanitizeFields.js";
|
|
6
6
|
import { getContextFilterParams } from "../helpers/contextInjector.js";
|
|
7
7
|
export async function handleGetOperation(module, collection, opts) {
|
|
@@ -23,7 +23,10 @@ export async function handleGetOperation(module, collection, opts) {
|
|
|
23
23
|
verbosity: opts.verbosity,
|
|
24
24
|
...contextParams,
|
|
25
25
|
});
|
|
26
|
-
|
|
26
|
+
// Compute formatted result without printing — spinner success line should
|
|
27
|
+
// appear ABOVE the data block, not after it.
|
|
28
|
+
const formatted = handleResponseFormatOptions(opts, res, { noPrint: true });
|
|
29
|
+
const { plainResult, result, meta, content } = formatted;
|
|
27
30
|
const totalEntries = (_b = (_a = meta === null || meta === void 0 ? void 0 : meta.pageInfo) === null || _a === void 0 ? void 0 : _a.totalEntries) !== null && _b !== void 0 ? _b : '?';
|
|
28
31
|
const page = (_d = (_c = meta === null || meta === void 0 ? void 0 : meta.pageInfo) === null || _c === void 0 ? void 0 : _c.page) !== null && _d !== void 0 ? _d : 1;
|
|
29
32
|
const totalPages = (_f = (_e = meta === null || meta === void 0 ? void 0 : meta.pageInfo) === null || _e === void 0 ? void 0 : _e.totalPages) !== null && _f !== void 0 ? _f : '?';
|
|
@@ -31,5 +34,6 @@ export async function handleGetOperation(module, collection, opts) {
|
|
|
31
34
|
text: `Got ${opts.limit} entries of ${totalEntries} : Page ${page} of ${totalPages}`,
|
|
32
35
|
});
|
|
33
36
|
spinner.stop();
|
|
37
|
+
printFormattedResponse(opts, formatted);
|
|
34
38
|
return { data: plainResult, content, result, meta };
|
|
35
39
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Operation handling functions
|
|
2
2
|
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
3
3
|
import { spinner } from "../../index.js";
|
|
4
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
4
|
+
import { handleResponseFormatOptions, printFormattedResponse, } from "../helpers/handleResponseFormatOptions.js";
|
|
5
5
|
export async function handleGetSingleOperation(module, collection, id, opts) {
|
|
6
6
|
spinner.start({
|
|
7
7
|
text: `Getting entry in [${collection}]`,
|
|
@@ -11,10 +11,12 @@ export async function handleGetSingleOperation(module, collection, id, opts) {
|
|
|
11
11
|
responseFormat: "table",
|
|
12
12
|
verbosity: opts.verbosity,
|
|
13
13
|
});
|
|
14
|
-
|
|
14
|
+
const formattedOpts = { ...opts, responseFormat: "table" };
|
|
15
|
+
const formatted = handleResponseFormatOptions(formattedOpts, res, { noPrint: true });
|
|
15
16
|
spinner.success({
|
|
16
17
|
text: `Got entry in ${collection}`,
|
|
17
18
|
});
|
|
18
19
|
spinner.stop();
|
|
19
|
-
|
|
20
|
+
printFormattedResponse(formattedOpts, formatted);
|
|
21
|
+
return { data: formatted.plainResult, content: formatted.content, result: formatted.result, meta: formatted.meta };
|
|
20
22
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Operation handling functions
|
|
2
2
|
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
3
3
|
import { spinner } from "../../index.js";
|
|
4
|
-
import { handleResponseFormatOptions, getApiResponseFormat } from "../helpers/handleResponseFormatOptions.js";
|
|
4
|
+
import { handleResponseFormatOptions, printFormattedResponse, getApiResponseFormat, } from "../helpers/handleResponseFormatOptions.js";
|
|
5
5
|
import { getContextFilterParams, hasActiveContext } from "../helpers/contextInjector.js";
|
|
6
6
|
async function fetchPage(module, collection, opts) {
|
|
7
7
|
const contextParams = getContextFilterParams(collection);
|
|
@@ -47,14 +47,19 @@ export async function handleListOperation(module, collection, opts) {
|
|
|
47
47
|
payload: allPayload,
|
|
48
48
|
meta: { ...meta, pageInfo: { ...(meta.pageInfo || {}), page: 1, totalPages: 1, totalEntries: allPayload.length } },
|
|
49
49
|
};
|
|
50
|
-
|
|
50
|
+
// Compute formatted result without printing — we want the spinner success
|
|
51
|
+
// line to appear ABOVE the data block, not below it. handleListOperation
|
|
52
|
+
// is the canonical CRUD-display path for `ay list`.
|
|
53
|
+
const formatted = handleResponseFormatOptions(opts, syntheticRes, { noPrint: true });
|
|
51
54
|
spinner.success({ text: `Got all ${allPayload.length} entries from ${totalPages} pages` });
|
|
52
55
|
spinner.stop();
|
|
53
|
-
|
|
56
|
+
printFormattedResponse(opts, formatted);
|
|
57
|
+
return { data: formatted.plainResult, content: formatted.content, result: formatted.result, meta: syntheticRes.meta };
|
|
54
58
|
}
|
|
55
59
|
// Single page fetch
|
|
56
60
|
let res = await fetchPage(module, collection, opts);
|
|
57
|
-
|
|
61
|
+
const formatted = handleResponseFormatOptions(opts, res, { noPrint: true });
|
|
62
|
+
const { plainResult, result, meta, content } = formatted;
|
|
58
63
|
const count = Array.isArray(result) ? result.length : 0;
|
|
59
64
|
const total = (_d = (_c = meta === null || meta === void 0 ? void 0 : meta.pageInfo) === null || _c === void 0 ? void 0 : _c.totalEntries) !== null && _d !== void 0 ? _d : count;
|
|
60
65
|
spinner.success({
|
|
@@ -63,5 +68,6 @@ export async function handleListOperation(module, collection, opts) {
|
|
|
63
68
|
: `No entries found in [${collection}]`,
|
|
64
69
|
});
|
|
65
70
|
spinner.stop();
|
|
71
|
+
printFormattedResponse(opts, formatted);
|
|
66
72
|
return { data: plainResult, content, result, meta };
|
|
67
73
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Operation handling functions
|
|
2
2
|
import { spinner } from "../../index.js";
|
|
3
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
3
|
+
import { handleResponseFormatOptions, printFormattedResponse, } from "../helpers/handleResponseFormatOptions.js";
|
|
4
4
|
import { localStorage } from "../helpers/localStorage.js";
|
|
5
5
|
import { auditCallHandler } from "../api/auditCallHandler.js";
|
|
6
6
|
export async function handleSingleAuditOperation(collection, id, auditId, opts) {
|
|
@@ -12,16 +12,17 @@ export async function handleSingleAuditOperation(collection, id, auditId, opts)
|
|
|
12
12
|
responseFormat: opts.responseFormat,
|
|
13
13
|
verbosity: opts.verbosity,
|
|
14
14
|
});
|
|
15
|
-
|
|
15
|
+
const formatted = handleResponseFormatOptions({ ...opts }, res, { noPrint: true });
|
|
16
16
|
spinner.success({
|
|
17
17
|
text: `Got audit [${auditId}] for [${id}] in [${collection}]`,
|
|
18
18
|
});
|
|
19
19
|
spinner.stop();
|
|
20
|
-
|
|
20
|
+
printFormattedResponse({ ...opts }, formatted);
|
|
21
|
+
localStorage.setItem("lastId", formatted.result._id);
|
|
21
22
|
return {
|
|
22
|
-
singleData: plainResult,
|
|
23
|
-
singleContent: content,
|
|
24
|
-
singleResult: result,
|
|
25
|
-
singleMeta: meta,
|
|
23
|
+
singleData: formatted.plainResult,
|
|
24
|
+
singleContent: formatted.content,
|
|
25
|
+
singleResult: formatted.result,
|
|
26
|
+
singleMeta: formatted.meta,
|
|
26
27
|
};
|
|
27
28
|
}
|