@fnndsc/chili 3.4.0 → 3.6.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.d.ts +18 -5
- package/dist/filesystem/fileGroupHandler.js +68 -46
- package/dist/filesystem/filesystemHandler.js +13 -11
- package/dist/filesystem/inodeCommand.js +3 -2
- package/dist/handlers/baseGroupHandler.d.ts +8 -2
- package/dist/handlers/baseGroupHandler.js +30 -18
- 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.d.ts +17 -6
- package/dist/plugins/pluginGroupHandler.js +58 -37
- package/dist/plugins/pluginHandler.js +23 -22
- package/dist/run.d.ts +22 -0
- package/dist/run.js +42 -46
- 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 { feeds_searchByTerm, feed_deleteById } from "../commands/feeds/delete.js
|
|
|
9
9
|
import { prompt_confirm } from "../utils/ui.js";
|
|
10
10
|
import { feed_create as feed_create_command } from "../commands/feed/create.js"; // Original name
|
|
11
11
|
import { feedCreate_render } from "../views/feed.js"; // Still needed for feedCreate_render
|
|
12
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
12
13
|
// import { FeedListResult } from "../commands/feeds/list.js"; // No longer needed
|
|
13
14
|
/**
|
|
14
15
|
* Handles commands related to groups of ChRIS feeds.
|
|
@@ -25,10 +26,10 @@ export class FeedGroupHandler {
|
|
|
25
26
|
// async feeds_list(options: CLIoptions): Promise<void> {
|
|
26
27
|
// try {
|
|
27
28
|
// const { feeds, selectedFields }: FeedListResult = await feeds_fetchList(options);
|
|
28
|
-
//
|
|
29
|
+
// chiliLog(feedList_render(feeds, selectedFields, { table: options.table, csv: options.csv }));
|
|
29
30
|
// } catch (error: unknown) {
|
|
30
31
|
// const msg = error instanceof Error ? error.message : String(error);
|
|
31
|
-
//
|
|
32
|
+
// chiliErrLog(chalk.red(`Error listing feeds: ${msg}`));
|
|
32
33
|
// }
|
|
33
34
|
// }
|
|
34
35
|
/**
|
|
@@ -41,11 +42,11 @@ export class FeedGroupHandler {
|
|
|
41
42
|
table_display(fields, ["fields"]);
|
|
42
43
|
}
|
|
43
44
|
else {
|
|
44
|
-
|
|
45
|
+
chiliLog(`No resource fields found for ${this.assetName}.`);
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
catch (error) {
|
|
48
|
-
|
|
49
|
+
chiliLog(errorStack.stack_search(this.assetName)[0]);
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
@@ -59,18 +60,18 @@ export class FeedGroupHandler {
|
|
|
59
60
|
for (const searchPart of searchParts) {
|
|
60
61
|
const feedIds = await this.baseGroupHandler.IDs_getFromSearch({ search: searchPart });
|
|
61
62
|
if (!feedIds || feedIds.length === 0) {
|
|
62
|
-
|
|
63
|
+
chiliLog(`No feeds found matching: ${searchPart}`);
|
|
63
64
|
continue;
|
|
64
65
|
}
|
|
65
66
|
for (const feedId of feedIds) {
|
|
66
|
-
|
|
67
|
+
chiliLog(`Sharing feed ID: ${feedId}...`);
|
|
67
68
|
const shareOptions = { is_public: options.is_public === true };
|
|
68
69
|
const success = await feed_shareById(Number(feedId), shareOptions);
|
|
69
70
|
if (success) {
|
|
70
|
-
|
|
71
|
+
chiliLog(`Feed ID ${feedId} shared successfully.`);
|
|
71
72
|
}
|
|
72
73
|
else {
|
|
73
|
-
|
|
74
|
+
chiliErrLog(`Failed to share feed ID ${feedId}.`);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
}
|
|
@@ -85,11 +86,11 @@ export class FeedGroupHandler {
|
|
|
85
86
|
for (const searchPart of searchParts) {
|
|
86
87
|
const items = await feeds_searchByTerm(searchPart);
|
|
87
88
|
if (items.length === 0) {
|
|
88
|
-
|
|
89
|
+
chiliLog(`No feeds found matching: ${searchPart}`);
|
|
89
90
|
continue;
|
|
90
91
|
}
|
|
91
92
|
for (const item of items) {
|
|
92
|
-
|
|
93
|
+
chiliLog(`Preparing to delete Feed: ID=${item.id}, Name=${item.name}`);
|
|
93
94
|
if (!options.force) {
|
|
94
95
|
const confirmed = await prompt_confirm(`Are you sure you want to delete feed ${item.name} (ID: ${item.id})?`);
|
|
95
96
|
if (!confirmed)
|
|
@@ -98,10 +99,10 @@ export class FeedGroupHandler {
|
|
|
98
99
|
const id = typeof item.id === "number" ? item.id : Number(item.id);
|
|
99
100
|
const success = await feed_deleteById(id);
|
|
100
101
|
if (success) {
|
|
101
|
-
|
|
102
|
+
chiliLog(`Deleted feed ${item.id}`);
|
|
102
103
|
}
|
|
103
104
|
else {
|
|
104
|
-
|
|
105
|
+
chiliErrLog(`Failed to delete feed ${item.id}`);
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
}
|
|
@@ -160,20 +161,20 @@ export class FeedMemberHandler {
|
|
|
160
161
|
try {
|
|
161
162
|
const feed = await feed_create_command(options);
|
|
162
163
|
if (feed) {
|
|
163
|
-
|
|
164
|
+
chiliLog(feedCreate_render(feed));
|
|
164
165
|
return feed;
|
|
165
166
|
}
|
|
166
|
-
|
|
167
|
+
chiliErrLog(chalk.red("Feed creation returned null result."));
|
|
167
168
|
const errors = errorStack.allOfType_get('error'); // Keep error reporting
|
|
168
169
|
if (errors.length > 0) {
|
|
169
|
-
|
|
170
|
-
errors.forEach(e =>
|
|
170
|
+
chiliErrLog(chalk.red('Errors:'));
|
|
171
|
+
errors.forEach(e => chiliErrLog(chalk.red(` - ${e}`)));
|
|
171
172
|
}
|
|
172
173
|
return null;
|
|
173
174
|
}
|
|
174
175
|
catch (error) {
|
|
175
176
|
const message = error instanceof Error ? error.message : String(error);
|
|
176
|
-
|
|
177
|
+
chiliErrLog(chalk.red(`Error: ${message}`));
|
|
177
178
|
return null;
|
|
178
179
|
}
|
|
179
180
|
}
|
|
@@ -197,7 +198,7 @@ export class FeedMemberHandler {
|
|
|
197
198
|
});
|
|
198
199
|
}
|
|
199
200
|
else {
|
|
200
|
-
|
|
201
|
+
chiliErrLog(`Failed to find '${this.assetName}' command. The 'new' subcommand was not added.`);
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
}
|
|
@@ -13,18 +13,31 @@ import { CLIoptions } from "../utils/cli.js";
|
|
|
13
13
|
* Handles commands related to groups of ChRIS files, links, or directories.
|
|
14
14
|
*/
|
|
15
15
|
export declare class FileGroupHandler {
|
|
16
|
-
private baseGroupHandler;
|
|
17
16
|
private controller;
|
|
18
17
|
readonly assetName: string;
|
|
18
|
+
private readonly path?;
|
|
19
19
|
private constructor();
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Creates a FileGroupHandler for an asset type. This performs no network work
|
|
22
|
+
* and resolves no ChRIS context — command registration needs only the asset
|
|
23
|
+
* name, and the controller is resolved lazily on first use (see
|
|
24
|
+
* {@link controller_ensure}). Keeping setup cheap means an unrelated command
|
|
25
|
+
* (or a directory that is not a ChRIS folder) pays no file-context cost.
|
|
22
26
|
*
|
|
23
27
|
* @param assetName - The type of asset to handle ('files', 'links', 'dirs').
|
|
24
|
-
* @param path - Optional path within ChRIS FS
|
|
25
|
-
*
|
|
28
|
+
* @param path - Optional path within ChRIS FS the controller binds to;
|
|
29
|
+
* defaults to the current ChRIS folder context.
|
|
30
|
+
* @returns A new FileGroupHandler instance.
|
|
31
|
+
*/
|
|
32
|
+
static handler_create(assetName: string, path?: string): FileGroupHandler;
|
|
33
|
+
/**
|
|
34
|
+
* Lazily resolves and memoizes the FileController for this asset against the
|
|
35
|
+
* bound path (or the current ChRIS context).
|
|
36
|
+
*
|
|
37
|
+
* @returns The controller, or null if the context cannot be resolved here
|
|
38
|
+
* (e.g. the current directory is not a ChRIS folder).
|
|
26
39
|
*/
|
|
27
|
-
|
|
40
|
+
private controller_ensure;
|
|
28
41
|
/**
|
|
29
42
|
* Lists files, links, or directories using the new command logic.
|
|
30
43
|
*/
|
|
@@ -12,35 +12,50 @@ import { files_searchByTerm, files_deleteById } from "../commands/files/delete.j
|
|
|
12
12
|
import { prompt_confirm } from "../utils/ui.js";
|
|
13
13
|
import { files_viewContent } from "../commands/file/view.js";
|
|
14
14
|
import { fileList_render } from "../views/file.js";
|
|
15
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
15
16
|
/**
|
|
16
17
|
* Handles commands related to groups of ChRIS files, links, or directories.
|
|
17
18
|
*/
|
|
18
19
|
export class FileGroupHandler {
|
|
19
|
-
constructor(
|
|
20
|
-
|
|
20
|
+
constructor(assetName, path) {
|
|
21
|
+
// Resolved lazily: only `share` needs a controller; list/fields/delete
|
|
22
|
+
// re-resolve their context through standalone salsa helpers.
|
|
23
|
+
this.controller = null;
|
|
21
24
|
this.assetName = assetName;
|
|
22
|
-
|
|
23
|
-
this.baseGroupHandler = new BaseGroupHandler(this.assetName, this.controller.chrisObject);
|
|
25
|
+
this.path = path;
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
26
|
-
*
|
|
28
|
+
* Creates a FileGroupHandler for an asset type. This performs no network work
|
|
29
|
+
* and resolves no ChRIS context — command registration needs only the asset
|
|
30
|
+
* name, and the controller is resolved lazily on first use (see
|
|
31
|
+
* {@link controller_ensure}). Keeping setup cheap means an unrelated command
|
|
32
|
+
* (or a directory that is not a ChRIS folder) pays no file-context cost.
|
|
27
33
|
*
|
|
28
34
|
* @param assetName - The type of asset to handle ('files', 'links', 'dirs').
|
|
29
|
-
* @param path - Optional path within ChRIS FS
|
|
30
|
-
*
|
|
35
|
+
* @param path - Optional path within ChRIS FS the controller binds to;
|
|
36
|
+
* defaults to the current ChRIS folder context.
|
|
37
|
+
* @returns A new FileGroupHandler instance.
|
|
31
38
|
*/
|
|
32
|
-
static
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
static handler_create(assetName, path) {
|
|
40
|
+
return new FileGroupHandler(assetName, path);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Lazily resolves and memoizes the FileController for this asset against the
|
|
44
|
+
* bound path (or the current ChRIS context).
|
|
45
|
+
*
|
|
46
|
+
* @returns The controller, or null if the context cannot be resolved here
|
|
47
|
+
* (e.g. the current directory is not a ChRIS folder).
|
|
48
|
+
*/
|
|
49
|
+
async controller_ensure() {
|
|
50
|
+
if (!this.controller) {
|
|
51
|
+
try {
|
|
52
|
+
this.controller = await FileController.handler_create(this.assetName, this.path);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
this.controller = null;
|
|
37
56
|
}
|
|
38
|
-
return new FileGroupHandler(controller, assetName);
|
|
39
|
-
}
|
|
40
|
-
catch (error) {
|
|
41
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
42
|
-
throw new Error(`Failed to initialize FileGroupHandler for ${assetName}: ${errorMessage}`);
|
|
43
57
|
}
|
|
58
|
+
return this.controller;
|
|
44
59
|
}
|
|
45
60
|
/**
|
|
46
61
|
* Lists files, links, or directories using the new command logic.
|
|
@@ -49,33 +64,33 @@ export class FileGroupHandler {
|
|
|
49
64
|
try {
|
|
50
65
|
const results = await files_fetchList(options, this.assetName, path);
|
|
51
66
|
if (!results) {
|
|
52
|
-
|
|
67
|
+
chiliErrLog(`No ${this.assetName} resources found. Perhaps check your current context?`);
|
|
53
68
|
return;
|
|
54
69
|
}
|
|
55
70
|
if (results.tableData.length === 0) {
|
|
56
|
-
|
|
71
|
+
chiliLog(`No ${this.assetName} found matching the criteria.`);
|
|
57
72
|
}
|
|
58
73
|
else {
|
|
59
74
|
const uniqueResults = resourceColumns_removeDuplicates(results);
|
|
60
75
|
// cumin returns dynamic table rows (Record<string, unknown>[]);
|
|
61
76
|
// narrow to the FileResource view model at this boundary.
|
|
62
|
-
|
|
77
|
+
chiliLog(fileList_render(uniqueResults.tableData, uniqueResults.selectedFields, { table: options.table, csv: options.csv }));
|
|
63
78
|
}
|
|
64
79
|
}
|
|
65
80
|
catch (error) {
|
|
66
81
|
const errors = errorStack.stack_search(this.assetName);
|
|
67
82
|
if (errors.length > 0) {
|
|
68
|
-
|
|
83
|
+
chiliLog(errors[0]);
|
|
69
84
|
}
|
|
70
85
|
else {
|
|
71
86
|
const msg = error instanceof Error ? error.message : String(error);
|
|
72
|
-
|
|
87
|
+
chiliErrLog(`Error: ${msg}`);
|
|
73
88
|
const errObj = error;
|
|
74
89
|
if (msg.includes("Internal server error") || (errObj && errObj.response && errObj.response.status === 500)) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
chiliErrLog(chalk.yellow("\nHint: This indicates a problem on the ChRIS server (CUBE)."));
|
|
91
|
+
chiliErrLog(chalk.yellow(" Please contact your system administrator or check the CUBE logs."));
|
|
92
|
+
chiliErrLog(chalk.yellow(" To see full debug output, run the command again with CHILI_DEBUG=true:"));
|
|
93
|
+
chiliErrLog(chalk.yellow(" CHILI_DEBUG=true chili ..."));
|
|
79
94
|
}
|
|
80
95
|
}
|
|
81
96
|
}
|
|
@@ -90,11 +105,11 @@ export class FileGroupHandler {
|
|
|
90
105
|
table_display(fields, ["fields"]);
|
|
91
106
|
}
|
|
92
107
|
else {
|
|
93
|
-
|
|
108
|
+
chiliLog(`No resource fields found for ${this.assetName}.`);
|
|
94
109
|
}
|
|
95
110
|
}
|
|
96
111
|
catch (error) {
|
|
97
|
-
|
|
112
|
+
chiliLog(errorStack.stack_search(this.assetName)[0]);
|
|
98
113
|
}
|
|
99
114
|
}
|
|
100
115
|
/**
|
|
@@ -105,16 +120,16 @@ export class FileGroupHandler {
|
|
|
105
120
|
for (const searchPart of searchParts) {
|
|
106
121
|
const items = await files_searchByTerm(searchPart, this.assetName);
|
|
107
122
|
if (items.length === 0) {
|
|
108
|
-
|
|
123
|
+
chiliLog(`No ${this.assetName} found matching: ${searchPart}`);
|
|
109
124
|
continue;
|
|
110
125
|
}
|
|
111
126
|
for (const item of items) {
|
|
112
127
|
const displayName = item.fname || item.path || item.id;
|
|
113
128
|
if (!item.id) {
|
|
114
|
-
|
|
129
|
+
chiliErrLog(`Cannot delete item without ID. Details: ${JSON.stringify(item)}`);
|
|
115
130
|
continue;
|
|
116
131
|
}
|
|
117
|
-
|
|
132
|
+
chiliLog(`Preparing to delete ${this.assetName}: ID=${item.id}, Name=${displayName}`);
|
|
118
133
|
if (!options.force) {
|
|
119
134
|
const confirmed = await prompt_confirm(`Are you sure you want to delete ${this.assetName} ${displayName} (ID: ${item.id})?`);
|
|
120
135
|
if (!confirmed)
|
|
@@ -122,10 +137,10 @@ export class FileGroupHandler {
|
|
|
122
137
|
}
|
|
123
138
|
const success = await files_deleteById(item.id, this.assetName);
|
|
124
139
|
if (success) {
|
|
125
|
-
|
|
140
|
+
chiliLog(`Deleted ${this.assetName} ${item.id}`);
|
|
126
141
|
}
|
|
127
142
|
else {
|
|
128
|
-
|
|
143
|
+
chiliErrLog(`Failed to delete ${this.assetName} ${item.id}`);
|
|
129
144
|
}
|
|
130
145
|
}
|
|
131
146
|
}
|
|
@@ -136,19 +151,24 @@ export class FileGroupHandler {
|
|
|
136
151
|
* @param options - CLI options for sharing files.
|
|
137
152
|
*/
|
|
138
153
|
async files_share(options) {
|
|
154
|
+
const controller = await this.controller_ensure();
|
|
155
|
+
if (!controller) {
|
|
156
|
+
chiliErrLog(`Cannot share ${this.assetName}: no ChRIS context is available in the current directory.`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
139
159
|
try {
|
|
140
|
-
|
|
160
|
+
chiliLog(`Sharing ${this.assetName} from ${controller.path_get}...`);
|
|
141
161
|
if (options.force) {
|
|
142
|
-
|
|
162
|
+
chiliLog("Force sharing enabled");
|
|
143
163
|
}
|
|
144
|
-
await
|
|
164
|
+
await controller.files_share(options);
|
|
145
165
|
}
|
|
146
166
|
catch (error) {
|
|
147
167
|
if (error instanceof Error) {
|
|
148
|
-
|
|
168
|
+
chiliErrLog(`Error sharing ${this.assetName}: ${error.message}`);
|
|
149
169
|
}
|
|
150
170
|
else {
|
|
151
|
-
|
|
171
|
+
chiliErrLog(`An unknown error occurred while sharing the ${this.assetName}`);
|
|
152
172
|
}
|
|
153
173
|
}
|
|
154
174
|
}
|
|
@@ -161,7 +181,9 @@ export class FileGroupHandler {
|
|
|
161
181
|
const fileGroupCommand = program
|
|
162
182
|
.command(this.assetName)
|
|
163
183
|
.description(`Interact with a group of ChRIS ${this.assetName}`);
|
|
164
|
-
|
|
184
|
+
// The list command only needs the asset name to register; a context-less
|
|
185
|
+
// BaseGroupHandler is enough to build it (its actions re-resolve context).
|
|
186
|
+
const listCommand = new BaseGroupHandler(this.assetName).baseListCommand_create(async (options) => {
|
|
165
187
|
await this.files_list(options);
|
|
166
188
|
});
|
|
167
189
|
// Add path argument and override action to handle it properly
|
|
@@ -233,14 +255,14 @@ export class FileMemberHandler {
|
|
|
233
255
|
const success = await files_create(fileIdentifier, options);
|
|
234
256
|
if (success) {
|
|
235
257
|
const resolvedChRISPath = await path_resolveChrisFs(fileIdentifier, options);
|
|
236
|
-
|
|
258
|
+
chiliLog(`File created successfully at: ${resolvedChRISPath}`);
|
|
237
259
|
}
|
|
238
260
|
// If success is false, files_create would have thrown an error which is caught below.
|
|
239
261
|
}
|
|
240
262
|
catch (error) {
|
|
241
263
|
// Log the error from files_create
|
|
242
264
|
const message = error instanceof Error ? error.message : String(error);
|
|
243
|
-
|
|
265
|
+
chiliErrLog(message);
|
|
244
266
|
}
|
|
245
267
|
}
|
|
246
268
|
/**
|
|
@@ -274,7 +296,7 @@ export class FileMemberHandler {
|
|
|
274
296
|
.action(async (options) => {
|
|
275
297
|
await this.file_cat(options);
|
|
276
298
|
});
|
|
277
|
-
|
|
299
|
+
chiliLog("FileMemberHandler commands set up successfully");
|
|
278
300
|
}
|
|
279
301
|
/**
|
|
280
302
|
* Displays the content of the file.
|
|
@@ -284,18 +306,18 @@ export class FileMemberHandler {
|
|
|
284
306
|
async file_cat(options) {
|
|
285
307
|
try {
|
|
286
308
|
const path = this.controller.path_get;
|
|
287
|
-
|
|
309
|
+
chiliLog(`Viewing file at ${path}`);
|
|
288
310
|
const content = await files_viewContent(path);
|
|
289
311
|
if (content !== null) {
|
|
290
|
-
|
|
312
|
+
chiliLog(content);
|
|
291
313
|
}
|
|
292
314
|
else {
|
|
293
|
-
|
|
315
|
+
chiliErrLog("Failed to view file content (empty or error).");
|
|
294
316
|
}
|
|
295
317
|
}
|
|
296
318
|
catch (error) {
|
|
297
319
|
const message = error instanceof Error ? error.message : String(error);
|
|
298
|
-
|
|
320
|
+
chiliErrLog(`Error viewing file: ${message}`);
|
|
299
321
|
}
|
|
300
322
|
}
|
|
301
323
|
}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
import { ChRISinode_create, listParams_fromOptions, BrowserType, } from "@fnndsc/cumin";
|
|
7
|
+
import { table_render } from "../screen/screen.js";
|
|
8
|
+
import { chiliErrLog, chiliLog } from "../screen/output.js";
|
|
7
9
|
/**
|
|
8
10
|
* Lists resources for a given inode path.
|
|
9
11
|
*
|
|
@@ -13,7 +15,7 @@ import { ChRISinode_create, listParams_fromOptions, BrowserType, } from "@fnndsc
|
|
|
13
15
|
async function inodeResources_list(path, options) {
|
|
14
16
|
const chrisInode = await ChRISinode_create(path);
|
|
15
17
|
if (!chrisInode) {
|
|
16
|
-
|
|
18
|
+
chiliErrLog(`Could not find path '${path}' in the CUBE filesystem.`);
|
|
17
19
|
return;
|
|
18
20
|
}
|
|
19
21
|
const params = listParams_fromOptions({
|
|
@@ -33,28 +35,28 @@ async function inodeResources_list(path, options) {
|
|
|
33
35
|
for (const browserType of browserTypes) {
|
|
34
36
|
const browser = chrisInode.browser_get(browserType);
|
|
35
37
|
if (!browser) {
|
|
36
|
-
|
|
38
|
+
chiliErrLog(`WARNING: ${browserType} browser is not available`);
|
|
37
39
|
continue;
|
|
38
40
|
}
|
|
39
41
|
try {
|
|
40
42
|
const resourceGet = browser.resource_get;
|
|
41
43
|
if (!resourceGet) {
|
|
42
|
-
|
|
44
|
+
chiliErrLog(`WARNING: ${browserType} resource is null`);
|
|
43
45
|
continue;
|
|
44
46
|
}
|
|
45
47
|
const resourcesList = await resourceGet.resources_getList(params);
|
|
46
48
|
const resourceFields = await resourceGet.resourceFields_get(resourcesList, fieldOptions[browserType]);
|
|
47
49
|
const results = resourceGet.resources_filterByFields(resourceFields);
|
|
48
50
|
if (results) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
chiliLog(`${browserType} resources:`);
|
|
52
|
+
chiliLog(table_render(results.tableData, results.selectedFields));
|
|
51
53
|
}
|
|
52
54
|
else {
|
|
53
|
-
|
|
55
|
+
chiliErrLog(`${browserType} resources: not found or could not be filtered`);
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
catch (error) {
|
|
57
|
-
|
|
59
|
+
chiliErrLog(`${browserType} resources: not found`);
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
}
|
|
@@ -67,12 +69,12 @@ async function inodeResources_list(path, options) {
|
|
|
67
69
|
*/
|
|
68
70
|
function inodeFields_list(inodeType, dataObj) {
|
|
69
71
|
if (!dataObj) {
|
|
70
|
-
|
|
72
|
+
chiliLog("No " + inodeType + " at this path");
|
|
71
73
|
return false;
|
|
72
74
|
}
|
|
73
75
|
if (dataObj.fields) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
chiliLog(inodeType);
|
|
77
|
+
chiliLog(table_render(dataObj.fields, ["fields"]));
|
|
76
78
|
return true;
|
|
77
79
|
}
|
|
78
80
|
return false;
|
|
@@ -85,7 +87,7 @@ function inodeFields_list(inodeType, dataObj) {
|
|
|
85
87
|
async function inodeResourceFields_list(path = "") {
|
|
86
88
|
const chrisFiles = await ChRISinode_create(path);
|
|
87
89
|
if (!chrisFiles) {
|
|
88
|
-
|
|
90
|
+
chiliErrLog(`Could not create ChRISinode for path: ${path}`);
|
|
89
91
|
return;
|
|
90
92
|
}
|
|
91
93
|
const fileBrowser = chrisFiles.fileBrowser_get;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
import { FileGroupHandler, FileMemberHandler } from "./fileGroupHandler.js";
|
|
8
|
+
import { chiliErrLog } from "../screen/output.js";
|
|
8
9
|
/**
|
|
9
10
|
* Sets up the 'inode' command for interacting with ChRIS filesystem resources.
|
|
10
11
|
*
|
|
@@ -18,7 +19,7 @@ export async function inodeCommand_setup(program) {
|
|
|
18
19
|
const args = command.args.slice(1);
|
|
19
20
|
const subcommand = args[0];
|
|
20
21
|
if (subcommand === "files") {
|
|
21
|
-
const fileGroupHandler =
|
|
22
|
+
const fileGroupHandler = FileGroupHandler.handler_create("files", path);
|
|
22
23
|
const filesProgram = new Command();
|
|
23
24
|
fileGroupHandler.fileGroupCommand_setup(filesProgram);
|
|
24
25
|
await filesProgram.parseAsync(args);
|
|
@@ -30,7 +31,7 @@ export async function inodeCommand_setup(program) {
|
|
|
30
31
|
await fileProgram.parseAsync(args);
|
|
31
32
|
}
|
|
32
33
|
else {
|
|
33
|
-
|
|
34
|
+
chiliErrLog("Usage: chili inode <path> <files|file> [options]");
|
|
34
35
|
command.help();
|
|
35
36
|
}
|
|
36
37
|
});
|
|
@@ -14,8 +14,14 @@ import { TableOptions } from "../screen/screen.js";
|
|
|
14
14
|
export declare class BaseGroupHandler {
|
|
15
15
|
assetName: string;
|
|
16
16
|
displayOptions: TableOptions;
|
|
17
|
-
chrisObject: ChRISPluginGroup | ChRISFeedGroup | ChRISEmbeddedResourceGroup<unknown> | ChRISPACSGroup;
|
|
18
|
-
constructor(assetName: string, chrisObject
|
|
17
|
+
chrisObject: ChRISPluginGroup | ChRISFeedGroup | ChRISEmbeddedResourceGroup<unknown> | ChRISPACSGroup | null;
|
|
18
|
+
constructor(assetName: string, chrisObject?: ChRISPluginGroup | ChRISFeedGroup | ChRISEmbeddedResourceGroup<unknown> | ChRISPACSGroup | null);
|
|
19
|
+
/**
|
|
20
|
+
* The resolved ChRIS context, for use inside actions. Throws if read before
|
|
21
|
+
* the context has been set — a lazy handler must resolve its context before
|
|
22
|
+
* an action dereferences it.
|
|
23
|
+
*/
|
|
24
|
+
private get chrisObjectResolved();
|
|
19
25
|
/**
|
|
20
26
|
* Lists ChRIS resources based on provided CLI options.
|
|
21
27
|
*
|