@fnndsc/chili 3.4.0 → 3.5.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/dist/chefs/chefs.js +12 -11
- package/dist/commands/fs/download.js +4 -3
- package/dist/commands/fs/upload.js +4 -3
- package/dist/commands/man/doc.js +3 -2
- package/dist/commands/plugins/add.js +35 -34
- package/dist/config/colorConfig.js +2 -1
- package/dist/connect/connectHandler.js +7 -6
- package/dist/context/contextCommand.js +3 -2
- package/dist/controllers/fileController.js +4 -3
- package/dist/controllers/pluginController.js +2 -1
- package/dist/feeds/feedHandler.js +19 -18
- package/dist/filesystem/fileGroupHandler.js +28 -27
- package/dist/filesystem/filesystemHandler.js +13 -11
- package/dist/filesystem/inodeCommand.js +2 -1
- package/dist/handlers/baseGroupHandler.js +12 -11
- package/dist/index.js +3 -2
- package/dist/lfs/lfs.js +6 -4
- package/dist/man/man.js +4 -3
- package/dist/man/renderer.js +3 -2
- package/dist/pacs/pacsQueryHandler.js +14 -13
- package/dist/pacs/pacsRetrieveHandler.js +13 -12
- package/dist/path/pathCommand.js +23 -22
- package/dist/plugins/pluginGroupHandler.js +4 -3
- package/dist/plugins/pluginHandler.js +23 -22
- package/dist/run.d.ts +13 -0
- package/dist/run.js +28 -13
- package/dist/screen/output.d.ts +88 -0
- package/dist/screen/output.js +95 -0
- package/dist/screen/screen.js +9 -8
- package/dist/utils/admin_prompt.js +10 -9
- package/dist/utils/docker.js +10 -9
- package/dist/views/pluginParameters.js +2 -1
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ import { BaseGroupHandler } from "../handlers/baseGroupHandler.js";
|
|
|
9
9
|
import { border_draw } from "../screen/screen.js";
|
|
10
10
|
import { pacsQueryResult_renderPretty } from "./pacsResultRender.js";
|
|
11
11
|
import { pacsQueryPayload_build } from "./pacsQueryPayload.js";
|
|
12
|
+
import { chiliLog } from "../screen/output.js";
|
|
12
13
|
/**
|
|
13
14
|
* Handler for PACS queries commands.
|
|
14
15
|
*/
|
|
@@ -69,7 +70,7 @@ export class PACSQueryGroupHandler {
|
|
|
69
70
|
const listCommand = this.baseGroupHandler.baseListCommand_create(async (options) => {
|
|
70
71
|
const pacsserver = await this.pacsserverContext_resolve(options.pacsserver);
|
|
71
72
|
if (!pacsserver) {
|
|
72
|
-
|
|
73
|
+
chiliLog(border_draw("No PACS server in context. Use --pacsserver or set via context."));
|
|
73
74
|
return;
|
|
74
75
|
}
|
|
75
76
|
const mergedOptions = this.options_withPACSFilter(options, pacsserver);
|
|
@@ -111,17 +112,17 @@ export class PACSQueryGroupHandler {
|
|
|
111
112
|
}
|
|
112
113
|
const payload = pacsQueryPayload_build(queryInput, options.title, options.description);
|
|
113
114
|
if (!payload) {
|
|
114
|
-
|
|
115
|
+
chiliLog(border_draw("Invalid query format. Provide JSON or comma-separated key:value pairs."));
|
|
115
116
|
return;
|
|
116
117
|
}
|
|
117
118
|
const result = await pacsQueries_create(pacsserver, payload);
|
|
118
119
|
if (!result.ok) {
|
|
119
120
|
const errors = errorStack_getAllOfType("error");
|
|
120
121
|
if (errors.length) {
|
|
121
|
-
errors.forEach((msg) =>
|
|
122
|
+
errors.forEach((msg) => chiliLog(border_draw(msg)));
|
|
122
123
|
}
|
|
123
124
|
else {
|
|
124
|
-
|
|
125
|
+
chiliLog(border_draw("Failed to create PACS query."));
|
|
125
126
|
}
|
|
126
127
|
return;
|
|
127
128
|
}
|
|
@@ -133,7 +134,7 @@ export class PACSQueryGroupHandler {
|
|
|
133
134
|
`pacs=${pacsserver}`,
|
|
134
135
|
`title="${created.title ?? options.title ?? ""}"`,
|
|
135
136
|
].join(" ");
|
|
136
|
-
|
|
137
|
+
chiliLog(border_draw(msg.trim()));
|
|
137
138
|
});
|
|
138
139
|
}
|
|
139
140
|
/**
|
|
@@ -149,17 +150,17 @@ export class PACSQueryGroupHandler {
|
|
|
149
150
|
.action(async (queryId, options) => {
|
|
150
151
|
const idNum = Number(queryId);
|
|
151
152
|
if (Number.isNaN(idNum)) {
|
|
152
|
-
|
|
153
|
+
chiliLog(border_draw("queryId must be a number."));
|
|
153
154
|
return;
|
|
154
155
|
}
|
|
155
156
|
const result = await pacsQuery_resultDecode(idNum);
|
|
156
157
|
if (!result.ok) {
|
|
157
158
|
const errors = errorStack_getAllOfType("error");
|
|
158
159
|
if (errors.length) {
|
|
159
|
-
errors.forEach((msg) =>
|
|
160
|
+
errors.forEach((msg) => chiliLog(border_draw(msg)));
|
|
160
161
|
}
|
|
161
162
|
else {
|
|
162
|
-
|
|
163
|
+
chiliLog(border_draw(`Failed to decode PACS query result for ${idNum}.`));
|
|
163
164
|
}
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
@@ -167,23 +168,23 @@ export class PACSQueryGroupHandler {
|
|
|
167
168
|
// Prefer JSON, then text, else indicate base64 length
|
|
168
169
|
if (decoded.json !== undefined) {
|
|
169
170
|
if (options.raw) {
|
|
170
|
-
|
|
171
|
+
chiliLog(border_draw(JSON.stringify(decoded.json, null, 2)));
|
|
171
172
|
return;
|
|
172
173
|
}
|
|
173
174
|
const pretty = this.pacsResult_renderPretty(decoded.json);
|
|
174
175
|
if (pretty) {
|
|
175
|
-
|
|
176
|
+
chiliLog(border_draw(pretty));
|
|
176
177
|
}
|
|
177
178
|
else {
|
|
178
|
-
|
|
179
|
+
chiliLog(border_draw(JSON.stringify(decoded.json, null, 2)));
|
|
179
180
|
}
|
|
180
181
|
}
|
|
181
182
|
else if (decoded.text) {
|
|
182
|
-
|
|
183
|
+
chiliLog(border_draw(decoded.text));
|
|
183
184
|
}
|
|
184
185
|
else {
|
|
185
186
|
const len = decoded.raw.length;
|
|
186
|
-
|
|
187
|
+
chiliLog(border_draw(`Decoded payload available (base64 length ${len}), but not printable.`));
|
|
187
188
|
}
|
|
188
189
|
});
|
|
189
190
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { errorStack_getAllOfType, } from "@fnndsc/cumin";
|
|
7
7
|
import { pacsRetrieve_create, pacsRetrieve_delete, pacsRetrieve_statusForQuery, } from "@fnndsc/salsa";
|
|
8
8
|
import { border_draw } from "../screen/screen.js";
|
|
9
|
+
import { chiliLog } from "../screen/output.js";
|
|
9
10
|
/**
|
|
10
11
|
* Handler for PACS retrieve commands.
|
|
11
12
|
*/
|
|
@@ -52,17 +53,17 @@ export class PACSRetrieveGroupHandler {
|
|
|
52
53
|
async retrieve_pull(queryIdStr) {
|
|
53
54
|
const queryId = Number(queryIdStr);
|
|
54
55
|
if (Number.isNaN(queryId)) {
|
|
55
|
-
|
|
56
|
+
chiliLog(border_draw("Query ID must be a number."));
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
const result = await pacsRetrieve_create(queryId);
|
|
59
60
|
if (!result.ok) {
|
|
60
61
|
const errors = errorStack_getAllOfType("error");
|
|
61
62
|
if (errors.length) {
|
|
62
|
-
errors.forEach((msg) =>
|
|
63
|
+
errors.forEach((msg) => chiliLog(border_draw(msg)));
|
|
63
64
|
}
|
|
64
65
|
else {
|
|
65
|
-
|
|
66
|
+
chiliLog(border_draw(`Failed to create PACS retrieve for query ${queryId}.`));
|
|
66
67
|
}
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
@@ -73,7 +74,7 @@ export class PACSRetrieveGroupHandler {
|
|
|
73
74
|
`query=${queryId}`,
|
|
74
75
|
`status=${record.status || "created"}`,
|
|
75
76
|
].join(" ");
|
|
76
|
-
|
|
77
|
+
chiliLog(border_draw(msg));
|
|
77
78
|
}
|
|
78
79
|
/**
|
|
79
80
|
* Handle the 'report' command - show detailed status.
|
|
@@ -83,23 +84,23 @@ export class PACSRetrieveGroupHandler {
|
|
|
83
84
|
async retrieve_report(queryIdStr) {
|
|
84
85
|
const queryId = Number(queryIdStr);
|
|
85
86
|
if (Number.isNaN(queryId)) {
|
|
86
|
-
|
|
87
|
+
chiliLog(border_draw("Query ID must be a number."));
|
|
87
88
|
return;
|
|
88
89
|
}
|
|
89
90
|
const result = await pacsRetrieve_statusForQuery(queryId);
|
|
90
91
|
if (!result.ok) {
|
|
91
92
|
const errors = errorStack_getAllOfType("error");
|
|
92
93
|
if (errors.length) {
|
|
93
|
-
errors.forEach((msg) =>
|
|
94
|
+
errors.forEach((msg) => chiliLog(border_draw(msg)));
|
|
94
95
|
}
|
|
95
96
|
else {
|
|
96
|
-
|
|
97
|
+
chiliLog(border_draw(`Failed to generate status report for query ${queryId}.`));
|
|
97
98
|
}
|
|
98
99
|
return;
|
|
99
100
|
}
|
|
100
101
|
const report = result.value;
|
|
101
102
|
const rendered = this.report_render(report);
|
|
102
|
-
|
|
103
|
+
chiliLog(border_draw(rendered));
|
|
103
104
|
}
|
|
104
105
|
/**
|
|
105
106
|
* Handle the 'cancel' command - delete a retrieve.
|
|
@@ -109,21 +110,21 @@ export class PACSRetrieveGroupHandler {
|
|
|
109
110
|
async retrieve_cancel(retrieveIdStr) {
|
|
110
111
|
const retrieveId = Number(retrieveIdStr);
|
|
111
112
|
if (Number.isNaN(retrieveId)) {
|
|
112
|
-
|
|
113
|
+
chiliLog(border_draw("Retrieve ID must be a number."));
|
|
113
114
|
return;
|
|
114
115
|
}
|
|
115
116
|
const result = await pacsRetrieve_delete(retrieveId);
|
|
116
117
|
if (!result.ok) {
|
|
117
118
|
const errors = errorStack_getAllOfType("error");
|
|
118
119
|
if (errors.length) {
|
|
119
|
-
errors.forEach((msg) =>
|
|
120
|
+
errors.forEach((msg) => chiliLog(border_draw(msg)));
|
|
120
121
|
}
|
|
121
122
|
else {
|
|
122
|
-
|
|
123
|
+
chiliLog(border_draw(`Failed to cancel PACS retrieve ${retrieveId}.`));
|
|
123
124
|
}
|
|
124
125
|
return;
|
|
125
126
|
}
|
|
126
|
-
|
|
127
|
+
chiliLog(border_draw(`PACS retrieve ${retrieveId} cancelled.`));
|
|
127
128
|
}
|
|
128
129
|
/**
|
|
129
130
|
* Determine overall completion status from series statuses.
|
package/dist/path/pathCommand.js
CHANGED
|
@@ -16,6 +16,7 @@ import open from "open";
|
|
|
16
16
|
import { execFile } from "child_process";
|
|
17
17
|
import os from "os";
|
|
18
18
|
import { files_downloadWithProgress } from "../commands/fs/download.js";
|
|
19
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
19
20
|
/**
|
|
20
21
|
* Creates a summary table for file transfer details.
|
|
21
22
|
*
|
|
@@ -166,7 +167,7 @@ async function mermaid_renderServerSide(mermaidDefinition, outputFile) {
|
|
|
166
167
|
return new Promise((resolve, reject) => {
|
|
167
168
|
execFile("npx", ["mmdc", "-i", inputFile, "-o", outputFile], (error) => {
|
|
168
169
|
if (error) {
|
|
169
|
-
|
|
170
|
+
chiliErrLog(`Mermaid render failed. Ensure @mermaid-js/mermaid-cli is available (npx mmdc): ${error.message}`);
|
|
170
171
|
reject(error);
|
|
171
172
|
return;
|
|
172
173
|
}
|
|
@@ -412,10 +413,10 @@ async function scanResult_render(scanResult, options) {
|
|
|
412
413
|
try {
|
|
413
414
|
const outputFile = path.resolve(options.save);
|
|
414
415
|
const savedFilePath = await mermaid_renderServerSide(mermaidDefinition, outputFile);
|
|
415
|
-
|
|
416
|
+
chiliLog(`Mermaid diagram saved to: ${savedFilePath}`);
|
|
416
417
|
}
|
|
417
418
|
catch (error) {
|
|
418
|
-
|
|
419
|
+
chiliErrLog(`Failed to save Mermaid diagram: ${error}`);
|
|
419
420
|
}
|
|
420
421
|
}
|
|
421
422
|
else {
|
|
@@ -424,16 +425,16 @@ async function scanResult_render(scanResult, options) {
|
|
|
424
425
|
return;
|
|
425
426
|
}
|
|
426
427
|
if (options.tree) {
|
|
427
|
-
|
|
428
|
+
chiliLog(archyTree_create(scanResult.fileInfo));
|
|
428
429
|
return;
|
|
429
430
|
}
|
|
430
431
|
if (!options.silent) {
|
|
431
432
|
for (const file of scanResult.fileInfo) {
|
|
432
433
|
if (file.isLink && !options.follow) {
|
|
433
|
-
|
|
434
|
+
chiliLog(`${file.chrisPath} -> ${file.linkTarget}`);
|
|
434
435
|
}
|
|
435
436
|
else {
|
|
436
|
-
|
|
437
|
+
chiliLog(`${file.chrisPath}`);
|
|
437
438
|
}
|
|
438
439
|
}
|
|
439
440
|
}
|
|
@@ -447,24 +448,24 @@ async function scanResult_render(scanResult, options) {
|
|
|
447
448
|
export async function scan_do(options) {
|
|
448
449
|
const chrisFolder = await chrisContext.current_get(Context.ChRISfolder);
|
|
449
450
|
if (!chrisFolder) {
|
|
450
|
-
|
|
451
|
+
chiliErrLog(chalk.red("No ChRIS folder context set. Use 'folder=' to set a context."));
|
|
451
452
|
return null;
|
|
452
453
|
}
|
|
453
454
|
if (!options.silent) {
|
|
454
|
-
|
|
455
|
+
chiliLog(chalk.cyan(`Scanning for ${options.dirsOnly ? "directories" : "all files"} recursively from ${chrisFolder}`));
|
|
455
456
|
}
|
|
456
457
|
const hostBasePath = options.hostpath || process.cwd();
|
|
457
458
|
const scanResult = await chrisFS_scan(chrisFolder, hostBasePath, options.follow, options.dirsOnly);
|
|
458
459
|
if (!scanResult) {
|
|
459
|
-
|
|
460
|
+
chiliErrLog(chalk.red("Failed to scan ChRIS filesystem."));
|
|
460
461
|
return null;
|
|
461
462
|
}
|
|
462
463
|
const filtered = scanResult_filter(scanResult, options);
|
|
463
464
|
await scanResult_render(filtered, options);
|
|
464
465
|
if (!options.silent) {
|
|
465
|
-
|
|
466
|
+
chiliLog(chalk.green(`Total size: ${bytes_format(filtered.totalSize)}`));
|
|
466
467
|
if (options.filter || options.endsWith) {
|
|
467
|
-
|
|
468
|
+
chiliLog(chalk.cyan(`Filtered results: ${filtered.fileInfo.length} items`));
|
|
468
469
|
}
|
|
469
470
|
}
|
|
470
471
|
return filtered;
|
|
@@ -517,25 +518,25 @@ async function localFS_scan(options) {
|
|
|
517
518
|
await chrisContext.currentContext_update();
|
|
518
519
|
const folder = chrisContext.singleContext.folder;
|
|
519
520
|
if (!folder) {
|
|
520
|
-
|
|
521
|
+
chiliErrLog("ChRIS folder context is undefined, cannot initialize chrisIO.");
|
|
521
522
|
return null;
|
|
522
523
|
}
|
|
523
524
|
// Validate that the folder context exists in CUBE before proceeding
|
|
524
525
|
try {
|
|
525
526
|
const testGroup = await objContext_create("ChRISDirsContext", `folder:${folder}`);
|
|
526
527
|
if (!testGroup) {
|
|
527
|
-
|
|
528
|
+
chiliErrLog(chalk.red(`Folder context '${folder}' does not exist in CUBE. Please specify an existing directory.`));
|
|
528
529
|
return null;
|
|
529
530
|
}
|
|
530
531
|
}
|
|
531
532
|
catch (error) {
|
|
532
|
-
|
|
533
|
+
chiliErrLog(chalk.red(`Folder context '${folder}' does not exist in CUBE. Please specify an existing directory.`));
|
|
533
534
|
return null;
|
|
534
535
|
}
|
|
535
536
|
// Folder exists, so just set chrisFolder without calling init()
|
|
536
537
|
// (init() tries to CREATE the folder which will fail if it already exists)
|
|
537
538
|
chrisIO.chrisFolder = folder;
|
|
538
|
-
|
|
539
|
+
chiliLog(border_draw(chalk.cyan("Scanning files to upload...")));
|
|
539
540
|
const filesToUpload = await filesToUpload_get(options.hostpath, folder);
|
|
540
541
|
let totalSize = 0;
|
|
541
542
|
for (const file of filesToUpload) {
|
|
@@ -643,12 +644,12 @@ async function chris_pull(scanRecord, progressBar) {
|
|
|
643
644
|
}
|
|
644
645
|
else {
|
|
645
646
|
summary.failedCount++;
|
|
646
|
-
|
|
647
|
+
chiliLog(chalk.yellow(`Failed to download: ${file.hostPath}`));
|
|
647
648
|
}
|
|
648
649
|
}
|
|
649
650
|
catch (error) {
|
|
650
651
|
summary.failedCount++;
|
|
651
|
-
|
|
652
|
+
chiliLog(chalk.red(`Error downloading ${file.hostPath}: ${error instanceof Error ? error.message : String(error)}`));
|
|
652
653
|
}
|
|
653
654
|
progressBar.update(index + 1, {
|
|
654
655
|
bytes: bytes_format(summary.transferSize), // Renamed
|
|
@@ -685,12 +686,12 @@ async function chris_push(scanRecord, progressBar) {
|
|
|
685
686
|
}
|
|
686
687
|
else {
|
|
687
688
|
summary.failedCount++;
|
|
688
|
-
|
|
689
|
+
chiliLog(chalk.yellow(`Failed to upload: ${file.hostPath}`));
|
|
689
690
|
}
|
|
690
691
|
}
|
|
691
692
|
catch (error) {
|
|
692
693
|
summary.failedCount++;
|
|
693
|
-
|
|
694
|
+
chiliLog(chalk.red(`Error uploading ${file.hostPath}: ${error instanceof Error ? error.message : String(error)}`));
|
|
694
695
|
}
|
|
695
696
|
progressBar.update(index + 1, {
|
|
696
697
|
bytes: bytes_format(summary.transferSize), // Renamed
|
|
@@ -713,7 +714,7 @@ async function download_handle(options) {
|
|
|
713
714
|
await chrisContext.currentContext_update();
|
|
714
715
|
const folder = chrisContext.singleContext.folder;
|
|
715
716
|
if (!folder) {
|
|
716
|
-
|
|
717
|
+
chiliErrLog(chalk.red("No ChRIS folder context set. Use 'connect' to establish a session."));
|
|
717
718
|
return false;
|
|
718
719
|
}
|
|
719
720
|
const localTarget = path.resolve(options.hostpath || process.cwd());
|
|
@@ -728,7 +729,7 @@ async function download_handle(options) {
|
|
|
728
729
|
}
|
|
729
730
|
catch (error) {
|
|
730
731
|
const msg = error instanceof Error ? error.message : String(error);
|
|
731
|
-
|
|
732
|
+
chiliErrLog(chalk.red(`Download failed: ${msg}`));
|
|
732
733
|
return false;
|
|
733
734
|
}
|
|
734
735
|
}
|
|
@@ -788,7 +789,7 @@ export async function pathCommand_setup(program) {
|
|
|
788
789
|
hostpath: hostpath || process.cwd(),
|
|
789
790
|
force: options.force,
|
|
790
791
|
});
|
|
791
|
-
|
|
792
|
+
chiliLog(result);
|
|
792
793
|
});
|
|
793
794
|
pathCommand
|
|
794
795
|
.command("scan")
|
|
@@ -8,6 +8,7 @@ import { options_toParams } from "../utils/cli.js";
|
|
|
8
8
|
import { PluginContextController } from "../controllers/pluginContextController.js";
|
|
9
9
|
import { pluginParameters_renderMan, pluginParameters_manRender } from "../views/pluginParameters.js";
|
|
10
10
|
import { envelope_ok, envelope_error } from "@fnndsc/cumin";
|
|
11
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
11
12
|
class InitializationError extends Error {
|
|
12
13
|
constructor(message) {
|
|
13
14
|
super(message);
|
|
@@ -53,7 +54,7 @@ export class PluginContextGroupHandler {
|
|
|
53
54
|
// We access the asset directly from the controller
|
|
54
55
|
const asset = this.controller.chrisObject.asset;
|
|
55
56
|
if (!asset || typeof asset.resources_listAndFilterByOptions !== 'function') {
|
|
56
|
-
|
|
57
|
+
chiliErrLog("Underlying resource does not support listing.");
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
60
|
const params = options_toParams(options);
|
|
@@ -62,11 +63,11 @@ export class PluginContextGroupHandler {
|
|
|
62
63
|
pluginParameters_renderMan(results);
|
|
63
64
|
}
|
|
64
65
|
else {
|
|
65
|
-
|
|
66
|
+
chiliLog("No parameters found.");
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
catch (error) {
|
|
69
|
-
|
|
70
|
+
chiliErrLog(`Error listing parameters: ${error}`);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
/**
|
|
@@ -13,6 +13,7 @@ import { pluginIds_resolve } from "../commands/plugin/search.js";
|
|
|
13
13
|
import { pluginRun_render } from "../views/plugin.js"; // Still needed for pluginRun_render
|
|
14
14
|
import chalk from "chalk";
|
|
15
15
|
import { pluginReadme_render } from "../commands/plugin/readme.js";
|
|
16
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
16
17
|
/**
|
|
17
18
|
* Handles commands related to groups of ChRIS plugins.
|
|
18
19
|
*/
|
|
@@ -34,10 +35,10 @@ export class PluginGroupHandler {
|
|
|
34
35
|
// async plugins_list(options: CLIoptions): Promise<void> {
|
|
35
36
|
// try {
|
|
36
37
|
// const { plugins, selectedFields } = await plugins_fetchList(options);
|
|
37
|
-
//
|
|
38
|
+
// chiliLog(pluginList_render(plugins, selectedFields, { table: options.table, csv: options.csv }));
|
|
38
39
|
// } catch (error: unknown) {
|
|
39
40
|
// const msg = error instanceof Error ? error.message : String(error);
|
|
40
|
-
//
|
|
41
|
+
// chiliErrLog(msg);
|
|
41
42
|
// }
|
|
42
43
|
// }
|
|
43
44
|
/**
|
|
@@ -50,11 +51,11 @@ export class PluginGroupHandler {
|
|
|
50
51
|
table_display(fields, ["fields"]);
|
|
51
52
|
}
|
|
52
53
|
else {
|
|
53
|
-
|
|
54
|
+
chiliLog(`No resource fields found for ${this.assetName}.`);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
catch (error) {
|
|
57
|
-
|
|
58
|
+
chiliLog(errorStack.stack_search(this.assetName)[0]);
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
/**
|
|
@@ -67,12 +68,12 @@ export class PluginGroupHandler {
|
|
|
67
68
|
for (const search of searchables) {
|
|
68
69
|
const items = await plugins_searchByTerm(search.raw);
|
|
69
70
|
if (items.length === 0) {
|
|
70
|
-
|
|
71
|
+
chiliLog(`No plugins found matching: ${search.raw}`);
|
|
71
72
|
continue;
|
|
72
73
|
}
|
|
73
74
|
for (const item of items) {
|
|
74
75
|
// Show item info - reusing table_display for single item details if possible, or simple log
|
|
75
|
-
|
|
76
|
+
chiliLog(`Preparing to delete Plugin: ID=${item.id}, Name=${item.name}, Version=${item.version}`);
|
|
76
77
|
if (!options.force) {
|
|
77
78
|
const confirmed = await prompt_confirm(`Are you sure you want to delete plugin ${item.name} (ID: ${item.id})?`);
|
|
78
79
|
if (!confirmed)
|
|
@@ -80,10 +81,10 @@ export class PluginGroupHandler {
|
|
|
80
81
|
}
|
|
81
82
|
const success = await plugin_deleteById(item.id);
|
|
82
83
|
if (success) {
|
|
83
|
-
|
|
84
|
+
chiliLog(`Deleted plugin ${item.id}`);
|
|
84
85
|
}
|
|
85
86
|
else {
|
|
86
|
-
|
|
87
|
+
chiliErrLog(`Failed to delete plugin ${item.id}`);
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
}
|
|
@@ -161,11 +162,11 @@ export class PluginMemberHandler {
|
|
|
161
162
|
async readme_print(repoUrl) {
|
|
162
163
|
const content = await this.controller.readmeContent_fetch(repoUrl);
|
|
163
164
|
if (content) {
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
chiliLog(chalk.green.bold("\nREADME Content:"));
|
|
166
|
+
chiliLog(pluginReadme_render(content));
|
|
166
167
|
}
|
|
167
168
|
else {
|
|
168
|
-
|
|
169
|
+
chiliLog(chalk.red("README not found in the repository."));
|
|
169
170
|
}
|
|
170
171
|
}
|
|
171
172
|
/**
|
|
@@ -176,21 +177,21 @@ export class PluginMemberHandler {
|
|
|
176
177
|
*/
|
|
177
178
|
async plugin_readme(pluginId) {
|
|
178
179
|
try {
|
|
179
|
-
|
|
180
|
+
chiliLog(`Fetching info for plugin with ID: ${pluginId}`);
|
|
180
181
|
const documentation = await this.controller.documentationUrl_get(pluginId);
|
|
181
182
|
if (!documentation) {
|
|
182
183
|
return null;
|
|
183
184
|
}
|
|
184
|
-
|
|
185
|
+
chiliLog(documentation);
|
|
185
186
|
await this.readme_print(documentation);
|
|
186
187
|
return documentation;
|
|
187
188
|
}
|
|
188
189
|
catch (error) {
|
|
189
190
|
if (error instanceof Error) {
|
|
190
|
-
|
|
191
|
+
chiliErrLog(`Error fetching plugin info: ${error.message}`);
|
|
191
192
|
}
|
|
192
193
|
else {
|
|
193
|
-
|
|
194
|
+
chiliErrLog("An unknown error occurred while fetching plugin info");
|
|
194
195
|
}
|
|
195
196
|
}
|
|
196
197
|
return null;
|
|
@@ -214,15 +215,15 @@ export class PluginMemberHandler {
|
|
|
214
215
|
try {
|
|
215
216
|
const instance = await plugin_execute(searchable, params);
|
|
216
217
|
if (!instance) {
|
|
217
|
-
|
|
218
|
+
chiliLog(errorStack.messagesOfType_search("error", "plugin"));
|
|
218
219
|
return null;
|
|
219
220
|
}
|
|
220
|
-
|
|
221
|
+
chiliLog(pluginRun_render(instance));
|
|
221
222
|
return instance.id;
|
|
222
223
|
}
|
|
223
224
|
catch (e) {
|
|
224
225
|
const message = e instanceof Error ? e.message : String(e);
|
|
225
|
-
|
|
226
|
+
chiliErrLog(message);
|
|
226
227
|
return null;
|
|
227
228
|
}
|
|
228
229
|
}
|
|
@@ -234,7 +235,7 @@ export class PluginMemberHandler {
|
|
|
234
235
|
if (!hits) {
|
|
235
236
|
return null;
|
|
236
237
|
}
|
|
237
|
-
|
|
238
|
+
chiliLog(hits);
|
|
238
239
|
return hits;
|
|
239
240
|
}
|
|
240
241
|
/**
|
|
@@ -270,10 +271,10 @@ export class PluginMemberHandler {
|
|
|
270
271
|
else {
|
|
271
272
|
const warnings = errorStack_getAllOfType('warning');
|
|
272
273
|
if (warnings && warnings.length > 0) {
|
|
273
|
-
warnings.forEach(warning =>
|
|
274
|
+
warnings.forEach(warning => chiliErrLog(chalk.yellow(warning)));
|
|
274
275
|
}
|
|
275
276
|
else {
|
|
276
|
-
|
|
277
|
+
chiliErrLog(chalk.red("Plugin not found."));
|
|
277
278
|
}
|
|
278
279
|
}
|
|
279
280
|
});
|
|
@@ -297,7 +298,7 @@ export class PluginMemberHandler {
|
|
|
297
298
|
});
|
|
298
299
|
}
|
|
299
300
|
else {
|
|
300
|
-
|
|
301
|
+
chiliErrLog(`Failed to find '${this.assetName}' command. The 'readme' subcommand was not added.`);
|
|
301
302
|
}
|
|
302
303
|
}
|
|
303
304
|
}
|
package/dist/run.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module
|
|
11
11
|
*/
|
|
12
|
+
import { type ChiliCaptured } from "./screen/output.js";
|
|
12
13
|
/**
|
|
13
14
|
* Executes a single chili command in the current process.
|
|
14
15
|
*
|
|
@@ -22,3 +23,15 @@
|
|
|
22
23
|
* the leading `node`/script entries).
|
|
23
24
|
*/
|
|
24
25
|
export declare function run(argv: string[]): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Executes a single chili command with its output captured instead of printed.
|
|
28
|
+
*
|
|
29
|
+
* Runs {@link run} inside {@link chili_capture}, so everything the command
|
|
30
|
+
* would have written to the output and error channels is collected and
|
|
31
|
+
* returned. This is how an in-process host (the brasa engine) drives chili
|
|
32
|
+
* headless and carries the result in an envelope, with no console monkeypatch.
|
|
33
|
+
*
|
|
34
|
+
* @param argv - The chili arguments, e.g. `["feeds", "list", "-s"]`.
|
|
35
|
+
* @returns The captured output and error text.
|
|
36
|
+
*/
|
|
37
|
+
export declare function run_capture(argv: string[]): Promise<ChiliCaptured>;
|
package/dist/run.js
CHANGED
|
@@ -27,6 +27,7 @@ import { PACSQueryGroupHandler } from "./pacs/pacsQueryHandler.js";
|
|
|
27
27
|
import { PACSRetrieveGroupHandler } from "./pacs/pacsRetrieveHandler.js";
|
|
28
28
|
import { chrisConnection_init, NodeStorageProvider, errorStack_getAllOfType, } from "@fnndsc/cumin";
|
|
29
29
|
import { FileGroupHandler } from "./filesystem/fileGroupHandler.js";
|
|
30
|
+
import { chiliErrLog, chiliLog, chili_capture } from "./screen/output.js";
|
|
30
31
|
/**
|
|
31
32
|
* Suppress the DEP0169 (`url.parse()`) warning emitted transitively by
|
|
32
33
|
* axios -> proxy-from-env, which we do not control. Installed once at import.
|
|
@@ -84,14 +85,14 @@ async function handlers_initialize(program) {
|
|
|
84
85
|
const err = e instanceof Error ? e.message : String(e);
|
|
85
86
|
const errors = errorStack_getAllOfType("error");
|
|
86
87
|
const warnings = errorStack_getAllOfType("warning");
|
|
87
|
-
|
|
88
|
+
chiliLog(`Note: File group commands (files, dirs, links) are unavailable. Reason: ${err}`);
|
|
88
89
|
if (errors.length > 0) {
|
|
89
|
-
|
|
90
|
-
errors.forEach((msg) =>
|
|
90
|
+
chiliLog("Errors:");
|
|
91
|
+
errors.forEach((msg) => chiliLog(` - ${msg}`));
|
|
91
92
|
}
|
|
92
93
|
if (warnings.length > 0) {
|
|
93
|
-
|
|
94
|
-
warnings.forEach((msg) =>
|
|
94
|
+
chiliLog("Warnings:");
|
|
95
|
+
warnings.forEach((msg) => chiliLog(` - ${msg}`));
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
try {
|
|
@@ -106,14 +107,14 @@ async function handlers_initialize(program) {
|
|
|
106
107
|
const err = e instanceof Error ? e.message : String(e);
|
|
107
108
|
const errors = errorStack_getAllOfType("error");
|
|
108
109
|
const warnings = errorStack_getAllOfType("warning");
|
|
109
|
-
|
|
110
|
+
chiliLog(`Note: Plugin context commands are unavailable. Reason: ${err}`);
|
|
110
111
|
if (errors.length > 0) {
|
|
111
|
-
|
|
112
|
-
errors.forEach((msg) =>
|
|
112
|
+
chiliLog("Errors:");
|
|
113
|
+
errors.forEach((msg) => chiliLog(` - ${msg}`));
|
|
113
114
|
}
|
|
114
115
|
if (warnings.length > 0) {
|
|
115
|
-
|
|
116
|
-
warnings.forEach((msg) =>
|
|
116
|
+
chiliLog("Warnings:");
|
|
117
|
+
warnings.forEach((msg) => chiliLog(` - ${msg}`));
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
}
|
|
@@ -155,7 +156,7 @@ export async function run(argv) {
|
|
|
155
156
|
if (context) {
|
|
156
157
|
const contextSetSuccess = await connection.context_set(context);
|
|
157
158
|
if (!contextSetSuccess) {
|
|
158
|
-
|
|
159
|
+
chiliErrLog("Failed to set context.");
|
|
159
160
|
return;
|
|
160
161
|
}
|
|
161
162
|
fullArgv = newArgs;
|
|
@@ -174,8 +175,8 @@ export async function run(argv) {
|
|
|
174
175
|
program.parseOptions(fullArgv);
|
|
175
176
|
const options = program.opts();
|
|
176
177
|
if (!options.nosplash) {
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
chiliLog(figlet.textSync("ChILI"));
|
|
179
|
+
chiliLog("ChILI handles Intelligent Line Interactions");
|
|
179
180
|
}
|
|
180
181
|
try {
|
|
181
182
|
await program.parseAsync(fullArgv);
|
|
@@ -190,3 +191,17 @@ export async function run(argv) {
|
|
|
190
191
|
throw err;
|
|
191
192
|
}
|
|
192
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Executes a single chili command with its output captured instead of printed.
|
|
196
|
+
*
|
|
197
|
+
* Runs {@link run} inside {@link chili_capture}, so everything the command
|
|
198
|
+
* would have written to the output and error channels is collected and
|
|
199
|
+
* returned. This is how an in-process host (the brasa engine) drives chili
|
|
200
|
+
* headless and carries the result in an envelope, with no console monkeypatch.
|
|
201
|
+
*
|
|
202
|
+
* @param argv - The chili arguments, e.g. `["feeds", "list", "-s"]`.
|
|
203
|
+
* @returns The captured output and error text.
|
|
204
|
+
*/
|
|
205
|
+
export async function run_capture(argv) {
|
|
206
|
+
return chili_capture(() => run(argv));
|
|
207
|
+
}
|