@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
package/dist/chefs/chefs.js
CHANGED
|
@@ -9,6 +9,7 @@ import { files_rm } from '../commands/fs/rm.js';
|
|
|
9
9
|
import { files_cp } from '../commands/fs/cp.js';
|
|
10
10
|
import { files_mv } from '../commands/fs/mv.js';
|
|
11
11
|
import { mkdir_render, touch_render, upload_render, cat_render, rm_render, cp_render, mv_render } from '../views/fs.js';
|
|
12
|
+
import { chiliLog } from "../screen/output.js";
|
|
12
13
|
/**
|
|
13
14
|
* Lists directory contents.
|
|
14
15
|
*
|
|
@@ -21,10 +22,10 @@ async function chefs_ls(options, pathStr = "") {
|
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
24
|
if (options.long) {
|
|
24
|
-
|
|
25
|
+
chiliLog(long_render(items, { human: !!options.human }));
|
|
25
26
|
}
|
|
26
27
|
else {
|
|
27
|
-
|
|
28
|
+
chiliLog(grid_render(items));
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
@@ -36,7 +37,7 @@ async function chefs_ls(options, pathStr = "") {
|
|
|
36
37
|
*/
|
|
37
38
|
async function chefs_cp(src, dest, options) {
|
|
38
39
|
const success = await files_cp(src, dest, options);
|
|
39
|
-
|
|
40
|
+
chiliLog(cp_render(src, dest, success));
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
42
43
|
* Moves a file or directory.
|
|
@@ -47,7 +48,7 @@ async function chefs_cp(src, dest, options) {
|
|
|
47
48
|
*/
|
|
48
49
|
async function chefs_mv(src, dest, _options) {
|
|
49
50
|
const success = await files_mv(src, dest);
|
|
50
|
-
|
|
51
|
+
chiliLog(mv_render(src, dest, success));
|
|
51
52
|
}
|
|
52
53
|
/**
|
|
53
54
|
* Creates a directory.
|
|
@@ -56,7 +57,7 @@ async function chefs_mv(src, dest, _options) {
|
|
|
56
57
|
*/
|
|
57
58
|
async function chefs_mkdir(dirPath) {
|
|
58
59
|
const success = await files_mkdir(dirPath);
|
|
59
|
-
|
|
60
|
+
chiliLog(mkdir_render(dirPath, success));
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
63
|
* Creates an empty file.
|
|
@@ -65,7 +66,7 @@ async function chefs_mkdir(dirPath) {
|
|
|
65
66
|
*/
|
|
66
67
|
async function chefs_touch(filePath) {
|
|
67
68
|
const success = await files_touch(filePath);
|
|
68
|
-
|
|
69
|
+
chiliLog(touch_render(filePath, success));
|
|
69
70
|
}
|
|
70
71
|
/**
|
|
71
72
|
* Uploads a local file or directory to ChRIS.
|
|
@@ -74,9 +75,9 @@ async function chefs_touch(filePath) {
|
|
|
74
75
|
* @param remotePath - Remote ChRIS path.
|
|
75
76
|
*/
|
|
76
77
|
async function chefs_upload(localPath, remotePath) {
|
|
77
|
-
|
|
78
|
+
chiliLog(`Uploading ${localPath} to ${remotePath}...`);
|
|
78
79
|
const success = await files_upload(localPath, remotePath);
|
|
79
|
-
|
|
80
|
+
chiliLog(upload_render(localPath, remotePath, success));
|
|
80
81
|
}
|
|
81
82
|
/**
|
|
82
83
|
* Changes the current working directory.
|
|
@@ -96,7 +97,7 @@ async function chefs_cd(path) {
|
|
|
96
97
|
*/
|
|
97
98
|
async function chefs_pwd() {
|
|
98
99
|
const current = await chrisContext.current_get(Context.ChRISfolder);
|
|
99
|
-
|
|
100
|
+
chiliLog(current || "/");
|
|
100
101
|
}
|
|
101
102
|
/**
|
|
102
103
|
* Displays file content.
|
|
@@ -106,7 +107,7 @@ async function chefs_pwd() {
|
|
|
106
107
|
async function chefs_cat(filePath) {
|
|
107
108
|
const result = await files_cat(filePath);
|
|
108
109
|
const content = result.ok ? result.value : null;
|
|
109
|
-
|
|
110
|
+
chiliLog(cat_render(content, filePath));
|
|
110
111
|
}
|
|
111
112
|
/**
|
|
112
113
|
* Removes a file or directory.
|
|
@@ -116,7 +117,7 @@ async function chefs_cat(filePath) {
|
|
|
116
117
|
*/
|
|
117
118
|
async function chefs_rm(targetPath, options) {
|
|
118
119
|
const result = await files_rm(targetPath, options);
|
|
119
|
-
|
|
120
|
+
chiliLog(rm_render(result));
|
|
120
121
|
}
|
|
121
122
|
/**
|
|
122
123
|
* Sets up the 'chefs' command group in Commander.
|
|
@@ -10,6 +10,7 @@ import chalk from "chalk";
|
|
|
10
10
|
import { pipeline } from "stream/promises";
|
|
11
11
|
import { bytes_format } from "./upload.js";
|
|
12
12
|
import { prompt_confirmOrThrow } from "../../utils/input_format.js";
|
|
13
|
+
import { chiliLog } from "../../screen/output.js";
|
|
13
14
|
export { bytes_format };
|
|
14
15
|
/**
|
|
15
16
|
* Recursively creates a directory and all parent directories.
|
|
@@ -141,7 +142,7 @@ export async function files_downloadWithProgress(chrisPath, localPath, options =
|
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
144
|
// Download directory
|
|
144
|
-
|
|
145
|
+
chiliLog(chalk.cyan("Scanning files to download..."));
|
|
145
146
|
options.onProgress?.({
|
|
146
147
|
operation: "download",
|
|
147
148
|
kind: "transfer",
|
|
@@ -190,7 +191,7 @@ export async function files_downloadWithProgress(chrisPath, localPath, options =
|
|
|
190
191
|
const result = await fileContent_getBinaryStream(file.path);
|
|
191
192
|
if (!result.ok) {
|
|
192
193
|
summary.failedCount++;
|
|
193
|
-
|
|
194
|
+
chiliLog(chalk.yellow(`\nFailed to download: ${file.path}`));
|
|
194
195
|
continue;
|
|
195
196
|
}
|
|
196
197
|
const { stream, size } = result.value;
|
|
@@ -212,7 +213,7 @@ export async function files_downloadWithProgress(chrisPath, localPath, options =
|
|
|
212
213
|
catch (error) {
|
|
213
214
|
summary.failedCount++;
|
|
214
215
|
const msg = error instanceof Error ? error.message : String(error);
|
|
215
|
-
|
|
216
|
+
chiliLog(chalk.red(`\nError downloading ${file.path}: ${msg}`));
|
|
216
217
|
}
|
|
217
218
|
options.onProgress?.({
|
|
218
219
|
operation: "download",
|
|
@@ -9,6 +9,7 @@ import fs from "fs";
|
|
|
9
9
|
import path from "path";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import { prompt_confirmOrThrow } from "../../utils/input_format.js";
|
|
12
|
+
import { chiliLog } from "../../screen/output.js";
|
|
12
13
|
/**
|
|
13
14
|
* Formats bytes into human-readable format.
|
|
14
15
|
* @param bytes - Number of bytes.
|
|
@@ -109,7 +110,7 @@ async function localFiles_scan(localPath, remotePath) {
|
|
|
109
110
|
export async function files_uploadWithProgress(localPath, remotePath, options = {}) {
|
|
110
111
|
const resolvedRemote = await path_resolveChrisFs(remotePath, {});
|
|
111
112
|
// Scan files
|
|
112
|
-
|
|
113
|
+
chiliLog(chalk.cyan("Scanning files to upload..."));
|
|
113
114
|
options.onProgress?.({
|
|
114
115
|
operation: "upload",
|
|
115
116
|
kind: "transfer",
|
|
@@ -184,12 +185,12 @@ export async function files_uploadWithProgress(localPath, remotePath, options =
|
|
|
184
185
|
}
|
|
185
186
|
else {
|
|
186
187
|
summary.failedCount++;
|
|
187
|
-
|
|
188
|
+
chiliLog(chalk.yellow(`Failed to upload: ${file.hostPath}`));
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
191
|
catch (error) {
|
|
191
192
|
summary.failedCount++;
|
|
192
|
-
|
|
193
|
+
chiliLog(chalk.red(`Error uploading ${file.hostPath}: ${error instanceof Error ? error.message : String(error)}`));
|
|
193
194
|
}
|
|
194
195
|
options.onProgress?.({
|
|
195
196
|
operation: "upload",
|
package/dist/commands/man/doc.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import fs from "fs";
|
|
10
10
|
import path from "path";
|
|
11
11
|
import { projectDir_get, browser_open, asciidoc_render } from "../../man/renderer.js";
|
|
12
|
+
import { chiliErrLog, chiliLog } from "../../screen/output.js";
|
|
12
13
|
/**
|
|
13
14
|
* Displays a documentation page for a specific topic.
|
|
14
15
|
*
|
|
@@ -19,7 +20,7 @@ export async function manPage_display(options) {
|
|
|
19
20
|
const docDir = path.join(projectDir_get(), "doc");
|
|
20
21
|
const docPath = path.join(docDir, `${options.topic}.adoc`);
|
|
21
22
|
if (!fs.existsSync(docPath)) {
|
|
22
|
-
|
|
23
|
+
chiliErrLog(`Documentation for '${options.topic}' not found.`);
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
25
26
|
if (options.browser) {
|
|
@@ -27,6 +28,6 @@ export async function manPage_display(options) {
|
|
|
27
28
|
}
|
|
28
29
|
else {
|
|
29
30
|
const content = fs.readFileSync(docPath, "utf-8");
|
|
30
|
-
|
|
31
|
+
chiliLog(await asciidoc_render(content, options.style, options.width));
|
|
31
32
|
}
|
|
32
33
|
}
|
|
@@ -14,13 +14,14 @@ import { computeResources_validate, computeResourceNames_parse, computeResources
|
|
|
14
14
|
import path from 'path';
|
|
15
15
|
import { input_detectFormat, PluginInputFormat, } from '../../utils/input_format.js';
|
|
16
16
|
import { adminCredentials_prompt, } from '../../utils/admin_prompt.js';
|
|
17
|
+
import { chiliErrLog, chiliLog } from "../../screen/output.js";
|
|
17
18
|
async function computeResources_resolve(options) {
|
|
18
19
|
if (options.compute) {
|
|
19
20
|
const names = computeResourceNames_parse(options.compute);
|
|
20
21
|
const validationResult = await computeResources_validate(names);
|
|
21
22
|
if (!validationResult.ok) {
|
|
22
23
|
const errors = errorStack.allOfType_get('error');
|
|
23
|
-
errors.forEach((err) =>
|
|
24
|
+
errors.forEach((err) => chiliErrLog(err));
|
|
24
25
|
return { ok: false };
|
|
25
26
|
}
|
|
26
27
|
return { ok: true, value: names };
|
|
@@ -28,7 +29,7 @@ async function computeResources_resolve(options) {
|
|
|
28
29
|
const allResult = await computeResources_getAll();
|
|
29
30
|
if (allResult.ok && allResult.value.length > 0) {
|
|
30
31
|
const names = allResult.value.map((r) => r.name);
|
|
31
|
-
|
|
32
|
+
chiliLog(`Using compute resources: ${names.join(', ')}`);
|
|
32
33
|
return { ok: true, value: names };
|
|
33
34
|
}
|
|
34
35
|
return { ok: true, value: ['host'] };
|
|
@@ -42,13 +43,13 @@ async function computeResources_resolve(options) {
|
|
|
42
43
|
*/
|
|
43
44
|
export async function plugin_add(input, options) {
|
|
44
45
|
const detected = input_detectFormat(input);
|
|
45
|
-
|
|
46
|
+
chiliLog(`Detected input format: ${detected.format}`);
|
|
46
47
|
const resourcesResult = await computeResources_resolve(options);
|
|
47
48
|
if (!resourcesResult.ok)
|
|
48
49
|
return 'failed';
|
|
49
50
|
const computeResources = resourcesResult.value;
|
|
50
51
|
// Phase 1: Check if plugin exists in current CUBE
|
|
51
|
-
|
|
52
|
+
chiliLog('\n=== Phase 1: Checking current CUBE ===');
|
|
52
53
|
const searchTerm = detected.format === PluginInputFormat.DOCKER_IMAGE
|
|
53
54
|
? detected.pluginName || detected.value
|
|
54
55
|
: detected.value;
|
|
@@ -56,10 +57,10 @@ export async function plugin_add(input, options) {
|
|
|
56
57
|
if (existingPlugin) {
|
|
57
58
|
return 'already_exists';
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
+
chiliLog('Plugin not found in current CUBE.');
|
|
60
61
|
// Phase 2: Search peer stores (skip if input is store URL)
|
|
61
62
|
if (detected.format !== PluginInputFormat.STORE_URL) {
|
|
62
|
-
|
|
63
|
+
chiliLog('\n=== Phase 2: Searching peer stores ===');
|
|
63
64
|
const peerStoreUrls = options.store
|
|
64
65
|
? [options.store]
|
|
65
66
|
: ['https://cube.chrisproject.org/api/v1/'];
|
|
@@ -71,15 +72,15 @@ export async function plugin_add(input, options) {
|
|
|
71
72
|
: undefined;
|
|
72
73
|
const peerResult = await plugins_searchPeers(searchName, searchVersion, peerStoreUrls);
|
|
73
74
|
if (peerResult) {
|
|
74
|
-
|
|
75
|
+
chiliLog(`Found plugin in peer store: ${peerResult.storeName}`);
|
|
75
76
|
const ok = await pluginFromStore_register(peerResult.plugin, computeResources, options);
|
|
76
77
|
return ok ? 'installed' : 'failed';
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
+
chiliLog('Plugin not found in peer stores.');
|
|
79
80
|
}
|
|
80
81
|
// Phase 3: Docker extraction (only for Docker images or plugin names)
|
|
81
82
|
if (detected.format !== PluginInputFormat.STORE_URL) {
|
|
82
|
-
|
|
83
|
+
chiliLog('\n=== Phase 3: Docker extraction ===');
|
|
83
84
|
const dockerImage = detected.format === PluginInputFormat.DOCKER_IMAGE
|
|
84
85
|
? detected.value
|
|
85
86
|
: `${detected.value}:latest`; // Assume latest tag for plugin names
|
|
@@ -87,7 +88,7 @@ export async function plugin_add(input, options) {
|
|
|
87
88
|
return ok ? 'installed' : 'failed';
|
|
88
89
|
}
|
|
89
90
|
// If we get here with a store URL, we couldn't process it
|
|
90
|
-
|
|
91
|
+
chiliErrLog('Store URL import not yet fully supported.');
|
|
91
92
|
return 'failed';
|
|
92
93
|
}
|
|
93
94
|
/**
|
|
@@ -101,7 +102,7 @@ export async function plugin_add(input, options) {
|
|
|
101
102
|
* @returns Promise resolving to success boolean.
|
|
102
103
|
*/
|
|
103
104
|
async function pluginFromStore_register(pluginData, computeResources, options) {
|
|
104
|
-
|
|
105
|
+
chiliLog('Importing plugin from peer store...');
|
|
105
106
|
const initialCreds = options.adminUser && options.adminPassword
|
|
106
107
|
? { username: options.adminUser, password: options.adminPassword }
|
|
107
108
|
: undefined;
|
|
@@ -109,11 +110,11 @@ async function pluginFromStore_register(pluginData, computeResources, options) {
|
|
|
109
110
|
const result = await plugin_importFromStore('', // Store URL not needed when we have plugin data
|
|
110
111
|
pluginData, computeResources, initialCreds);
|
|
111
112
|
if (result.success) {
|
|
112
|
-
|
|
113
|
+
chiliLog(`Plugin '${result.plugin?.name}' registered successfully.`);
|
|
113
114
|
return true;
|
|
114
115
|
}
|
|
115
116
|
if (!result.requiresAuth) {
|
|
116
|
-
|
|
117
|
+
chiliErrLog(result.errorMessage || 'Failed to import plugin from store.');
|
|
117
118
|
return false;
|
|
118
119
|
}
|
|
119
120
|
// Admin auth required - try with interactive credentials
|
|
@@ -122,16 +123,16 @@ async function pluginFromStore_register(pluginData, computeResources, options) {
|
|
|
122
123
|
return retryResult.success;
|
|
123
124
|
}, options);
|
|
124
125
|
if (!retrySuccess) {
|
|
125
|
-
|
|
126
|
+
chiliErrLog('Failed to import plugin from store (authentication failed or rejected).');
|
|
126
127
|
const errors = errorStack.allOfType_get('error');
|
|
127
128
|
if (errors.length > 0) {
|
|
128
|
-
|
|
129
|
-
errors.forEach((e) =>
|
|
129
|
+
chiliErrLog('Errors:');
|
|
130
|
+
errors.forEach((e) => chiliErrLog(`- ${e}`));
|
|
130
131
|
}
|
|
131
132
|
const warnings = errorStack.allOfType_get('warning');
|
|
132
133
|
if (warnings.length > 0) {
|
|
133
|
-
|
|
134
|
-
warnings.forEach((e) =>
|
|
134
|
+
chiliErrLog('Warnings:');
|
|
135
|
+
warnings.forEach((e) => chiliErrLog(`- ${e}`));
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
return retrySuccess;
|
|
@@ -155,11 +156,11 @@ async function pluginFromDocker_register(image, computeResources, options) {
|
|
|
155
156
|
if (!pulled) {
|
|
156
157
|
return false;
|
|
157
158
|
}
|
|
158
|
-
|
|
159
|
+
chiliLog('Extracting plugin descriptor from image...');
|
|
159
160
|
const pluginData = await pluginJSON_extractFromImage(image, options);
|
|
160
161
|
if (!pluginData) {
|
|
161
162
|
const msg = 'Failed to extract plugin descriptor from image.';
|
|
162
|
-
|
|
163
|
+
chiliErrLog(msg);
|
|
163
164
|
errorStack.stack_push('error', msg);
|
|
164
165
|
return false;
|
|
165
166
|
}
|
|
@@ -169,10 +170,10 @@ async function pluginFromDocker_register(image, computeResources, options) {
|
|
|
169
170
|
? { username: options.adminUser, password: options.adminPassword }
|
|
170
171
|
: undefined;
|
|
171
172
|
// Register with admin API
|
|
172
|
-
|
|
173
|
+
chiliLog('Registering plugin with ChRIS CUBE...');
|
|
173
174
|
const registered = await plugin_registerWithAdmin(pluginData, computeResources, initialCreds);
|
|
174
175
|
if (registered) {
|
|
175
|
-
|
|
176
|
+
chiliLog(`Plugin '${registered.name}' registered successfully.`);
|
|
176
177
|
return true;
|
|
177
178
|
}
|
|
178
179
|
// Check if failure was due to admin auth
|
|
@@ -187,7 +188,7 @@ async function pluginFromDocker_register(image, computeResources, options) {
|
|
|
187
188
|
lowerE.includes('admin credentials required');
|
|
188
189
|
});
|
|
189
190
|
if (!authError) {
|
|
190
|
-
|
|
191
|
+
chiliErrLog('Failed to register plugin.');
|
|
191
192
|
return false;
|
|
192
193
|
}
|
|
193
194
|
// Retry with admin credentials
|
|
@@ -224,17 +225,17 @@ async function pluginJSON_extractFromImage(image, options) {
|
|
|
224
225
|
},
|
|
225
226
|
];
|
|
226
227
|
for (const method of methods) {
|
|
227
|
-
|
|
228
|
+
chiliLog(`Trying ${method.name}...`);
|
|
228
229
|
const jsonString = await method.fn();
|
|
229
230
|
if (jsonString && jsonString.trim() !== '') {
|
|
230
231
|
try {
|
|
231
232
|
const parsed = JSON.parse(jsonString);
|
|
232
|
-
|
|
233
|
+
chiliLog(`Successfully extracted plugin descriptor using ${method.name}`);
|
|
233
234
|
return parsed;
|
|
234
235
|
}
|
|
235
236
|
catch (e) {
|
|
236
237
|
const msg = `Failed to parse JSON from ${method.name}`;
|
|
237
|
-
|
|
238
|
+
chiliErrLog(msg);
|
|
238
239
|
errorStack.stack_push('error', msg);
|
|
239
240
|
}
|
|
240
241
|
}
|
|
@@ -296,7 +297,7 @@ async function pluginJSON_tryOldChrisapp(image) {
|
|
|
296
297
|
return null;
|
|
297
298
|
}
|
|
298
299
|
const command = `docker run --rm ${image} ${cmd[0]} --json`;
|
|
299
|
-
|
|
300
|
+
chiliLog(` Running: ${cmd[0]} --json`);
|
|
300
301
|
const result = await shellCommand_runWithDetails(command);
|
|
301
302
|
if (!result.success || !result.stdout || result.stdout.trim() === '') {
|
|
302
303
|
if (result.error || result.stderr) {
|
|
@@ -319,20 +320,20 @@ function pluginData_inferMissingFields(pluginData, image, options) {
|
|
|
319
320
|
if (!pluginData.name) {
|
|
320
321
|
const imageNameWithoutTag = image.split(':')[0];
|
|
321
322
|
pluginData.name = path.basename(imageNameWithoutTag);
|
|
322
|
-
|
|
323
|
+
chiliLog(`Inferred plugin name: ${pluginData.name}`);
|
|
323
324
|
}
|
|
324
325
|
if (!pluginData.dock_image) {
|
|
325
326
|
pluginData.dock_image = image;
|
|
326
|
-
|
|
327
|
+
chiliLog(`Inferred dock_image: ${pluginData.dock_image}`);
|
|
327
328
|
}
|
|
328
329
|
if (!pluginData.public_repo && options.public_repo) {
|
|
329
330
|
pluginData.public_repo = options.public_repo;
|
|
330
|
-
|
|
331
|
+
chiliLog(`Using provided public_repo: ${pluginData.public_repo}`);
|
|
331
332
|
}
|
|
332
333
|
else if (!pluginData.public_repo && image.includes('/')) {
|
|
333
334
|
const repoGuess = image.split('/')[0] + '/' + path.basename(image.split(':')[0]);
|
|
334
335
|
pluginData.public_repo = `https://github.com/${repoGuess}`;
|
|
335
|
-
|
|
336
|
+
chiliLog(`Inferred public_repo: ${pluginData.public_repo}`);
|
|
336
337
|
}
|
|
337
338
|
}
|
|
338
339
|
/**
|
|
@@ -358,7 +359,7 @@ async function registrationWithAuth_retry(registrationFn, options) {
|
|
|
358
359
|
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
359
360
|
const creds = await adminCredentials_prompt(attempt, MAX_ATTEMPTS);
|
|
360
361
|
if (!creds) {
|
|
361
|
-
|
|
362
|
+
chiliLog('Authentication cancelled.');
|
|
362
363
|
return false;
|
|
363
364
|
}
|
|
364
365
|
const success = await registrationFn(creds);
|
|
@@ -366,9 +367,9 @@ async function registrationWithAuth_retry(registrationFn, options) {
|
|
|
366
367
|
return true;
|
|
367
368
|
}
|
|
368
369
|
if (attempt < MAX_ATTEMPTS) {
|
|
369
|
-
|
|
370
|
+
chiliLog('Authentication failed.');
|
|
370
371
|
}
|
|
371
372
|
}
|
|
372
|
-
|
|
373
|
+
chiliErrLog(`Authentication failed after ${MAX_ATTEMPTS} attempts.`);
|
|
373
374
|
return false;
|
|
374
375
|
}
|
|
@@ -11,6 +11,7 @@ import * as fs from 'fs';
|
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import { fileURLToPath } from 'url';
|
|
13
13
|
import chalk from 'chalk';
|
|
14
|
+
import { chiliErrLog } from "../screen/output.js";
|
|
14
15
|
let cachedConfig = null;
|
|
15
16
|
/**
|
|
16
17
|
* Loads the color configuration from colors.yml.
|
|
@@ -32,7 +33,7 @@ function colorConfig_load() {
|
|
|
32
33
|
}
|
|
33
34
|
catch (e) {
|
|
34
35
|
const msg = e instanceof Error ? e.message : String(e);
|
|
35
|
-
|
|
36
|
+
chiliErrLog(`Warning: Could not load color config: ${msg}`);
|
|
36
37
|
return {
|
|
37
38
|
icons: {
|
|
38
39
|
enabled: true,
|
|
@@ -2,6 +2,7 @@ import { connect_login } from "../commands/connect/login.js";
|
|
|
2
2
|
import { connect_logout } from "../commands/connect/logout.js";
|
|
3
3
|
import { login_render, logout_render } from "../views/connect.js";
|
|
4
4
|
import chalk from "chalk";
|
|
5
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
5
6
|
/**
|
|
6
7
|
* Sets up the 'connect' and 'logout' commands for the CLI program.
|
|
7
8
|
*
|
|
@@ -23,12 +24,12 @@ export function connectCommand_setup(program) {
|
|
|
23
24
|
};
|
|
24
25
|
try {
|
|
25
26
|
const success = await connect_login(connectOptions);
|
|
26
|
-
|
|
27
|
+
chiliLog(login_render(success, url, user));
|
|
27
28
|
}
|
|
28
29
|
catch (error) {
|
|
29
|
-
|
|
30
|
+
chiliLog(login_render(false, url, user));
|
|
30
31
|
const msg = error instanceof Error ? error.message : String(error);
|
|
31
|
-
|
|
32
|
+
chiliErrLog(chalk.red(`Error: ${msg}`));
|
|
32
33
|
}
|
|
33
34
|
});
|
|
34
35
|
program
|
|
@@ -37,12 +38,12 @@ export function connectCommand_setup(program) {
|
|
|
37
38
|
.action(async () => {
|
|
38
39
|
try {
|
|
39
40
|
await connect_logout();
|
|
40
|
-
|
|
41
|
+
chiliLog(logout_render(true));
|
|
41
42
|
}
|
|
42
43
|
catch (error) {
|
|
43
|
-
|
|
44
|
+
chiliLog(logout_render(false));
|
|
44
45
|
const msg = error instanceof Error ? error.message : String(error);
|
|
45
|
-
|
|
46
|
+
chiliErrLog(chalk.red(`Error: ${msg}`));
|
|
46
47
|
}
|
|
47
48
|
});
|
|
48
49
|
}
|
|
@@ -8,6 +8,7 @@ import { context_getFull, context_getSingle, context_set as salsa_context_set }
|
|
|
8
8
|
import chalk from "chalk";
|
|
9
9
|
// import Table from "cli-table3";
|
|
10
10
|
import { screen, border_draw, table_display } from "../screen/screen.js";
|
|
11
|
+
import { chiliLog } from "../screen/output.js";
|
|
11
12
|
/**
|
|
12
13
|
* Retrieves and formats ChRIS context information based on CLI options.
|
|
13
14
|
*
|
|
@@ -94,7 +95,7 @@ async function context_displaySingle(options) {
|
|
|
94
95
|
Value: singleContext.pacsserver || "Not set",
|
|
95
96
|
},
|
|
96
97
|
];
|
|
97
|
-
|
|
98
|
+
chiliLog(screen.table_output(tableData, {
|
|
98
99
|
head: ["Context", "Value"],
|
|
99
100
|
columns: [
|
|
100
101
|
{ color: "yellow", justification: "right" },
|
|
@@ -174,7 +175,7 @@ export async function contextCommand_setup(program) {
|
|
|
174
175
|
.option("--all", "get all contexts for current session")
|
|
175
176
|
.action(async (options) => {
|
|
176
177
|
const result = await context_get(options);
|
|
177
|
-
|
|
178
|
+
chiliLog(result);
|
|
178
179
|
});
|
|
179
180
|
contextCommand
|
|
180
181
|
.command("set")
|
|
@@ -7,6 +7,7 @@ import { errorStack } from "@fnndsc/cumin";
|
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import { BaseController } from "./baseController.js";
|
|
9
9
|
import { files_getGroup, files_getSingle, files_share as salsaFiles_share, fileContent_get } from "@fnndsc/salsa";
|
|
10
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
10
11
|
/**
|
|
11
12
|
* Controller for managing ChRIS file system resources (files, links, directories).
|
|
12
13
|
* Extends BaseController to provide file-specific functionality.
|
|
@@ -62,7 +63,7 @@ export class FileController extends BaseController {
|
|
|
62
63
|
async files_share(options) {
|
|
63
64
|
const fileId = options.fileId; // Assuming CLIoptions has a fileId property
|
|
64
65
|
if (fileId === undefined) {
|
|
65
|
-
|
|
66
|
+
chiliErrLog("Error: fileId is required for sharing.");
|
|
66
67
|
return;
|
|
67
68
|
}
|
|
68
69
|
const shareOptions = { ...options }; // Pass all CLI options as share options for now
|
|
@@ -78,10 +79,10 @@ export class FileController extends BaseController {
|
|
|
78
79
|
const result = await fileContent_get(filePath);
|
|
79
80
|
if (!result.ok) {
|
|
80
81
|
const error = errorStack.stack_pop();
|
|
81
|
-
|
|
82
|
+
chiliErrLog(chalk.red(`Error viewing file: ${error?.message || 'Unknown error'}`));
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
chiliLog(result.value);
|
|
85
86
|
}
|
|
86
87
|
/**
|
|
87
88
|
* Gets the current path associated with this controller.
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { ChRISPluginGroup, dictionary_fromCLI } from "@fnndsc/cumin";
|
|
7
7
|
import { BaseController } from "./baseController.js";
|
|
8
8
|
import { plugin_run as salsaPlugin_run, plugins_searchableToIDs as salsaPlugins_searchableToIDs, pluginMeta_readmeContentFetch, pluginMeta_documentationUrlGet, pluginMeta_pluginIDFromSearch } from "@fnndsc/salsa";
|
|
9
|
+
import { chiliErrLog } from "../screen/output.js";
|
|
9
10
|
/**
|
|
10
11
|
* Controller for managing ChRIS plugins.
|
|
11
12
|
* Handles plugin searching, running, and group operations.
|
|
@@ -54,7 +55,7 @@ export class PluginController extends BaseController {
|
|
|
54
55
|
parsedParams = dictionary_fromCLI(params);
|
|
55
56
|
}
|
|
56
57
|
catch (e) {
|
|
57
|
-
|
|
58
|
+
chiliErrLog("Error parsing plugin parameters:", e);
|
|
58
59
|
return null;
|
|
59
60
|
}
|
|
60
61
|
return await salsaPlugin_run(searchable, parsedParams);
|