@fnndsc/chili 3.2.5
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/LICENSE +21 -0
- package/README.md +113 -0
- package/dist/chefs/chefs.d.ts +15 -0
- package/dist/chefs/chefs.js +195 -0
- package/dist/commands/compute/fields.d.ts +6 -0
- package/dist/commands/compute/fields.js +13 -0
- package/dist/commands/compute/list.d.ts +19 -0
- package/dist/commands/compute/list.js +20 -0
- package/dist/commands/connect/login.d.ts +16 -0
- package/dist/commands/connect/login.js +18 -0
- package/dist/commands/connect/logout.d.ts +6 -0
- package/dist/commands/connect/logout.js +16 -0
- package/dist/commands/feed/comments.d.ts +41 -0
- package/dist/commands/feed/comments.js +45 -0
- package/dist/commands/feed/create.d.ts +13 -0
- package/dist/commands/feed/create.js +40 -0
- package/dist/commands/feed/note.d.ts +21 -0
- package/dist/commands/feed/note.js +24 -0
- package/dist/commands/feeds/delete.d.ts +14 -0
- package/dist/commands/feeds/delete.js +34 -0
- package/dist/commands/feeds/fields.d.ts +6 -0
- package/dist/commands/feeds/fields.js +17 -0
- package/dist/commands/feeds/list.d.ts +17 -0
- package/dist/commands/feeds/list.js +38 -0
- package/dist/commands/feeds/share.d.ts +17 -0
- package/dist/commands/feeds/share.js +19 -0
- package/dist/commands/file/view.d.ts +8 -0
- package/dist/commands/file/view.js +25 -0
- package/dist/commands/files/delete.d.ts +16 -0
- package/dist/commands/files/delete.js +36 -0
- package/dist/commands/files/fields.d.ts +7 -0
- package/dist/commands/files/fields.js +18 -0
- package/dist/commands/files/list.d.ts +11 -0
- package/dist/commands/files/list.js +23 -0
- package/dist/commands/fs/cat.d.ts +15 -0
- package/dist/commands/fs/cat.js +26 -0
- package/dist/commands/fs/cp.d.ts +17 -0
- package/dist/commands/fs/cp.js +26 -0
- package/dist/commands/fs/create.d.ts +15 -0
- package/dist/commands/fs/create.js +83 -0
- package/dist/commands/fs/download.d.ts +25 -0
- package/dist/commands/fs/download.js +235 -0
- package/dist/commands/fs/edit.d.ts +16 -0
- package/dist/commands/fs/edit.js +25 -0
- package/dist/commands/fs/ls.d.ts +18 -0
- package/dist/commands/fs/ls.js +142 -0
- package/dist/commands/fs/mkdir.d.ts +8 -0
- package/dist/commands/fs/mkdir.js +21 -0
- package/dist/commands/fs/mv.d.ts +13 -0
- package/dist/commands/fs/mv.js +73 -0
- package/dist/commands/fs/rm.d.ts +24 -0
- package/dist/commands/fs/rm.js +108 -0
- package/dist/commands/fs/touch.d.ts +16 -0
- package/dist/commands/fs/touch.js +62 -0
- package/dist/commands/fs/upload.d.ts +55 -0
- package/dist/commands/fs/upload.js +221 -0
- package/dist/commands/groups/fields.d.ts +6 -0
- package/dist/commands/groups/fields.js +13 -0
- package/dist/commands/groups/list.d.ts +16 -0
- package/dist/commands/groups/list.js +26 -0
- package/dist/commands/man/doc.d.ts +16 -0
- package/dist/commands/man/doc.js +32 -0
- package/dist/commands/man/topics.d.ts +6 -0
- package/dist/commands/man/topics.js +27 -0
- package/dist/commands/pipeline/fields.d.ts +6 -0
- package/dist/commands/pipeline/fields.js +13 -0
- package/dist/commands/pipeline/run.d.ts +18 -0
- package/dist/commands/pipeline/run.js +33 -0
- package/dist/commands/plugin/readme.d.ts +14 -0
- package/dist/commands/plugin/readme.js +49 -0
- package/dist/commands/plugin/run.d.ts +10 -0
- package/dist/commands/plugin/run.js +29 -0
- package/dist/commands/plugin/search.d.ts +7 -0
- package/dist/commands/plugin/search.js +18 -0
- package/dist/commands/plugininstances/fields.d.ts +6 -0
- package/dist/commands/plugininstances/fields.js +13 -0
- package/dist/commands/plugininstances/list.d.ts +16 -0
- package/dist/commands/plugininstances/list.js +26 -0
- package/dist/commands/pluginmetas/fields.d.ts +6 -0
- package/dist/commands/pluginmetas/fields.js +13 -0
- package/dist/commands/pluginmetas/list.d.ts +16 -0
- package/dist/commands/pluginmetas/list.js +26 -0
- package/dist/commands/plugins/add.d.ts +34 -0
- package/dist/commands/plugins/add.js +374 -0
- package/dist/commands/plugins/delete.d.ts +14 -0
- package/dist/commands/plugins/delete.js +34 -0
- package/dist/commands/plugins/fields.d.ts +6 -0
- package/dist/commands/plugins/fields.js +17 -0
- package/dist/commands/plugins/list.d.ts +17 -0
- package/dist/commands/plugins/list.js +40 -0
- package/dist/commands/plugins/overview.d.ts +6 -0
- package/dist/commands/plugins/overview.js +17 -0
- package/dist/commands/store/list.d.ts +23 -0
- package/dist/commands/store/list.js +48 -0
- package/dist/commands/tags/fields.d.ts +6 -0
- package/dist/commands/tags/fields.js +13 -0
- package/dist/commands/tags/list.d.ts +16 -0
- package/dist/commands/tags/list.js +26 -0
- package/dist/commands/workflows/fields.d.ts +6 -0
- package/dist/commands/workflows/fields.js +13 -0
- package/dist/commands/workflows/list.d.ts +16 -0
- package/dist/commands/workflows/list.js +26 -0
- package/dist/config/colorConfig.d.ts +56 -0
- package/dist/config/colorConfig.js +161 -0
- package/dist/connect/connectHandler.d.ts +15 -0
- package/dist/connect/connectHandler.js +48 -0
- package/dist/context/contextCommand.d.ts +13 -0
- package/dist/context/contextCommand.js +193 -0
- package/dist/controllers/baseController.d.ts +43 -0
- package/dist/controllers/baseController.js +67 -0
- package/dist/controllers/feedController.d.ts +35 -0
- package/dist/controllers/feedController.js +53 -0
- package/dist/controllers/fileController.d.ts +56 -0
- package/dist/controllers/fileController.js +93 -0
- package/dist/controllers/pluginContextController.d.ts +24 -0
- package/dist/controllers/pluginContextController.js +49 -0
- package/dist/controllers/pluginController.d.ts +70 -0
- package/dist/controllers/pluginController.js +98 -0
- package/dist/controllers/pluginMetaController.d.ts +41 -0
- package/dist/controllers/pluginMetaController.js +52 -0
- package/dist/feeds/feedHandler.d.ts +64 -0
- package/dist/feeds/feedHandler.js +203 -0
- package/dist/filesystem/fileGroupHandler.d.ts +92 -0
- package/dist/filesystem/fileGroupHandler.js +318 -0
- package/dist/filesystem/filesystemHandler.d.ts +12 -0
- package/dist/filesystem/filesystemHandler.js +135 -0
- package/dist/filesystem/inodeCommand.d.ts +12 -0
- package/dist/filesystem/inodeCommand.js +37 -0
- package/dist/handlers/baseGroupHandler.d.ts +103 -0
- package/dist/handlers/baseGroupHandler.js +342 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +239 -0
- package/dist/lfs/lfs.d.ts +25 -0
- package/dist/lfs/lfs.js +74 -0
- package/dist/man/man.d.ts +15 -0
- package/dist/man/man.js +31 -0
- package/dist/man/renderer.d.ts +26 -0
- package/dist/man/renderer.js +187 -0
- package/dist/models/feed.d.ts +18 -0
- package/dist/models/feed.js +8 -0
- package/dist/models/listing.d.ts +33 -0
- package/dist/models/listing.js +9 -0
- package/dist/models/plugin.d.ts +27 -0
- package/dist/models/plugin.js +1 -0
- package/dist/models/resource.d.ts +39 -0
- package/dist/models/resource.js +9 -0
- package/dist/pacs/pacsQueryHandler.d.ts +55 -0
- package/dist/pacs/pacsQueryHandler.js +196 -0
- package/dist/pacs/pacsQueryPayload.d.ts +19 -0
- package/dist/pacs/pacsQueryPayload.js +44 -0
- package/dist/pacs/pacsResultRender.d.ts +20 -0
- package/dist/pacs/pacsResultRender.js +141 -0
- package/dist/pacs/pacsRetrieveHandler.d.ts +87 -0
- package/dist/pacs/pacsRetrieveHandler.js +272 -0
- package/dist/pacs/pacsServerHandler.d.ts +15 -0
- package/dist/pacs/pacsServerHandler.js +32 -0
- package/dist/path/pathCommand.d.ts +64 -0
- package/dist/path/pathCommand.js +805 -0
- package/dist/path/pathMapper.d.ts +189 -0
- package/dist/path/pathMapper.js +382 -0
- package/dist/plugins/pluginGroupHandler.d.ts +42 -0
- package/dist/plugins/pluginGroupHandler.js +90 -0
- package/dist/plugins/pluginHandler.d.ts +87 -0
- package/dist/plugins/pluginHandler.js +303 -0
- package/dist/plugins/pluginMetaHandler.d.ts +21 -0
- package/dist/plugins/pluginMetaHandler.js +27 -0
- package/dist/screen/screen.d.ts +214 -0
- package/dist/screen/screen.js +478 -0
- package/dist/utils/admin_prompt.d.ts +42 -0
- package/dist/utils/admin_prompt.js +105 -0
- package/dist/utils/cli.d.ts +67 -0
- package/dist/utils/cli.js +112 -0
- package/dist/utils/docker.d.ts +74 -0
- package/dist/utils/docker.js +155 -0
- package/dist/utils/input_format.d.ts +77 -0
- package/dist/utils/input_format.js +135 -0
- package/dist/utils/sort.d.ts +29 -0
- package/dist/utils/sort.js +63 -0
- package/dist/utils/ui.d.ts +7 -0
- package/dist/utils/ui.js +26 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.js +14 -0
- package/dist/views/compute.d.ts +17 -0
- package/dist/views/compute.js +40 -0
- package/dist/views/connect.d.ts +13 -0
- package/dist/views/connect.js +35 -0
- package/dist/views/feed.d.ts +44 -0
- package/dist/views/feed.js +110 -0
- package/dist/views/file.d.ts +25 -0
- package/dist/views/file.js +71 -0
- package/dist/views/fs.d.ts +51 -0
- package/dist/views/fs.js +105 -0
- package/dist/views/ls.d.ts +37 -0
- package/dist/views/ls.js +190 -0
- package/dist/views/plugin.d.ts +28 -0
- package/dist/views/plugin.js +71 -0
- package/dist/views/pluginParameters.d.ts +17 -0
- package/dist/views/pluginParameters.js +79 -0
- package/docs/00_intro.adoc +25 -0
- package/docs/01_setup.adoc +63 -0
- package/docs/02_context.adoc +128 -0
- package/docs/03_searchable.adoc +134 -0
- package/docs/10_everyday_examples.adoc +9 -0
- package/docs/11_upload_data.adoc +146 -0
- package/docs/12_create_a_feed.adoc +9 -0
- package/docs/13_run_a_plugin.adoc +271 -0
- package/docs/20_plugins.adoc +16 -0
- package/docs/21_pluginReadme.adoc +123 -0
- package/docs/30_filesystem.adoc +93 -0
- package/docs/31_fileops.adoc +51 -0
- package/docs/32_file_content.adoc +471 -0
- package/docs/_architecture.adoc +48 -0
- package/docs/_deepContext.adoc +84 -0
- package/docs/_roadmap.adoc +42 -0
- package/docs/_searchable.adoc +187 -0
- package/docs/_state.adoc +68 -0
- package/docs/pacs.adoc +101 -0
- package/docs/pathMapper.md +246 -0
- package/package.json +92 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Admin Credential Prompting
|
|
3
|
+
*
|
|
4
|
+
* Utilities for prompting users for admin credentials when required for plugin
|
|
5
|
+
* registration operations. Supports both interactive prompting and flag-based
|
|
6
|
+
* credential provision.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Interface for admin credentials.
|
|
12
|
+
*/
|
|
13
|
+
export interface AdminCredentials {
|
|
14
|
+
username: string;
|
|
15
|
+
password: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Registers question functions from the active REPL.
|
|
19
|
+
* Called by chell's plugin builtin before invoking plugin_add.
|
|
20
|
+
*
|
|
21
|
+
* @param askFn - Visible-input question function.
|
|
22
|
+
* @param askHiddenFn - Hidden-input (password) question function.
|
|
23
|
+
*/
|
|
24
|
+
export declare function adminPrompt_register(askFn: (prompt: string) => Promise<string>, askHiddenFn: (prompt: string) => Promise<string>): void;
|
|
25
|
+
/**
|
|
26
|
+
* Prompts the user for admin credentials interactively.
|
|
27
|
+
*
|
|
28
|
+
* Uses injected REPL question functions when available so the REPL's
|
|
29
|
+
* readline interface is not duplicated on stdin.
|
|
30
|
+
*
|
|
31
|
+
* @param attempt - Current attempt number (for retry logic).
|
|
32
|
+
* @param maxAttempts - Maximum number of attempts allowed.
|
|
33
|
+
* @returns Promise resolving to admin credentials, or null if user cancels.
|
|
34
|
+
*/
|
|
35
|
+
export declare function adminCredentials_prompt(attempt?: number, maxAttempts?: number): Promise<AdminCredentials | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Validates admin credentials by checking if they are non-empty.
|
|
38
|
+
*
|
|
39
|
+
* @param credentials - Admin credentials to validate.
|
|
40
|
+
* @returns True if credentials are valid, false otherwise.
|
|
41
|
+
*/
|
|
42
|
+
export declare function adminCredentials_validate(credentials: AdminCredentials | null): boolean;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Admin Credential Prompting
|
|
3
|
+
*
|
|
4
|
+
* Utilities for prompting users for admin credentials when required for plugin
|
|
5
|
+
* registration operations. Supports both interactive prompting and flag-based
|
|
6
|
+
* credential provision.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import * as readline from 'readline';
|
|
11
|
+
import { Writable } from 'stream';
|
|
12
|
+
/** Injected by the host (chell) so prompts route through the active readline. */
|
|
13
|
+
let _askFn = null;
|
|
14
|
+
let _askHiddenFn = null;
|
|
15
|
+
/**
|
|
16
|
+
* Registers question functions from the active REPL.
|
|
17
|
+
* Called by chell's plugin builtin before invoking plugin_add.
|
|
18
|
+
*
|
|
19
|
+
* @param askFn - Visible-input question function.
|
|
20
|
+
* @param askHiddenFn - Hidden-input (password) question function.
|
|
21
|
+
*/
|
|
22
|
+
export function adminPrompt_register(askFn, askHiddenFn) {
|
|
23
|
+
_askFn = askFn;
|
|
24
|
+
_askHiddenFn = askHiddenFn;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Prompts the user for admin credentials interactively.
|
|
28
|
+
*
|
|
29
|
+
* Uses injected REPL question functions when available so the REPL's
|
|
30
|
+
* readline interface is not duplicated on stdin.
|
|
31
|
+
*
|
|
32
|
+
* @param attempt - Current attempt number (for retry logic).
|
|
33
|
+
* @param maxAttempts - Maximum number of attempts allowed.
|
|
34
|
+
* @returns Promise resolving to admin credentials, or null if user cancels.
|
|
35
|
+
*/
|
|
36
|
+
export async function adminCredentials_prompt(attempt = 1, maxAttempts = 3) {
|
|
37
|
+
if (attempt === 1) {
|
|
38
|
+
console.log('\nAdmin credentials required to register plugins.');
|
|
39
|
+
console.log('You can provide these via --adminUser and --adminPassword flags.');
|
|
40
|
+
console.log('');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(`\nAuthentication failed. Attempt ${attempt} of ${maxAttempts}.`);
|
|
44
|
+
console.log('');
|
|
45
|
+
}
|
|
46
|
+
const askFn = _askFn ?? ask_fallback;
|
|
47
|
+
const askHiddenFn = _askHiddenFn ?? askHidden_fallback;
|
|
48
|
+
const username = await askFn('Username: ');
|
|
49
|
+
if (!username) {
|
|
50
|
+
console.log('Username cannot be empty.');
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const password = await askHiddenFn('Password: ');
|
|
54
|
+
if (!password) {
|
|
55
|
+
console.log('Password cannot be empty.');
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return { username, password };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Fallback visible-input prompt (used outside the REPL).
|
|
62
|
+
*/
|
|
63
|
+
function ask_fallback(prompt) {
|
|
64
|
+
return new Promise((resolve) => {
|
|
65
|
+
const rl = readline.createInterface({
|
|
66
|
+
input: process.stdin,
|
|
67
|
+
output: process.stdout,
|
|
68
|
+
});
|
|
69
|
+
rl.question(prompt, (answer) => { rl.close(); resolve(answer.trim()); });
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Fallback hidden-input prompt (used outside the REPL).
|
|
74
|
+
*/
|
|
75
|
+
function askHidden_fallback(prompt) {
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
const muted = new Writable({
|
|
78
|
+
write(_chunk, _enc, cb) { cb(); }
|
|
79
|
+
});
|
|
80
|
+
const rl = readline.createInterface({
|
|
81
|
+
input: process.stdin,
|
|
82
|
+
output: muted,
|
|
83
|
+
terminal: true,
|
|
84
|
+
});
|
|
85
|
+
process.stdout.write(prompt);
|
|
86
|
+
rl.question('', (answer) => {
|
|
87
|
+
process.stdout.write('\n');
|
|
88
|
+
rl.close();
|
|
89
|
+
resolve(answer.trim());
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Validates admin credentials by checking if they are non-empty.
|
|
95
|
+
*
|
|
96
|
+
* @param credentials - Admin credentials to validate.
|
|
97
|
+
* @returns True if credentials are valid, false otherwise.
|
|
98
|
+
*/
|
|
99
|
+
export function adminCredentials_validate(credentials) {
|
|
100
|
+
if (!credentials) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return credentials.username.trim().length > 0 &&
|
|
104
|
+
credentials.password.trim().length > 0;
|
|
105
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file CLI option helpers: parsing, param conversion, and ChRIS path resolution.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { ListOptions, Result } from "@fnndsc/cumin";
|
|
7
|
+
/**
|
|
8
|
+
* Common CLI option flags shared across chili commands.
|
|
9
|
+
*/
|
|
10
|
+
export interface CLIoptions {
|
|
11
|
+
page?: string;
|
|
12
|
+
fields?: string;
|
|
13
|
+
search?: string;
|
|
14
|
+
params?: string;
|
|
15
|
+
content?: string;
|
|
16
|
+
fromFile?: string;
|
|
17
|
+
path?: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
all?: boolean;
|
|
20
|
+
user?: string;
|
|
21
|
+
table?: boolean;
|
|
22
|
+
csv?: boolean;
|
|
23
|
+
sort?: string;
|
|
24
|
+
reverse?: boolean;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Converts CLI options into ChRIS list query parameters.
|
|
29
|
+
*
|
|
30
|
+
* @param options - The CLI options.
|
|
31
|
+
* @param keyPairField - Field treated as the search key-pair.
|
|
32
|
+
* @returns ListOptions suitable for a ChRIS list query.
|
|
33
|
+
*/
|
|
34
|
+
export declare function options_toParams(options: CLIoptions, keyPairField?: keyof CLIoptions): ListOptions;
|
|
35
|
+
/**
|
|
36
|
+
* Resolves a ChRIS filesystem path based on various inputs.
|
|
37
|
+
*
|
|
38
|
+
* This function builds the logical path from inputs, then converts it to
|
|
39
|
+
* the physical path where data actually resides (resolving any links).
|
|
40
|
+
*
|
|
41
|
+
* @param fileIdentifier - The primary argument, which can be a filename or a path fragment (relative or absolute).
|
|
42
|
+
* @param options - CLI options including optional `path` (base directory) and `name` (explicit filename).
|
|
43
|
+
* @returns The fully resolved absolute ChRIS physical path.
|
|
44
|
+
*/
|
|
45
|
+
export declare function path_resolveChrisFs(fileIdentifier: string | undefined, options: {
|
|
46
|
+
path?: string;
|
|
47
|
+
name?: string;
|
|
48
|
+
}): Promise<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Resolves a logical path to its physical path by following links.
|
|
51
|
+
*
|
|
52
|
+
* This function delegates to the PathMapper singleton, which uses
|
|
53
|
+
* hierarchical caching to optimize repeated resolutions with common prefixes.
|
|
54
|
+
*
|
|
55
|
+
* Example:
|
|
56
|
+
* Logical: /home/user/public/data
|
|
57
|
+
* Where: public -> /PUBLIC
|
|
58
|
+
* Physical: /PUBLIC/data
|
|
59
|
+
*
|
|
60
|
+
* @param logicalPath - The logical (apparent) path the user sees/navigates
|
|
61
|
+
* @returns A Result containing the physical path, or Err if path is invalid
|
|
62
|
+
*/
|
|
63
|
+
export declare function logical_toPhysical(logicalPath: string): Promise<Result<string>>;
|
|
64
|
+
/**
|
|
65
|
+
* Clears the path mapping cache. Useful when links are created/deleted.
|
|
66
|
+
*/
|
|
67
|
+
export declare function linkCache_clear(): void;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file CLI option helpers: parsing, param conversion, and ChRIS path resolution.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { chrisContext, Context, errorStack } from "@fnndsc/cumin";
|
|
7
|
+
import { keyPairParams_apply } from "@fnndsc/cumin";
|
|
8
|
+
import path from "path"; // Node.js path module for joining paths
|
|
9
|
+
import { pathMapper_get } from "../path/pathMapper.js";
|
|
10
|
+
/**
|
|
11
|
+
* Converts CLI options into ChRIS list query parameters.
|
|
12
|
+
*
|
|
13
|
+
* @param options - The CLI options.
|
|
14
|
+
* @param keyPairField - Field treated as the search key-pair.
|
|
15
|
+
* @returns ListOptions suitable for a ChRIS list query.
|
|
16
|
+
*/
|
|
17
|
+
export function options_toParams(options, keyPairField = "search") {
|
|
18
|
+
const baseParams = {
|
|
19
|
+
limit: options.limit ? Number(options.limit) : (options.page ? parseInt(options.page, 10) : 20),
|
|
20
|
+
offset: options.offset ? Number(options.offset) : 0,
|
|
21
|
+
fields: options.fields,
|
|
22
|
+
};
|
|
23
|
+
const keyPairValue = options[keyPairField];
|
|
24
|
+
if (typeof keyPairValue === "string") {
|
|
25
|
+
return keyPairParams_apply(baseParams, keyPairValue);
|
|
26
|
+
}
|
|
27
|
+
return baseParams;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolves a ChRIS filesystem path based on various inputs.
|
|
31
|
+
*
|
|
32
|
+
* This function builds the logical path from inputs, then converts it to
|
|
33
|
+
* the physical path where data actually resides (resolving any links).
|
|
34
|
+
*
|
|
35
|
+
* @param fileIdentifier - The primary argument, which can be a filename or a path fragment (relative or absolute).
|
|
36
|
+
* @param options - CLI options including optional `path` (base directory) and `name` (explicit filename).
|
|
37
|
+
* @returns The fully resolved absolute ChRIS physical path.
|
|
38
|
+
*/
|
|
39
|
+
export async function path_resolveChrisFs(fileIdentifier, options) {
|
|
40
|
+
// 1. Build the logical path first
|
|
41
|
+
let logicalPath;
|
|
42
|
+
if (fileIdentifier && fileIdentifier.startsWith('/')) {
|
|
43
|
+
// Absolute path provided
|
|
44
|
+
logicalPath = fileIdentifier.replace(/\/\//g, '/');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Relative path - determine base directory
|
|
48
|
+
let baseDir;
|
|
49
|
+
if (options.path) {
|
|
50
|
+
baseDir = options.path;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const currentContext = await chrisContext.current_get(Context.ChRISfolder);
|
|
54
|
+
baseDir = currentContext || "/";
|
|
55
|
+
}
|
|
56
|
+
if (!baseDir.startsWith('/')) {
|
|
57
|
+
baseDir = `/${baseDir}`;
|
|
58
|
+
}
|
|
59
|
+
// Determine the path fragment to join
|
|
60
|
+
let pathFragment;
|
|
61
|
+
if (options.name) {
|
|
62
|
+
pathFragment = options.name;
|
|
63
|
+
}
|
|
64
|
+
else if (fileIdentifier) {
|
|
65
|
+
pathFragment = fileIdentifier;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// No fileIdentifier or name - use current directory as logical path
|
|
69
|
+
logicalPath = baseDir.replace(/\/\//g, '/');
|
|
70
|
+
// Convert to physical and return
|
|
71
|
+
const physicalResult = await logical_toPhysical(logicalPath);
|
|
72
|
+
if (!physicalResult.ok) {
|
|
73
|
+
errorStack.stack_push('error', 'Failed to resolve current directory to physical location');
|
|
74
|
+
return logicalPath; // Fallback to logical
|
|
75
|
+
}
|
|
76
|
+
return physicalResult.value;
|
|
77
|
+
}
|
|
78
|
+
logicalPath = path.posix.join(baseDir, pathFragment).replace(/\/\/\//g, '/');
|
|
79
|
+
}
|
|
80
|
+
// 2. Convert logical path to physical path
|
|
81
|
+
const physicalResult = await logical_toPhysical(logicalPath);
|
|
82
|
+
if (!physicalResult.ok) {
|
|
83
|
+
errorStack.stack_push('error', `Failed to resolve logical path '${logicalPath}' to physical location`);
|
|
84
|
+
return logicalPath; // Fallback to using logical path directly
|
|
85
|
+
}
|
|
86
|
+
return physicalResult.value;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolves a logical path to its physical path by following links.
|
|
90
|
+
*
|
|
91
|
+
* This function delegates to the PathMapper singleton, which uses
|
|
92
|
+
* hierarchical caching to optimize repeated resolutions with common prefixes.
|
|
93
|
+
*
|
|
94
|
+
* Example:
|
|
95
|
+
* Logical: /home/user/public/data
|
|
96
|
+
* Where: public -> /PUBLIC
|
|
97
|
+
* Physical: /PUBLIC/data
|
|
98
|
+
*
|
|
99
|
+
* @param logicalPath - The logical (apparent) path the user sees/navigates
|
|
100
|
+
* @returns A Result containing the physical path, or Err if path is invalid
|
|
101
|
+
*/
|
|
102
|
+
export async function logical_toPhysical(logicalPath) {
|
|
103
|
+
const mapper = pathMapper_get();
|
|
104
|
+
return mapper.logical_toPhysical(logicalPath);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Clears the path mapping cache. Useful when links are created/deleted.
|
|
108
|
+
*/
|
|
109
|
+
export function linkCache_clear() {
|
|
110
|
+
const mapper = pathMapper_get();
|
|
111
|
+
mapper.cache_clear();
|
|
112
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Promisified version of child_process.exec.
|
|
3
|
+
* @param command - The command string to execute.
|
|
4
|
+
* @returns A Promise that resolves with { stdout, stderr }.
|
|
5
|
+
*/
|
|
6
|
+
export declare function childProcess_exec(command: string): Promise<{
|
|
7
|
+
stdout: string;
|
|
8
|
+
stderr: string;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Executes a shell command and returns its stdout.
|
|
12
|
+
* @param command - The command to execute.
|
|
13
|
+
* @returns The stdout of the command, or null if an error occurred.
|
|
14
|
+
*/
|
|
15
|
+
export declare function shellCommand_run(command: string): Promise<string | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Executes a shell command and returns detailed result including stderr.
|
|
18
|
+
*
|
|
19
|
+
* @param command - The command to execute.
|
|
20
|
+
* @returns Object with stdout, stderr, and success status.
|
|
21
|
+
*/
|
|
22
|
+
export declare function shellCommand_runWithDetails(command: string): Promise<{
|
|
23
|
+
stdout: string;
|
|
24
|
+
stderr: string;
|
|
25
|
+
success: boolean;
|
|
26
|
+
error?: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Checks if Docker is installed and running.
|
|
30
|
+
* @returns True if Docker is available, false otherwise.
|
|
31
|
+
*/
|
|
32
|
+
export declare function docker_checkAvailability(): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Checks if a Docker image exists locally.
|
|
35
|
+
*
|
|
36
|
+
* @param image - The Docker image name/tag to check (e.g., 'fnndsc/pl-dircopy:2.1.1').
|
|
37
|
+
* @returns Promise resolving to true if image exists locally, false otherwise.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const exists = await docker_imageExistsLocally('fnndsc/pl-dircopy:2.1.1');
|
|
42
|
+
* if (!exists) {
|
|
43
|
+
* await docker_pullImage('fnndsc/pl-dircopy:2.1.1');
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function docker_imageExistsLocally(image: string): Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Pulls a Docker image from a registry.
|
|
50
|
+
*
|
|
51
|
+
* Checks if image exists locally first. If it exists, skips pull.
|
|
52
|
+
* Output is suppressed for CLI use (use --quiet flag).
|
|
53
|
+
*
|
|
54
|
+
* @param image - The Docker image name/tag to pull.
|
|
55
|
+
* @param quiet - Whether to suppress verbose output (default: true for CLI).
|
|
56
|
+
* @returns Promise resolving to true if pull succeeded or image already exists, false otherwise.
|
|
57
|
+
*/
|
|
58
|
+
export declare function docker_pullImage(image: string, quiet?: boolean): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Gets the CMD directive from a Docker image.
|
|
61
|
+
*
|
|
62
|
+
* Inspects the Docker image configuration to extract the default command.
|
|
63
|
+
* This is useful for running plugins that don't have chris_plugin_info.
|
|
64
|
+
*
|
|
65
|
+
* @param image - The Docker image name/tag.
|
|
66
|
+
* @returns Promise resolving to array of command parts, or empty array if not found.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const cmd = await docker_getImageCmd('fnndsc/pl-civet:2.1.1.3');
|
|
71
|
+
* // Returns: ['civet.py'] or similar
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function docker_getImageCmd(image: string): Promise<string[]>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Docker utility functions.
|
|
3
|
+
*
|
|
4
|
+
* This module provides helper functions for interacting with the Docker CLI,
|
|
5
|
+
* such as checking availability and running commands.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { exec } from "child_process";
|
|
10
|
+
/**
|
|
11
|
+
* Promisified version of child_process.exec.
|
|
12
|
+
* @param command - The command string to execute.
|
|
13
|
+
* @returns A Promise that resolves with { stdout, stderr }.
|
|
14
|
+
*/
|
|
15
|
+
export async function childProcess_exec(command) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
exec(command, (error, stdout, stderr) => {
|
|
18
|
+
if (error) {
|
|
19
|
+
reject(error);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
resolve({ stdout, stderr });
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Executes a shell command and returns its stdout.
|
|
29
|
+
* @param command - The command to execute.
|
|
30
|
+
* @returns The stdout of the command, or null if an error occurred.
|
|
31
|
+
*/
|
|
32
|
+
export async function shellCommand_run(command) {
|
|
33
|
+
try {
|
|
34
|
+
const { stdout, stderr } = await childProcess_exec(command);
|
|
35
|
+
if (stderr) {
|
|
36
|
+
// console.warn(`Command stderr: ${stderr.trim()}`); // Log stderr as warning, not necessarily an error
|
|
37
|
+
}
|
|
38
|
+
return stdout.trim();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
// console.error(`Command failed: ${command}`);
|
|
42
|
+
// console.error(`Error: ${error.message}`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Executes a shell command and returns detailed result including stderr.
|
|
48
|
+
*
|
|
49
|
+
* @param command - The command to execute.
|
|
50
|
+
* @returns Object with stdout, stderr, and success status.
|
|
51
|
+
*/
|
|
52
|
+
export async function shellCommand_runWithDetails(command) {
|
|
53
|
+
try {
|
|
54
|
+
const { stdout, stderr } = await childProcess_exec(command);
|
|
55
|
+
return {
|
|
56
|
+
stdout: stdout.trim(),
|
|
57
|
+
stderr: stderr.trim(),
|
|
58
|
+
success: true,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
63
|
+
return {
|
|
64
|
+
stdout: '',
|
|
65
|
+
stderr: '',
|
|
66
|
+
success: false,
|
|
67
|
+
error: errorMessage,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Checks if Docker is installed and running.
|
|
73
|
+
* @returns True if Docker is available, false otherwise.
|
|
74
|
+
*/
|
|
75
|
+
export async function docker_checkAvailability() {
|
|
76
|
+
const result = await shellCommand_run("docker info > /dev/null 2>&1 && echo OK");
|
|
77
|
+
if (result === "OK") {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
console.error("Error: Docker is not installed or not running.");
|
|
81
|
+
console.error("Please ensure Docker is properly set up on your system to add plugins.");
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Checks if a Docker image exists locally.
|
|
86
|
+
*
|
|
87
|
+
* @param image - The Docker image name/tag to check (e.g., 'fnndsc/pl-dircopy:2.1.1').
|
|
88
|
+
* @returns Promise resolving to true if image exists locally, false otherwise.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const exists = await docker_imageExistsLocally('fnndsc/pl-dircopy:2.1.1');
|
|
93
|
+
* if (!exists) {
|
|
94
|
+
* await docker_pullImage('fnndsc/pl-dircopy:2.1.1');
|
|
95
|
+
* }
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export async function docker_imageExistsLocally(image) {
|
|
99
|
+
const result = await shellCommand_run(`docker images -q ${image} 2>/dev/null`);
|
|
100
|
+
return result !== null && result.trim().length > 0;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Pulls a Docker image from a registry.
|
|
104
|
+
*
|
|
105
|
+
* Checks if image exists locally first. If it exists, skips pull.
|
|
106
|
+
* Output is suppressed for CLI use (use --quiet flag).
|
|
107
|
+
*
|
|
108
|
+
* @param image - The Docker image name/tag to pull.
|
|
109
|
+
* @param quiet - Whether to suppress verbose output (default: true for CLI).
|
|
110
|
+
* @returns Promise resolving to true if pull succeeded or image already exists, false otherwise.
|
|
111
|
+
*/
|
|
112
|
+
export async function docker_pullImage(image, quiet = true) {
|
|
113
|
+
const existsLocally = await docker_imageExistsLocally(image);
|
|
114
|
+
if (existsLocally) {
|
|
115
|
+
console.log(`Docker image ${image} already exists locally.`);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
console.log(`Pulling Docker image: ${image}...`);
|
|
119
|
+
const quietFlag = quiet ? '--quiet' : '';
|
|
120
|
+
const result = await shellCommand_run(`docker pull ${quietFlag} ${image}`);
|
|
121
|
+
if (result !== null) {
|
|
122
|
+
console.log(`Successfully pulled ${image}`);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
console.error(`Failed to pull Docker image: ${image}`);
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Gets the CMD directive from a Docker image.
|
|
130
|
+
*
|
|
131
|
+
* Inspects the Docker image configuration to extract the default command.
|
|
132
|
+
* This is useful for running plugins that don't have chris_plugin_info.
|
|
133
|
+
*
|
|
134
|
+
* @param image - The Docker image name/tag.
|
|
135
|
+
* @returns Promise resolving to array of command parts, or empty array if not found.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const cmd = await docker_getImageCmd('fnndsc/pl-civet:2.1.1.3');
|
|
140
|
+
* // Returns: ['civet.py'] or similar
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export async function docker_getImageCmd(image) {
|
|
144
|
+
const result = await shellCommand_run(`docker inspect --format='{{json .Config.Cmd}}' ${image} 2>/dev/null`);
|
|
145
|
+
if (!result || result.trim() === '' || result === 'null') {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const cmd = JSON.parse(result);
|
|
150
|
+
return Array.isArray(cmd) ? cmd : [];
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Input Format Detection
|
|
3
|
+
*
|
|
4
|
+
* Utilities for detecting the format of plugin input strings (name, Docker image, or store URL).
|
|
5
|
+
* Used by plugin_add to determine the appropriate registration strategy.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Recognized input formats for plugin add (e.g. docker image, source URL).
|
|
11
|
+
*/
|
|
12
|
+
export declare enum PluginInputFormat {
|
|
13
|
+
PLUGIN_NAME = "plugin_name",
|
|
14
|
+
DOCKER_IMAGE = "docker_image",
|
|
15
|
+
STORE_URL = "store_url"
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Interface describing the detected input format.
|
|
19
|
+
*/
|
|
20
|
+
export interface DetectedFormat {
|
|
21
|
+
format: PluginInputFormat;
|
|
22
|
+
value: string;
|
|
23
|
+
pluginName?: string;
|
|
24
|
+
version?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Detects the format of a plugin input string.
|
|
28
|
+
*
|
|
29
|
+
* Determines whether the input is:
|
|
30
|
+
* - A store URL (starts with http:// or https://)
|
|
31
|
+
* - A Docker image (contains / or :)
|
|
32
|
+
* - A plugin name (everything else)
|
|
33
|
+
*
|
|
34
|
+
* @param input - The plugin input string to analyze.
|
|
35
|
+
* @returns DetectedFormat object describing the input type.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* input_detectFormat('pl-dircopy')
|
|
40
|
+
* // { format: 'plugin_name', value: 'pl-dircopy' }
|
|
41
|
+
*
|
|
42
|
+
* input_detectFormat('fnndsc/pl-dircopy:2.1.1')
|
|
43
|
+
* // { format: 'docker_image', value: 'fnndsc/pl-dircopy:2.1.1', pluginName: 'pl-dircopy', version: '2.1.1' }
|
|
44
|
+
*
|
|
45
|
+
* input_detectFormat('https://cube.chrisproject.org/api/v1/plugins/96/')
|
|
46
|
+
* // { format: 'store_url', value: 'https://...' }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function input_detectFormat(input: string): DetectedFormat;
|
|
50
|
+
/**
|
|
51
|
+
* Extracts a plugin name and version from a Docker image string.
|
|
52
|
+
*
|
|
53
|
+
* Examples:
|
|
54
|
+
* 'fnndsc/pl-dircopy:2.1.1' -> { name: 'pl-dircopy', version: '2.1.1' }
|
|
55
|
+
* 'fnndsc/pl-dircopy' -> { name: 'pl-dircopy', version: undefined }
|
|
56
|
+
* 'pl-dircopy:latest' -> { name: 'pl-dircopy', version: 'latest' }
|
|
57
|
+
*
|
|
58
|
+
* @param dockerImage - Docker image string.
|
|
59
|
+
* @returns Object containing extracted plugin name and optional version.
|
|
60
|
+
*/
|
|
61
|
+
export declare function pluginNameAndVersion_extractFromImage(dockerImage: string): {
|
|
62
|
+
name: string;
|
|
63
|
+
version?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Backward-compatible helper to extract only the plugin name from a Docker image.
|
|
67
|
+
*
|
|
68
|
+
* @param dockerImage - Docker image string.
|
|
69
|
+
* @returns The extracted plugin name.
|
|
70
|
+
*/
|
|
71
|
+
export declare function pluginName_extractFromImage(dockerImage: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* Prompts the user for confirmation. Throws if declined or if prompt cannot be shown (non-TTY) without force.
|
|
74
|
+
*
|
|
75
|
+
* @param message - The confirmation message to display.
|
|
76
|
+
*/
|
|
77
|
+
export declare function prompt_confirmOrThrow(message: string): Promise<void>;
|