@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.
@@ -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
- console.log(long_render(items, { human: !!options.human }));
25
+ chiliLog(long_render(items, { human: !!options.human }));
25
26
  }
26
27
  else {
27
- console.log(grid_render(items));
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
- console.log(cp_render(src, dest, success));
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
- console.log(mv_render(src, dest, success));
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
- console.log(mkdir_render(dirPath, success));
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
- console.log(touch_render(filePath, success));
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
- console.log(`Uploading ${localPath} to ${remotePath}...`);
78
+ chiliLog(`Uploading ${localPath} to ${remotePath}...`);
78
79
  const success = await files_upload(localPath, remotePath);
79
- console.log(upload_render(localPath, remotePath, success));
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
- console.log(current || "/");
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
- console.log(cat_render(content, filePath));
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
- console.log(rm_render(result));
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
- console.log(chalk.cyan("Scanning files to download..."));
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
- console.log(chalk.yellow(`\nFailed to download: ${file.path}`));
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
- console.log(chalk.red(`\nError downloading ${file.path}: ${msg}`));
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
- console.log(chalk.cyan("Scanning files to upload..."));
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
- console.log(chalk.yellow(`Failed to upload: ${file.hostPath}`));
188
+ chiliLog(chalk.yellow(`Failed to upload: ${file.hostPath}`));
188
189
  }
189
190
  }
190
191
  catch (error) {
191
192
  summary.failedCount++;
192
- console.log(chalk.red(`Error uploading ${file.hostPath}: ${error instanceof Error ? error.message : String(error)}`));
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",
@@ -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
- console.error(`Documentation for '${options.topic}' not found.`);
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
- console.log(await asciidoc_render(content, options.style, options.width));
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) => console.error(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
- console.log(`Using compute resources: ${names.join(', ')}`);
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
- console.log(`Detected input format: ${detected.format}`);
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
- console.log('\n=== Phase 1: Checking current CUBE ===');
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
- console.log('Plugin not found in current CUBE.');
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
- console.log('\n=== Phase 2: Searching peer stores ===');
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
- console.log(`Found plugin in peer store: ${peerResult.storeName}`);
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
- console.log('Plugin not found in peer stores.');
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
- console.log('\n=== Phase 3: Docker extraction ===');
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
- console.error('Store URL import not yet fully supported.');
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
- console.log('Importing plugin from peer store...');
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
- console.log(`Plugin '${result.plugin?.name}' registered successfully.`);
113
+ chiliLog(`Plugin '${result.plugin?.name}' registered successfully.`);
113
114
  return true;
114
115
  }
115
116
  if (!result.requiresAuth) {
116
- console.error(result.errorMessage || 'Failed to import plugin from store.');
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
- console.error('Failed to import plugin from store (authentication failed or rejected).');
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
- console.error('Errors:');
129
- errors.forEach((e) => console.error(`- ${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
- console.error('Warnings:');
134
- warnings.forEach((e) => console.error(`- ${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
- console.log('Extracting plugin descriptor from image...');
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
- console.error(msg);
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
- console.log('Registering plugin with ChRIS CUBE...');
173
+ chiliLog('Registering plugin with ChRIS CUBE...');
173
174
  const registered = await plugin_registerWithAdmin(pluginData, computeResources, initialCreds);
174
175
  if (registered) {
175
- console.log(`Plugin '${registered.name}' registered successfully.`);
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
- console.error('Failed to register plugin.');
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
- console.log(`Trying ${method.name}...`);
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
- console.log(`Successfully extracted plugin descriptor using ${method.name}`);
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
- console.error(msg);
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
- console.log(` Running: ${cmd[0]} --json`);
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
- console.log(`Inferred plugin name: ${pluginData.name}`);
323
+ chiliLog(`Inferred plugin name: ${pluginData.name}`);
323
324
  }
324
325
  if (!pluginData.dock_image) {
325
326
  pluginData.dock_image = image;
326
- console.log(`Inferred dock_image: ${pluginData.dock_image}`);
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
- console.log(`Using provided public_repo: ${pluginData.public_repo}`);
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
- console.log(`Inferred public_repo: ${pluginData.public_repo}`);
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
- console.log('Authentication cancelled.');
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
- console.log('Authentication failed.');
370
+ chiliLog('Authentication failed.');
370
371
  }
371
372
  }
372
- console.error(`Authentication failed after ${MAX_ATTEMPTS} attempts.`);
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
- console.error(`Warning: Could not load color config: ${msg}`);
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
- console.log(login_render(success, url, user));
27
+ chiliLog(login_render(success, url, user));
27
28
  }
28
29
  catch (error) {
29
- console.log(login_render(false, url, user));
30
+ chiliLog(login_render(false, url, user));
30
31
  const msg = error instanceof Error ? error.message : String(error);
31
- console.error(chalk.red(`Error: ${msg}`));
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
- console.log(logout_render(true));
41
+ chiliLog(logout_render(true));
41
42
  }
42
43
  catch (error) {
43
- console.log(logout_render(false));
44
+ chiliLog(logout_render(false));
44
45
  const msg = error instanceof Error ? error.message : String(error);
45
- console.error(chalk.red(`Error: ${msg}`));
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
- console.log(screen.table_output(tableData, {
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
- console.log(result);
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
- console.error("Error: fileId is required for sharing.");
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
- console.error(chalk.red(`Error viewing file: ${error?.message || 'Unknown error'}`));
82
+ chiliErrLog(chalk.red(`Error viewing file: ${error?.message || 'Unknown error'}`));
82
83
  return;
83
84
  }
84
- console.log(result.value);
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
- console.error("Error parsing plugin parameters:", e);
58
+ chiliErrLog("Error parsing plugin parameters:", e);
58
59
  return null;
59
60
  }
60
61
  return await salsaPlugin_run(searchable, parsedParams);