@fnndsc/brasa 0.56.4 → 0.57.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/buildinfo.json +1 -1
- package/dist/builtins/argumentTokens.d.ts +13 -0
- package/dist/builtins/argumentTokens.js +15 -3
- package/dist/builtins/argumentTokens.js.map +1 -1
- package/dist/builtins/fs/url.d.ts +27 -2
- package/dist/builtins/fs/url.js +60 -10
- package/dist/builtins/fs/url.js.map +1 -1
- package/dist/builtins/help.d.ts +6 -10
- package/dist/builtins/help.js +34 -87
- package/dist/builtins/help.js.map +1 -1
- package/dist/builtins/pluginExecute.d.ts +21 -3
- package/dist/builtins/pluginExecute.js +69 -33
- package/dist/builtins/pluginExecute.js.map +1 -1
- package/dist/builtins/res/pipeline.d.ts +231 -2
- package/dist/builtins/res/pipeline.js +225 -107
- package/dist/builtins/res/pipeline.js.map +1 -1
- package/dist/builtins/res/plugin.d.ts +343 -3
- package/dist/builtins/res/plugin.js +221 -67
- package/dist/builtins/res/plugin.js.map +1 -1
- package/dist/builtins/res/plugin.sync.js +5 -3
- package/dist/builtins/res/plugin.sync.js.map +1 -1
- package/dist/chris/binDeclarations.d.ts +312 -0
- package/dist/chris/binDeclarations.js +572 -0
- package/dist/chris/binDeclarations.js.map +1 -0
- package/dist/chris/chrisCommands.d.ts +1 -0
- package/dist/chris/chrisCommands.js +5 -30
- package/dist/chris/chrisCommands.js.map +1 -1
- package/dist/chris/commandFallback.d.ts +30 -3
- package/dist/chris/commandFallback.js +163 -94
- package/dist/chris/commandFallback.js.map +1 -1
- package/dist/chris/completion.d.ts +37 -0
- package/dist/chris/completion.js +41 -121
- package/dist/chris/completion.js.map +1 -1
- package/dist/chris/kinds.d.ts +11 -0
- package/dist/chris/kinds.js +32 -1
- package/dist/chris/kinds.js.map +1 -1
- package/dist/core/argumentKinds.d.ts +18 -0
- package/dist/core/argumentKinds.js +33 -0
- package/dist/core/argumentKinds.js.map +1 -1
- package/dist/core/backend.d.ts +12 -5
- package/dist/core/backend.js.map +1 -1
- package/dist/core/commandDeclaration.d.ts +40 -0
- package/dist/core/commandDeclaration.js.map +1 -1
- package/dist/core/commandOrder.js +3 -3
- package/dist/core/commandOrder.js.map +1 -1
- package/dist/core/commandParse.d.ts +14 -0
- package/dist/core/commandParse.js +39 -5
- package/dist/core/commandParse.js.map +1 -1
- package/dist/core/commandRegistry.d.ts +22 -36
- package/dist/core/commandRegistry.js +19 -10
- package/dist/core/commandRegistry.js.map +1 -1
- package/dist/core/commandSchema.js +4 -0
- package/dist/core/commandSchema.js.map +1 -1
- package/dist/core/coreCommands.d.ts +1 -0
- package/dist/core/coreCommands.js +6 -19
- package/dist/core/coreCommands.js.map +1 -1
- package/dist/core/dispatch.js +12 -41
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/preprocess.d.ts +0 -15
- package/dist/core/preprocess.js +0 -17
- package/dist/core/preprocess.js.map +1 -1
- package/dist/core/shellWords.d.ts +34 -0
- package/dist/core/shellWords.js +60 -0
- package/dist/core/shellWords.js.map +1 -0
- package/dist/core.d.ts +5 -0
- package/dist/core.js +4 -0
- package/dist/core.js.map +1 -1
- package/dist/lib/completer/declared.js +22 -6
- package/dist/lib/completer/declared.js.map +1 -1
- package/dist/lib/completer/index.js +15 -53
- package/dist/lib/completer/index.js.map +1 -1
- package/dist/notes.json +1 -1
- package/package.json +1 -1
- package/dist/builtins/res/pipeline.args.d.ts +0 -35
- package/dist/builtins/res/pipeline.args.js +0 -94
- package/dist/builtins/res/pipeline.args.js.map +0 -1
- package/dist/chris/help.d.ts +0 -18
- package/dist/chris/help.js +0 -229
- package/dist/chris/help.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { chrisfetchCommand, pingCommand } from '../builtins/games/chrislab.js';
|
|
2
|
-
import {
|
|
2
|
+
import { pluginCommand } from '../builtins/res/plugin.js';
|
|
3
|
+
import { pipelineCommand } from '../builtins/res/pipeline.js';
|
|
3
4
|
import { chmodCommand, getfaclCommand, setfaclCommand } from '../builtins/fs/acl.js';
|
|
4
5
|
import { getfattrCommand, setfattrCommand } from '../builtins/fs/xattr.js';
|
|
5
6
|
import { pacsCommand } from '../builtins/net/pacs.js';
|
|
@@ -16,7 +17,6 @@ import { contextCommand } from '../builtins/sys/context.js';
|
|
|
16
17
|
import { physicalmodeCommand } from '../builtins/sys/physicalmode.js';
|
|
17
18
|
import { idCommand, whereamiCommand, whoamiCommand } from '../builtins/sys/whoami.js';
|
|
18
19
|
import { procCommand } from '../builtins/proc.js';
|
|
19
|
-
import { envelopeHandler_wrap } from '../core/sink.js';
|
|
20
20
|
import { fileCommand, md5sumCommand, sha256sumCommand, stringsCommand, xxdCommand } from '../builtins/games/bytes.js';
|
|
21
21
|
import { duCommand } from '../builtins/fs/du.js';
|
|
22
22
|
import { editCommand } from '../builtins/fs/edit.js';
|
|
@@ -27,7 +27,6 @@ import { recordCommand } from '../builtins/res/record.js';
|
|
|
27
27
|
import { gatherCommand } from '../builtins/res/gather.js';
|
|
28
28
|
import { userCommand } from '../builtins/res/user.js';
|
|
29
29
|
import { motdCommand } from '../builtins/sys/motd.js';
|
|
30
|
-
import { chrisHelp } from './help.js';
|
|
31
30
|
import { whatifCommand } from './commandFallback.js';
|
|
32
31
|
import { berthCommand } from '../builtins/berth/berth.js';
|
|
33
32
|
import { downloadCommand } from '../builtins/fs/download.js';
|
|
@@ -41,29 +40,6 @@ import { workflowCommand } from '../builtins/res/workflow.js';
|
|
|
41
40
|
import { dirsCommand, filesCommand, linksCommand } from '../builtins/res/files.js';
|
|
42
41
|
import { parametersofpluginCommand } from '../builtins/parametersofplugin.js';
|
|
43
42
|
import { storeCommand } from '../builtins/store.js';
|
|
44
|
-
const envelope = {
|
|
45
|
-
plugin: builtin_plugin,
|
|
46
|
-
plugins: builtin_plugin,
|
|
47
|
-
pipeline: builtin_pipeline,
|
|
48
|
-
pipelines: builtin_pipeline,
|
|
49
|
-
};
|
|
50
|
-
const plain = {
|
|
51
|
-
pipeline: envelopeHandler_wrap(builtin_pipeline),
|
|
52
|
-
pipelines: envelopeHandler_wrap(builtin_pipeline),
|
|
53
|
-
plugin: envelopeHandler_wrap(builtin_plugin),
|
|
54
|
-
plugins: envelopeHandler_wrap(builtin_plugin),
|
|
55
|
-
};
|
|
56
|
-
/** The ChRIS backend commands: their handlers. Their help is registered from `builtins/help.ts`, which holds it. */
|
|
57
|
-
/**
|
|
58
|
-
* What the ChRIS commands hold of the session: a read holds nothing and
|
|
59
|
-
* runs beside anything. A command not named holds the whole session; a
|
|
60
|
-
* declared command says in its declaration (`gather` holds the cohort).
|
|
61
|
-
*/
|
|
62
|
-
const holds = {
|
|
63
|
-
...Object.fromEntries([
|
|
64
|
-
'pipelines', 'plugins',
|
|
65
|
-
].map((name) => [name, []])),
|
|
66
|
-
};
|
|
67
43
|
/** The ChRIS commands declared in one record each: grammar, kinds, handler, holds and help together. */
|
|
68
44
|
const declarations = [
|
|
69
45
|
downloadCommand, berthCommand,
|
|
@@ -80,12 +56,11 @@ const declarations = [
|
|
|
80
56
|
xxdCommand, stringsCommand, sha256sumCommand, md5sumCommand, motdCommand, recordCommand,
|
|
81
57
|
// Files.
|
|
82
58
|
editCommand, configCommand, uploadCommand, fileCommand,
|
|
59
|
+
// Resources.
|
|
60
|
+
pluginCommand, pipelineCommand,
|
|
83
61
|
];
|
|
62
|
+
/** The ChRIS backend's commands, every one declared in one record. */
|
|
84
63
|
export const chrisCommands = {
|
|
85
|
-
envelope,
|
|
86
|
-
plain,
|
|
87
|
-
help: chrisHelp,
|
|
88
|
-
holds,
|
|
89
64
|
declarations,
|
|
90
65
|
};
|
|
91
66
|
//# sourceMappingURL=chrisCommands.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chrisCommands.js","sourceRoot":"","sources":["../../src/chris/chrisCommands.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"chrisCommands.js","sourceRoot":"","sources":["../../src/chris/chrisCommands.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
import type { CommandEnvelope } from '@fnndsc/menu';
|
|
2
2
|
import type { BackendFallback } from '../core/backend.js';
|
|
3
3
|
import type { ExpressionDeclaration } from '../core/commandDeclaration.js';
|
|
4
|
+
import { type PipelineLine } from './binDeclarations.js';
|
|
5
|
+
/** The built-in names the ChRIS session answers, for `help variables`. */
|
|
6
|
+
export declare const CHRIS_BUILTIN_LINES: ReadonlyArray<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Answers a pipeline line already read: the look it asks for, or its runs.
|
|
9
|
+
* --diagram (with --withargs, or --signalflow) → the diagram
|
|
10
|
+
* --signalflow → SignalFlow YAML
|
|
11
|
+
* --help / -h → the pipeline's page
|
|
12
|
+
* --nodes / --parameters → pipeline info
|
|
13
|
+
* --manifest → pipeline manifest
|
|
14
|
+
* --source / --readme → pipeline source
|
|
15
|
+
* otherwise → a run
|
|
16
|
+
*
|
|
17
|
+
* @param name - The pipeline's `/bin` name.
|
|
18
|
+
* @param line - The line, read against its declaration.
|
|
19
|
+
* @param dry - Resolve a run and print it, creating and running nothing.
|
|
20
|
+
* @returns The answer's envelope.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* await pipelineParsed_run('PHI_detection_id12', line);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function pipelineParsed_run(name: string, line: PipelineLine, dry?: boolean): Promise<CommandEnvelope>;
|
|
4
28
|
/**
|
|
5
29
|
* `whatif <plugin or Pipeline line>`: resolves the line as a run would, to
|
|
6
30
|
* the version, the operands, the stage, the node and the parameters, prints
|
|
7
31
|
* that, and stops before anything is created or run. A prefix, as `time`
|
|
8
|
-
* and `env` are, since every flag after a `/bin` name is the plugin's
|
|
32
|
+
* and `env` are, since every flag after a `/bin` name is the plugin's: the
|
|
33
|
+
* line after it is parsed against that plugin's or pipeline's declaration,
|
|
34
|
+
* and refused as the real line would be.
|
|
9
35
|
*
|
|
10
36
|
* @param args - The line: the `/bin` name and its words.
|
|
11
37
|
* @returns An ok envelope when the real line would be accepted; an error after the refusal the real line would give.
|
|
@@ -13,8 +39,9 @@ import type { ExpressionDeclaration } from '../core/commandDeclaration.js';
|
|
|
13
39
|
export declare function builtin_whatif(args: string[]): Promise<CommandEnvelope>;
|
|
14
40
|
/**
|
|
15
41
|
* `whatif <plugin or Pipeline line>`: the declaration. Its words are a whole
|
|
16
|
-
* line of another command, whose
|
|
17
|
-
* them
|
|
42
|
+
* line of another command, whose grammar is that command's (the declaration
|
|
43
|
+
* CUBE's parameters make), so it hands them on as they came, as `time` and
|
|
44
|
+
* `env` would.
|
|
18
45
|
*
|
|
19
46
|
* @example
|
|
20
47
|
* ```ts
|
|
@@ -3,19 +3,20 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A plugin named with its version runs as that plugin. A word naming a
|
|
5
5
|
* plugin or a pipeline in `/bin` runs it (a captured line runs only a
|
|
6
|
-
* pipeline: a plugin's run prints live).
|
|
7
|
-
*
|
|
6
|
+
* pipeline: a plugin's run prints live). Its line is parsed first against
|
|
7
|
+
* the declaration made from CUBE's parameters (`binDeclarations.ts`), and a
|
|
8
|
+
* bad line is refused before anything runs. Anything else goes to chili,
|
|
9
|
+
* when chili has the command, with a notice ahead of its output.
|
|
8
10
|
*
|
|
9
11
|
* @module
|
|
10
12
|
*/
|
|
11
13
|
import chalk from 'chalk';
|
|
12
|
-
import { CHRIS_BUILTIN_LINES } from './help.js';
|
|
13
14
|
import { variablesPage_render } from '../builtins/variablesPage.js';
|
|
14
15
|
import { envelope_deliver, sink_get } from '../core/sink.js';
|
|
15
16
|
import { exitCode_read, exitCode_set, handler_runDirect } from '../core/handlerRun.js';
|
|
16
17
|
import { runs_awaitSettled, settlement_render } from '../builtins/res/runWait.js';
|
|
17
18
|
import { binExecutableMatches_get, binPluginHighest_find } from './binExecutables.js';
|
|
18
|
-
import {
|
|
19
|
+
import { pipelineDiagramCommand_handle, pipelineInfo_handle, pipelineManifestCommand_handle, pipelineRun_execute, pipelineSource_handle, } from '../builtins/res/pipeline.js';
|
|
19
20
|
import { builtin_executePlugin } from '../builtins/pluginExecute.js';
|
|
20
21
|
import { pluginExecutable_handle } from '../builtins/executable.js';
|
|
21
22
|
import { pipelineExecutableHelp_render, pluginExecutableHelp_render } from '../builtins/help.js';
|
|
@@ -28,6 +29,14 @@ import { newFeed_cacheAdd } from '../builtins/feedCreation.js';
|
|
|
28
29
|
import { OperandRefusal, operands_read, stage_lines, stage_make, stageMade_lines, stageWriter_default, stageWriter_none } from '../builtins/operands.js';
|
|
29
30
|
import { echoNode_render } from '../builtins/runEcho.js';
|
|
30
31
|
import { operandRuns_split } from '../builtins/operandRuns.js';
|
|
32
|
+
import { shellWords_values } from '../lib/parser.js';
|
|
33
|
+
import { binDeclaration_get, binEntry_resolve, pipelineDeclaration_get, pipelineWords_parse, pluginDeclaration_get, } from './binDeclarations.js';
|
|
34
|
+
/** The built-in names the ChRIS session answers, for `help variables`. */
|
|
35
|
+
export const CHRIS_BUILTIN_LINES = [
|
|
36
|
+
' ${gather} every gathered member, as operands (where it was gathered FROM); read live',
|
|
37
|
+
' ${gather.series.folderPath} the same members, where they LANDED in CUBE',
|
|
38
|
+
' ${gather.name} ${gather.feed.id} any field of the cohort, as `gather` answers it',
|
|
39
|
+
];
|
|
31
40
|
/**
|
|
32
41
|
* The node a pipeline run starts from, read from its operand (#1303): a
|
|
33
42
|
* directory inside a feed is that node; outside one, or a set of files
|
|
@@ -35,14 +44,14 @@ import { operandRuns_split } from '../builtins/operandRuns.js';
|
|
|
35
44
|
* name (or the subjects') as its title, and the run goes on from that root.
|
|
36
45
|
*
|
|
37
46
|
* @param name - The pipeline's `/bin` name, for the refusal lines.
|
|
38
|
-
* @param
|
|
47
|
+
* @param line - The line, read.
|
|
39
48
|
* @param dry - Say where the run would start, staging and rooting nothing (`whatif`).
|
|
40
|
-
* @returns
|
|
49
|
+
* @returns Where the run starts, or null after a refusal was said.
|
|
41
50
|
*/
|
|
42
|
-
async function pipelineOperand_place(name,
|
|
51
|
+
async function pipelineOperand_place(name, line, dry = false) {
|
|
43
52
|
let operands;
|
|
44
53
|
try {
|
|
45
|
-
operands = await operands_read(
|
|
54
|
+
operands = await operands_read(line.operands);
|
|
46
55
|
}
|
|
47
56
|
catch (error) {
|
|
48
57
|
if (!(error instanceof OperandRefusal))
|
|
@@ -54,14 +63,14 @@ async function pipelineOperand_place(name, args, dry = false) {
|
|
|
54
63
|
// No operand: the working directory is the input, as it is for a plugin run from /bin. Inside a feed node the
|
|
55
64
|
// run goes on from that node (`pipeline run` reads it); outside one, pl-dircopy roots a new feed on it first,
|
|
56
65
|
// as the directory operand would (#1364).
|
|
57
|
-
if (
|
|
58
|
-
return {
|
|
66
|
+
if (line.previous !== undefined)
|
|
67
|
+
return { previous: line.previous, dryNewFeed: false, rooted: false };
|
|
59
68
|
const cwd = await path_resolve('.');
|
|
60
69
|
if (path_isInFeed(cwd))
|
|
61
|
-
return {
|
|
70
|
+
return { dryNewFeed: false, rooted: false };
|
|
62
71
|
operands = { ...operands, directory: cwd, typed: [cwd] };
|
|
63
72
|
}
|
|
64
|
-
if (
|
|
73
|
+
if (line.previous !== undefined) {
|
|
65
74
|
sink_get().err_write(chalk.red(`${name}: the operand and --previous say the input twice\n`));
|
|
66
75
|
return null;
|
|
67
76
|
}
|
|
@@ -71,7 +80,7 @@ async function pipelineOperand_place(name, args, dry = false) {
|
|
|
71
80
|
sink_get().err_write(chalk.red(`${name}: ${operands.typed[0]} is in a feed but not at a node (…/feeds/feed_N/pl-x_ID)\n`));
|
|
72
81
|
return null;
|
|
73
82
|
}
|
|
74
|
-
return {
|
|
83
|
+
return { previous: here, dryNewFeed: false, rooted: false };
|
|
75
84
|
}
|
|
76
85
|
let stage = null;
|
|
77
86
|
let root = operands.directory ?? '';
|
|
@@ -88,14 +97,14 @@ async function pipelineOperand_place(name, args, dry = false) {
|
|
|
88
97
|
}
|
|
89
98
|
if (dry)
|
|
90
99
|
sink_get().data_write(chalk.cyan(`would stage under ${stage.path}\n`));
|
|
91
|
-
for (const
|
|
92
|
-
sink_get().data_write(chalk.cyan(`${
|
|
100
|
+
for (const stageLine of stage_lines(stage))
|
|
101
|
+
sink_get().data_write(chalk.cyan(`${stageLine}\n`));
|
|
93
102
|
root = stage.path;
|
|
94
103
|
title = stage.subjects.map((subject) => subject.name).join(', ');
|
|
95
104
|
}
|
|
96
105
|
if (dry) {
|
|
97
106
|
sink_get().data_write(chalk.gray(`${echoNode_render(root, title)}\n`));
|
|
98
|
-
return {
|
|
107
|
+
return { dryNewFeed: true, rooted: false };
|
|
99
108
|
}
|
|
100
109
|
const feed = await feed_create([root], { title });
|
|
101
110
|
if (feed === null) {
|
|
@@ -106,27 +115,39 @@ async function pipelineOperand_place(name, args, dry = false) {
|
|
|
106
115
|
newFeed_cacheAdd({ feedID: feed.id, title, ownerUsername: feed.owner_username, rootInstanceID });
|
|
107
116
|
sink_get().data_write(chalk.green(`Feed created: ${feed.id}\n`));
|
|
108
117
|
if (stage !== null) {
|
|
109
|
-
for (const
|
|
110
|
-
sink_get().data_write(chalk.cyan(`${
|
|
118
|
+
for (const made of stageMade_lines(stage, `/home/${feed.owner_username}/feeds/feed_${feed.id}/pl-dircopy_${rootInstanceID}/data`))
|
|
119
|
+
sink_get().data_write(chalk.cyan(`${made}\n`));
|
|
111
120
|
}
|
|
112
|
-
return {
|
|
121
|
+
return { previous: rootInstanceID, dryNewFeed: false, rooted: true };
|
|
113
122
|
}
|
|
114
123
|
/**
|
|
115
124
|
* Runs a pipeline once from the node its operand names.
|
|
116
125
|
*
|
|
117
126
|
* @param name - The pipeline's `/bin` name.
|
|
118
|
-
* @param
|
|
127
|
+
* @param line - The line, read: at most one directory operand.
|
|
119
128
|
* @param dry - Resolve the run and print it, creating and running nothing.
|
|
120
129
|
* @returns The run's envelope; an error envelope after a refusal was said.
|
|
121
130
|
*/
|
|
122
|
-
async function pipelineRun_start(name,
|
|
131
|
+
async function pipelineRun_start(name, line, dry = false) {
|
|
123
132
|
// The operand says where the run starts (#1303); refused, nothing runs.
|
|
124
|
-
const placed = await pipelineOperand_place(name,
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
const placed = await pipelineOperand_place(name, line, dry);
|
|
134
|
+
if (placed === null)
|
|
135
|
+
return { status: 'error', rendered: '' };
|
|
136
|
+
const request = {
|
|
137
|
+
pipeline: name,
|
|
138
|
+
...(line.compute !== undefined ? { compute: line.compute } : {}),
|
|
139
|
+
...(placed.previous !== undefined ? { previous: placed.previous } : {}),
|
|
140
|
+
...(line.paramFile !== undefined ? { paramFile: line.paramFile } : {}),
|
|
141
|
+
bindings: line.bindings.map((binding) => ({ node: binding.node, field: binding.field, value: binding.value })),
|
|
142
|
+
detach: line.detach,
|
|
143
|
+
verbose: line.verbose,
|
|
144
|
+
dry,
|
|
145
|
+
dryNewFeed: placed.dryNewFeed,
|
|
146
|
+
};
|
|
147
|
+
const envelope = await pipelineRun_execute(request);
|
|
127
148
|
// The model says when the run rooted a feed first: the fallback rooted it, so the fallback says so (the kind is
|
|
128
149
|
// `pipeline.scheduled`, PIPELINE_SCHEDULED_KIND; named here so a test's stub of the pipeline module need not carry it).
|
|
129
|
-
if (placed
|
|
150
|
+
if (placed.rooted && envelope.model?.kind === 'pipeline.scheduled')
|
|
130
151
|
envelope.model.data.newFeed = true;
|
|
131
152
|
return envelope;
|
|
132
153
|
}
|
|
@@ -135,14 +156,14 @@ async function pipelineRun_start(name, args, dry = false) {
|
|
|
135
156
|
* names several, each run headed by its operand.
|
|
136
157
|
*
|
|
137
158
|
* @param name - The pipeline's `/bin` name.
|
|
138
|
-
* @param
|
|
159
|
+
* @param line - The line, read.
|
|
139
160
|
* @param dry - Resolve every run and print it, creating and running nothing.
|
|
140
161
|
* @returns The last run's envelope, an error when any run failed or the line was refused.
|
|
141
162
|
*/
|
|
142
|
-
async function pipelineRuns_start(name,
|
|
163
|
+
async function pipelineRuns_start(name, line, dry = false) {
|
|
143
164
|
let runs;
|
|
144
165
|
try {
|
|
145
|
-
runs = await operandRuns_split(
|
|
166
|
+
runs = await operandRuns_split(line.operands);
|
|
146
167
|
}
|
|
147
168
|
catch (error) {
|
|
148
169
|
if (!(error instanceof OperandRefusal))
|
|
@@ -151,21 +172,20 @@ async function pipelineRuns_start(name, args, dry = false) {
|
|
|
151
172
|
return { status: 'error', rendered: '' };
|
|
152
173
|
}
|
|
153
174
|
if (runs.length === 1)
|
|
154
|
-
return pipelineRun_start(name,
|
|
175
|
+
return pipelineRun_start(name, line, dry);
|
|
155
176
|
// Every run is dispatched before any is waited for; then one wait holds the line for them all.
|
|
156
|
-
const detach = args.includes('--detach');
|
|
157
177
|
const instanceIDs = [];
|
|
158
178
|
let last = { status: 'ok', rendered: '' };
|
|
159
179
|
let failed = false;
|
|
160
180
|
for (const words of runs) {
|
|
161
181
|
sink_get().data_write(chalk.gray(`${name} ${words[0]}:\n`));
|
|
162
|
-
last = await pipelineRun_start(name,
|
|
182
|
+
last = await pipelineRun_start(name, { ...line, operands: words, detach: true }, dry);
|
|
163
183
|
failed ||= last.status === 'error';
|
|
164
184
|
if (last.model?.kind === 'pipeline.scheduled') {
|
|
165
185
|
instanceIDs.push(...last.model.data.instances.map((node) => node.instanceId));
|
|
166
186
|
}
|
|
167
187
|
}
|
|
168
|
-
if (!detach && instanceIDs.length > 0) {
|
|
188
|
+
if (!line.detach && instanceIDs.length > 0) {
|
|
169
189
|
const settlement = await runs_awaitSettled(instanceIDs, name);
|
|
170
190
|
sink_get().data_write(`${settlement_render(settlement, name)}\n`);
|
|
171
191
|
if (settlement.outcome === 'settled' && settlement.failed > 0)
|
|
@@ -174,51 +194,80 @@ async function pipelineRuns_start(name, args, dry = false) {
|
|
|
174
194
|
return failed ? { ...last, status: 'error' } : last;
|
|
175
195
|
}
|
|
176
196
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* --
|
|
180
|
-
* --
|
|
181
|
-
* --
|
|
182
|
-
* --
|
|
183
|
-
* --
|
|
184
|
-
*
|
|
185
|
-
* (bare or --compute) → pipeline run
|
|
197
|
+
* Answers a pipeline line already read: the look it asks for, or its runs.
|
|
198
|
+
* --diagram (with --withargs, or --signalflow) → the diagram
|
|
199
|
+
* --signalflow → SignalFlow YAML
|
|
200
|
+
* --help / -h → the pipeline's page
|
|
201
|
+
* --nodes / --parameters → pipeline info
|
|
202
|
+
* --manifest → pipeline manifest
|
|
203
|
+
* --source / --readme → pipeline source
|
|
204
|
+
* otherwise → a run
|
|
186
205
|
*
|
|
187
|
-
* @param name - The pipeline name
|
|
188
|
-
* @param
|
|
206
|
+
* @param name - The pipeline's `/bin` name.
|
|
207
|
+
* @param line - The line, read against its declaration.
|
|
189
208
|
* @param dry - Resolve a run and print it, creating and running nothing.
|
|
190
|
-
* @returns The
|
|
209
|
+
* @returns The answer's envelope.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* await pipelineParsed_run('PHI_detection_id12', line);
|
|
214
|
+
* ```
|
|
191
215
|
*/
|
|
192
|
-
async function
|
|
216
|
+
export async function pipelineParsed_run(name, line, dry = false) {
|
|
193
217
|
const exitCodeBefore = exitCode_read();
|
|
194
218
|
let envelope;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
219
|
+
switch (line.look) {
|
|
220
|
+
case 'help':
|
|
221
|
+
envelope = { status: 'ok', rendered: pipelineExecutableHelp_render(name, (await pipelineDeclaration_get(name)) ?? undefined) };
|
|
222
|
+
break;
|
|
223
|
+
case 'diagram':
|
|
224
|
+
envelope = await pipelineDiagramCommand_handle(name, line.withArguments, line.signalflow);
|
|
225
|
+
break;
|
|
226
|
+
case 'signalflow':
|
|
227
|
+
envelope = await pipelineDiagramCommand_handle(name, false, true);
|
|
228
|
+
break;
|
|
229
|
+
case 'manifest':
|
|
230
|
+
envelope = await pipelineManifestCommand_handle(name);
|
|
231
|
+
break;
|
|
232
|
+
case 'nodes':
|
|
233
|
+
envelope = await pipelineInfo_handle(name);
|
|
234
|
+
break;
|
|
235
|
+
case 'source':
|
|
236
|
+
envelope = await pipelineSource_handle(name);
|
|
237
|
+
break;
|
|
238
|
+
case null:
|
|
239
|
+
envelope = await pipelineRuns_start(name, line, dry);
|
|
240
|
+
break;
|
|
201
241
|
}
|
|
202
|
-
else if (args.includes('--signalflow')) {
|
|
203
|
-
envelope = await builtin_pipeline(['diagram', name, '--signalflow']);
|
|
204
|
-
}
|
|
205
|
-
else if (args.includes('--manifest')) {
|
|
206
|
-
envelope = await builtin_pipeline(['manifest', name]);
|
|
207
|
-
}
|
|
208
|
-
else if (args.includes('--nodes') || args.includes('--parameters')) {
|
|
209
|
-
envelope = await builtin_pipeline(['info', name]);
|
|
210
|
-
}
|
|
211
|
-
else if (args.includes('--source') || args.includes('--readme')) {
|
|
212
|
-
envelope = await builtin_pipeline(['source', name]);
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
envelope = await pipelineRuns_start(name, args, dry);
|
|
216
|
-
}
|
|
217
|
-
const result = envelope ?? { status: 'ok', rendered: '' };
|
|
218
242
|
const exitCodeAfter = exitCode_read();
|
|
219
243
|
if (exitCodeAfter !== 0 && exitCodeAfter !== exitCodeBefore)
|
|
220
|
-
|
|
221
|
-
return
|
|
244
|
+
envelope.status = 'error';
|
|
245
|
+
return envelope;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Handles a pipeline name invoked directly as an executable from /bin: its
|
|
249
|
+
* line parsed against the declaration made from its manifest, a bad line
|
|
250
|
+
* refused before anything runs.
|
|
251
|
+
*
|
|
252
|
+
* @param name - The pipeline's `/bin` name.
|
|
253
|
+
* @param args - Arguments following the pipeline name.
|
|
254
|
+
* @param dry - Resolve a run and print it, creating and running nothing.
|
|
255
|
+
* @returns The answer's envelope; an error after a refusal.
|
|
256
|
+
*/
|
|
257
|
+
async function pipelineExecutable_handle(name, args, dry = false) {
|
|
258
|
+
const declaration = await pipelineDeclaration_get(name);
|
|
259
|
+
if (declaration === null) {
|
|
260
|
+
sink_get().err_write(chalk.red(`${name}: could not read the pipeline's manifest from CUBE, so the line cannot be read\n`));
|
|
261
|
+
exitCode_set(1);
|
|
262
|
+
return { status: 'error', rendered: '' };
|
|
263
|
+
}
|
|
264
|
+
const parsed = await pipelineWords_parse(declaration, args);
|
|
265
|
+
if (!parsed.ok) {
|
|
266
|
+
sink_get().err_write(`${chalk.red(parsed.refusal)}\n`);
|
|
267
|
+
exitCode_set(1);
|
|
268
|
+
return { status: 'error', rendered: '' };
|
|
269
|
+
}
|
|
270
|
+
return pipelineParsed_run(name, parsed.line, dry);
|
|
222
271
|
}
|
|
223
272
|
/**
|
|
224
273
|
* Hands a word to chili when chili has it, with the hand-off notice on the
|
|
@@ -240,7 +289,9 @@ async function chili_delegate(command, args) {
|
|
|
240
289
|
* `whatif <plugin or Pipeline line>`: resolves the line as a run would, to
|
|
241
290
|
* the version, the operands, the stage, the node and the parameters, prints
|
|
242
291
|
* that, and stops before anything is created or run. A prefix, as `time`
|
|
243
|
-
* and `env` are, since every flag after a `/bin` name is the plugin's
|
|
292
|
+
* and `env` are, since every flag after a `/bin` name is the plugin's: the
|
|
293
|
+
* line after it is parsed against that plugin's or pipeline's declaration,
|
|
294
|
+
* and refused as the real line would be.
|
|
244
295
|
*
|
|
245
296
|
* @param args - The line: the `/bin` name and its words.
|
|
246
297
|
* @returns An ok envelope when the real line would be accepted; an error after the refusal the real line would give.
|
|
@@ -251,49 +302,51 @@ export async function builtin_whatif(args) {
|
|
|
251
302
|
sink_get().err_write(chalk.red('whatif: usage: whatif <plugin or Pipeline> [operands] [options]\n'));
|
|
252
303
|
return { status: 'error', rendered: '' };
|
|
253
304
|
}
|
|
305
|
+
// The words after the /bin name keep the shell words the line carried, so its operands glob by kind.
|
|
306
|
+
const carried = args.words;
|
|
307
|
+
const lineWords = carried !== undefined && carried.length === args.length ? shellWords_values(carried.slice(1)) : words;
|
|
254
308
|
const binMatches = await binExecutableMatches_get(command);
|
|
255
309
|
if (binMatches.plugin)
|
|
256
|
-
return builtin_executePlugin(command,
|
|
310
|
+
return builtin_executePlugin(command, lineWords, undefined, true);
|
|
257
311
|
if (binMatches.pipeline) {
|
|
258
|
-
const envelope = await pipelineExecutable_handle(binMatches.pipeline.name,
|
|
312
|
+
const envelope = await pipelineExecutable_handle(binMatches.pipeline.name, lineWords, true);
|
|
259
313
|
envelope_deliver(envelope);
|
|
260
314
|
return { ...envelope, rendered: '' };
|
|
261
315
|
}
|
|
262
316
|
const highest = await binPluginHighest_find(command);
|
|
263
317
|
if (highest !== null) {
|
|
264
318
|
sink_get().data_write(chalk.gray(`running ${highest.executable} (highest of ${highest.versions.join(', ')})\n`));
|
|
265
|
-
return builtin_executePlugin(highest.executable,
|
|
319
|
+
return builtin_executePlugin(highest.executable, lineWords, undefined, true);
|
|
266
320
|
}
|
|
267
321
|
sink_get().err_write(chalk.red(`whatif: ${command}: not a plugin or a Pipeline in /bin\n`));
|
|
268
322
|
return { status: 'error', rendered: '' };
|
|
269
323
|
}
|
|
270
324
|
/**
|
|
271
325
|
* Completes a word of a `whatif` line as the line after it completes: its
|
|
272
|
-
* first word a plugin `/bin` lists,
|
|
273
|
-
*
|
|
326
|
+
* first word a plugin or pipeline `/bin` lists, then the rest from that
|
|
327
|
+
* entry's declaration (its options, and its input paths).
|
|
274
328
|
*
|
|
275
329
|
* @param words - The words after `whatif`, before the one completed.
|
|
276
330
|
* @param word - The word typed so far.
|
|
277
331
|
* @returns The candidates.
|
|
278
332
|
*/
|
|
279
333
|
async function whatifWord_complete(words, word) {
|
|
280
|
-
const { chrisCompletion } = await import('./completion.js');
|
|
281
334
|
const first = words[0];
|
|
282
335
|
if (first === undefined) {
|
|
283
|
-
const
|
|
284
|
-
return
|
|
336
|
+
const { binNames_list } = await import('./completion.js');
|
|
337
|
+
return (await binNames_list()).filter((name) => name.startsWith(word));
|
|
285
338
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if (words[words.length - 1] === 'as' || !(await chrisCompletion.pathArguments?.(first)))
|
|
339
|
+
const declaration = await binDeclaration_get(first);
|
|
340
|
+
if (declaration === null)
|
|
289
341
|
return [];
|
|
290
|
-
const {
|
|
291
|
-
return
|
|
342
|
+
const { declaredWord_complete } = await import('../lib/completer/declared.js');
|
|
343
|
+
return declaredWord_complete(declaration, words.slice(1), word);
|
|
292
344
|
}
|
|
293
345
|
/**
|
|
294
346
|
* `whatif <plugin or Pipeline line>`: the declaration. Its words are a whole
|
|
295
|
-
* line of another command, whose
|
|
296
|
-
* them
|
|
347
|
+
* line of another command, whose grammar is that command's (the declaration
|
|
348
|
+
* CUBE's parameters make), so it hands them on as they came, as `time` and
|
|
349
|
+
* `env` would.
|
|
297
350
|
*
|
|
298
351
|
* @example
|
|
299
352
|
* ```ts
|
|
@@ -306,7 +359,7 @@ export const whatifCommand = {
|
|
|
306
359
|
help: {
|
|
307
360
|
usage: 'whatif <plugin or Pipeline> [operands] [options]',
|
|
308
361
|
summary: 'Print what a plugin or Pipeline line would do, and run nothing',
|
|
309
|
-
description: 'Resolve the line as a run would and print it: the version picked, the operands as read, the stage, the node it would attach to or the feed it would root, and every parameter with defaults marked. Nothing is staged, no feed is made, no job starts. When the real line would refuse, whatif prints the same refusal and exits non-zero. A prefix, as time and env are: every flag after a /bin name belongs to the plugin, and several directory operands print one resolution per run.',
|
|
362
|
+
description: 'Resolve the line as a run would and print it: the version picked, the operands as read, the stage, the node it would attach to or the feed it would root, and every parameter with defaults marked. Nothing is staged, no feed is made, no job starts. When the real line would refuse, whatif prints the same refusal and exits non-zero: the line is parsed against the plugin\'s or Pipeline\'s own declaration, made from CUBE\'s parameters. A prefix, as time and env are: every flag after a /bin name belongs to the plugin, and several directory operands print one resolution per run.',
|
|
310
363
|
category: 'Resources',
|
|
311
364
|
examples: ['whatif pl-freesurfer ~/uploads/t1.nii as sub-01', 'whatif pl-dcm2niix ~/feeds/feed_12/pl-dircopy_40/data'],
|
|
312
365
|
},
|
|
@@ -314,9 +367,27 @@ export const whatifCommand = {
|
|
|
314
367
|
handler: builtin_whatif,
|
|
315
368
|
complete: whatifWord_complete,
|
|
316
369
|
};
|
|
370
|
+
/**
|
|
371
|
+
* The page of a `/bin` entry, its usage and every option from the
|
|
372
|
+
* declaration CUBE's parameters make.
|
|
373
|
+
*
|
|
374
|
+
* @param entry - The entry.
|
|
375
|
+
* @returns The page.
|
|
376
|
+
*/
|
|
377
|
+
async function binEntryHelp_render(entry) {
|
|
378
|
+
if (entry.kind === 'plugin')
|
|
379
|
+
return pluginExecutableHelp_render(entry.executable, (await pluginDeclaration_get(entry.executable)) ?? undefined);
|
|
380
|
+
return pipelineExecutableHelp_render(entry.name, (await pipelineDeclaration_get(entry.name)) ?? undefined);
|
|
381
|
+
}
|
|
317
382
|
/** The ChRIS backend's fallback. */
|
|
318
383
|
export const chrisFallback = {
|
|
319
|
-
claim:
|
|
384
|
+
claim: async (command, args) => {
|
|
385
|
+
// A plugin version's page is its declaration's, read from CUBE.
|
|
386
|
+
if (/-v[^/]+$/.test(command) && (args.includes('--help') || args.includes('-h'))) {
|
|
387
|
+
return { status: 'ok', rendered: pluginExecutableHelp_render(command, (await pluginDeclaration_get(command)) ?? undefined) };
|
|
388
|
+
}
|
|
389
|
+
return pluginExecutable_handle(command, args);
|
|
390
|
+
},
|
|
320
391
|
unknown: async (command, args, captured) => {
|
|
321
392
|
const binMatches = await binExecutableMatches_get(command);
|
|
322
393
|
// A bare /bin plugin name runs the plugin, and a run is a CUBE job: typed
|
|
@@ -349,13 +420,11 @@ export const chrisFallback = {
|
|
|
349
420
|
return variablesPage_render(CHRIS_BUILTIN_LINES);
|
|
350
421
|
// A plugin version (`pl-dircopy-v2.1.2`) is its own executable.
|
|
351
422
|
if (/-v[^/]+$/.test(command))
|
|
352
|
-
return pluginExecutableHelp_render(command);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
// A bare plugin name's help is its highest version's.
|
|
357
|
-
const highest = await binPluginHighest_find(command);
|
|
358
|
-
return highest === null ? null : pluginExecutableHelp_render(highest.executable);
|
|
423
|
+
return pluginExecutableHelp_render(command, (await pluginDeclaration_get(command)) ?? undefined);
|
|
424
|
+
// A pipeline, or a bare plugin name (its highest version's page).
|
|
425
|
+
const entry = await binEntry_resolve(command);
|
|
426
|
+
return entry === null ? null : binEntryHelp_render(entry);
|
|
359
427
|
},
|
|
428
|
+
declaration: binDeclaration_get,
|
|
360
429
|
};
|
|
361
430
|
//# sourceMappingURL=commandFallback.js.map
|