@galaxy-tool-util/schema 1.10.1 → 1.12.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/index.d.ts +26 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/dist/schema/bundle-types.d.ts +6 -2
- package/dist/schema/bundle-types.d.ts.map +1 -1
- package/dist/schema/bundle-types.js.map +1 -1
- package/dist/schema/parameter-defaults.d.ts.map +1 -1
- package/dist/schema/parameter-defaults.js +7 -3
- package/dist/schema/parameter-defaults.js.map +1 -1
- package/dist/schema/parameters/base.d.ts.map +1 -1
- package/dist/schema/parameters/base.js +3 -1
- package/dist/schema/parameters/base.js.map +1 -1
- package/dist/schema/parameters/gx-drill-down.js +2 -1
- package/dist/schema/parameters/gx-drill-down.js.map +1 -1
- package/dist/schema/parameters/gx-text.js +2 -2
- package/dist/schema/parameters/gx-text.js.map +1 -1
- package/dist/schema/parsed-tool.d.ts +180 -10
- package/dist/schema/parsed-tool.d.ts.map +1 -1
- package/dist/schema/parsed-tool.js +56 -2
- package/dist/schema/parsed-tool.js.map +1 -1
- package/dist/schema/state-representations.js +1 -1
- package/dist/schema/state-representations.js.map +1 -1
- package/dist/tool-state-validator.d.ts +2 -2
- package/dist/tool-state-validator.d.ts.map +1 -1
- package/dist/tool-state-validator.js +4 -4
- package/dist/tool-state-validator.js.map +1 -1
- package/dist/trs/index.d.ts +110 -0
- package/dist/trs/index.d.ts.map +1 -0
- package/dist/trs/index.js +64 -0
- package/dist/trs/index.js.map +1 -0
- package/dist/user-tool-parse/index.d.ts +4 -1
- package/dist/user-tool-parse/index.d.ts.map +1 -1
- package/dist/user-tool-parse/index.js +4 -1
- package/dist/user-tool-parse/index.js.map +1 -1
- package/dist/user-tool-parse/input-source.d.ts +105 -0
- package/dist/user-tool-parse/input-source.d.ts.map +1 -0
- package/dist/user-tool-parse/input-source.js +271 -0
- package/dist/user-tool-parse/input-source.js.map +1 -0
- package/dist/user-tool-parse/inputs.d.ts +15 -8
- package/dist/user-tool-parse/inputs.d.ts.map +1 -1
- package/dist/user-tool-parse/inputs.js +188 -295
- package/dist/user-tool-parse/inputs.js.map +1 -1
- package/dist/user-tool-parse/outputs.d.ts +2 -1
- package/dist/user-tool-parse/outputs.d.ts.map +1 -1
- package/dist/user-tool-parse/outputs.js +4 -3
- package/dist/user-tool-parse/outputs.js.map +1 -1
- package/dist/user-tool-parse/parse.d.ts +17 -2
- package/dist/user-tool-parse/parse.d.ts.map +1 -1
- package/dist/user-tool-parse/parse.js +23 -6
- package/dist/user-tool-parse/parse.js.map +1 -1
- package/dist/workflow/normalized/stateful-runner.d.ts +3 -1
- package/dist/workflow/normalized/stateful-runner.d.ts.map +1 -1
- package/dist/workflow/normalized/stateful-runner.js +1 -1
- package/dist/workflow/normalized/stateful-runner.js.map +1 -1
- package/dist/workflow/normalized/toFormat2Stateful.js +8 -10
- package/dist/workflow/normalized/toFormat2Stateful.js.map +1 -1
- package/dist/workflow/normalized/toNativeStateful.d.ts.map +1 -1
- package/dist/workflow/normalized/toNativeStateful.js +3 -10
- package/dist/workflow/normalized/toNativeStateful.js.map +1 -1
- package/dist/workflow/report-models.d.ts +1 -1
- package/dist/workflow/report-models.d.ts.map +1 -1
- package/dist/workflow/report-models.js +1 -0
- package/dist/workflow/report-models.js.map +1 -1
- package/dist/workflow/stateful-convert.d.ts.map +1 -1
- package/dist/workflow/stateful-convert.js +6 -0
- package/dist/workflow/stateful-convert.js.map +1 -1
- package/dist/workflow/stateful-validate.d.ts +12 -5
- package/dist/workflow/stateful-validate.d.ts.map +1 -1
- package/dist/workflow/stateful-validate.js +62 -24
- package/dist/workflow/stateful-validate.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* `galaxy.tool_util.parameters.factory._from_input_source_galaxy
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* `
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
2
|
+
* Tool input factory. Mirrors
|
|
3
|
+
* `galaxy.tool_util.parameters.factory._from_input_source_galaxy` +
|
|
4
|
+
* `input_models_for_page`: it consumes an `InputSource` (see `./input-source.ts`)
|
|
5
|
+
* rather than a raw dict, so both the inline/YAML source and an XML source in
|
|
6
|
+
* `@galaxy-tool-util/tool-xml` build the same `ToolParameterModel` union from
|
|
7
|
+
* `bundle-types.ts`. Validator handling is best-effort: `parse_validators`
|
|
8
|
+
* returns every parsed validator and the factory keeps the ones valid for the
|
|
9
|
+
* parameter type (mirrors `static_validators(...)`).
|
|
10
10
|
*/
|
|
11
|
+
import { DictPageSource, coerceBool, isDict, readNullableString, readNullableInt, readNullableFloat, } from "./input-source.js";
|
|
11
12
|
const DATA_PARAM_TYPES = new Set([
|
|
12
13
|
"integer",
|
|
13
14
|
"float",
|
|
@@ -28,91 +29,59 @@ const DATA_PARAM_TYPES = new Set([
|
|
|
28
29
|
"directory_uri",
|
|
29
30
|
]);
|
|
30
31
|
export function parseInputs(raw) {
|
|
31
|
-
|
|
32
|
-
return list.map(parseInput);
|
|
32
|
+
return inputModelsForPage(new DictPageSource(raw));
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
return out;
|
|
34
|
+
/**
|
|
35
|
+
* Mirror of `factory.input_models_for_page`: build the `ToolParameterModel`
|
|
36
|
+
* list for one `PageSource`, whatever backs it (the inline/YAML `DictPageSource`
|
|
37
|
+
* or an XML page source in `@galaxy-tool-util/tool-xml`).
|
|
38
|
+
*/
|
|
39
|
+
export function inputModelsForPage(page) {
|
|
40
|
+
const models = [];
|
|
41
|
+
for (const source of page.parseInputSources()) {
|
|
42
|
+
// `<display>` is not a real input (data_source tools carry one); skip it,
|
|
43
|
+
// matching `factory.input_models_for_page`.
|
|
44
|
+
if (source.parseInputType() === "display")
|
|
45
|
+
continue;
|
|
46
|
+
models.push(fromInputSource(source));
|
|
49
47
|
}
|
|
50
|
-
return
|
|
51
|
-
}
|
|
52
|
-
function parseInput(input) {
|
|
53
|
-
const containerType = readContainerType(input);
|
|
54
|
-
if (containerType === "conditional")
|
|
55
|
-
return parseConditional(input);
|
|
56
|
-
if (containerType === "repeat")
|
|
57
|
-
return parseRepeat(input);
|
|
58
|
-
if (containerType === "section")
|
|
59
|
-
return parseSection(input);
|
|
60
|
-
return parseLeafParam(input);
|
|
48
|
+
return models;
|
|
61
49
|
}
|
|
62
|
-
function
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
return
|
|
66
|
-
if (
|
|
67
|
-
return
|
|
68
|
-
if (
|
|
69
|
-
return
|
|
70
|
-
return
|
|
50
|
+
function fromInputSource(source) {
|
|
51
|
+
const inputType = source.parseInputType();
|
|
52
|
+
if (inputType === "conditional")
|
|
53
|
+
return buildConditional(source);
|
|
54
|
+
if (inputType === "repeat")
|
|
55
|
+
return buildRepeat(source);
|
|
56
|
+
if (inputType === "section")
|
|
57
|
+
return buildSection(source);
|
|
58
|
+
return buildLeafParam(source);
|
|
71
59
|
}
|
|
72
|
-
function
|
|
73
|
-
const name =
|
|
74
|
-
const
|
|
75
|
-
if (!isDict(testRaw)) {
|
|
76
|
-
throw new Error(`conditional '${name}' must define a 'test_parameter'`);
|
|
77
|
-
}
|
|
78
|
-
const testParam = parseLeafParam(testRaw);
|
|
60
|
+
function buildConditional(source) {
|
|
61
|
+
const name = source.parseName();
|
|
62
|
+
const testParam = fromInputSource(source.parseTestInputSource());
|
|
79
63
|
if (testParam.parameter_type !== "gx_boolean" && testParam.parameter_type !== "gx_select") {
|
|
80
64
|
throw new Error(`conditional '${name}' test_parameter must be boolean or select (got ${testParam.parameter_type})`);
|
|
81
65
|
}
|
|
82
|
-
const whens =
|
|
66
|
+
const whens = buildWhens(source, testParam);
|
|
83
67
|
return {
|
|
84
68
|
parameter_type: "gx_conditional",
|
|
85
69
|
name,
|
|
86
|
-
hidden:
|
|
87
|
-
label:
|
|
88
|
-
help:
|
|
89
|
-
argument: readNullableString(
|
|
70
|
+
hidden: source.getBool("hidden", false),
|
|
71
|
+
label: source.parseLabel(),
|
|
72
|
+
help: source.parseHelp(),
|
|
73
|
+
argument: readNullableString(source.get("argument")),
|
|
90
74
|
is_dynamic: false,
|
|
91
75
|
test_parameter: testParam,
|
|
92
76
|
whens,
|
|
93
77
|
};
|
|
94
78
|
}
|
|
95
|
-
function
|
|
79
|
+
function buildWhens(source, testParam) {
|
|
96
80
|
const defaultDiscriminator = defaultTestDiscriminator(testParam);
|
|
97
81
|
const result = [];
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const whenList = input.whens;
|
|
102
|
-
if (isDict(whenMap)) {
|
|
103
|
-
for (const [key, value] of Object.entries(whenMap)) {
|
|
104
|
-
const params = Array.isArray(value) ? value.filter(isDict) : [];
|
|
105
|
-
result.push(makeWhen(key, parseInputs(params), defaultDiscriminator, testParam));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
else if (Array.isArray(whenList)) {
|
|
109
|
-
for (const item of whenList) {
|
|
110
|
-
if (!isDict(item))
|
|
111
|
-
continue;
|
|
112
|
-
const disc = item.discriminator;
|
|
113
|
-
const params = item.parameters;
|
|
114
|
-
result.push(makeWhen(disc, parseInputs(params), defaultDiscriminator, testParam));
|
|
115
|
-
}
|
|
82
|
+
for (const [rawDiscriminator, page] of source.parseWhenInputSources()) {
|
|
83
|
+
const parameters = inputModelsForPage(page);
|
|
84
|
+
result.push(makeWhen(rawDiscriminator, parameters, defaultDiscriminator, testParam));
|
|
116
85
|
}
|
|
117
86
|
return result;
|
|
118
87
|
}
|
|
@@ -132,7 +101,19 @@ function defaultTestDiscriminator(testParam) {
|
|
|
132
101
|
function makeWhen(rawDiscriminator, parameters, defaultDiscriminator, testParam) {
|
|
133
102
|
let typed;
|
|
134
103
|
if (testParam.parameter_type === "gx_boolean") {
|
|
135
|
-
|
|
104
|
+
// Mirror Python: a `<when value="X">` string matching the test param's
|
|
105
|
+
// truevalue/falsevalue maps to that boolean before `string_as_bool`, so
|
|
106
|
+
// e.g. truevalue="--flag" with `<when value="--flag">` selects `true`.
|
|
107
|
+
const bp = testParam;
|
|
108
|
+
if (typeof rawDiscriminator === "string" && rawDiscriminator === bp.truevalue) {
|
|
109
|
+
typed = true;
|
|
110
|
+
}
|
|
111
|
+
else if (typeof rawDiscriminator === "string" && rawDiscriminator === bp.falsevalue) {
|
|
112
|
+
typed = false;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
typed = coerceBool(rawDiscriminator);
|
|
116
|
+
}
|
|
136
117
|
}
|
|
137
118
|
else {
|
|
138
119
|
typed = rawDiscriminator == null ? "" : String(rawDiscriminator);
|
|
@@ -140,106 +121,89 @@ function makeWhen(rawDiscriminator, parameters, defaultDiscriminator, testParam)
|
|
|
140
121
|
const isDefault = typed === defaultDiscriminator;
|
|
141
122
|
return { discriminator: typed, parameters, is_default_when: isDefault };
|
|
142
123
|
}
|
|
143
|
-
function
|
|
144
|
-
|
|
145
|
-
return v;
|
|
146
|
-
if (typeof v === "string") {
|
|
147
|
-
const lower = v.toLowerCase();
|
|
148
|
-
if (lower === "true" || lower === "yes" || lower === "1")
|
|
149
|
-
return true;
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
return Boolean(v);
|
|
153
|
-
}
|
|
154
|
-
function parseRepeat(input) {
|
|
155
|
-
const name = readString(input.name);
|
|
156
|
-
const innerRaw = input.blocks ?? input.parameters ?? input.inputs;
|
|
157
|
-
const parameters = parseInputs(innerRaw);
|
|
124
|
+
function buildRepeat(source) {
|
|
125
|
+
const parameters = inputModelsForPage(source.parseNestedInputsSource());
|
|
158
126
|
return {
|
|
159
127
|
parameter_type: "gx_repeat",
|
|
160
|
-
name,
|
|
161
|
-
hidden:
|
|
162
|
-
label:
|
|
163
|
-
help:
|
|
164
|
-
argument: readNullableString(
|
|
128
|
+
name: source.parseName(),
|
|
129
|
+
hidden: source.getBool("hidden", false),
|
|
130
|
+
label: source.parseLabel(),
|
|
131
|
+
help: source.parseHelp(),
|
|
132
|
+
argument: readNullableString(source.get("argument")),
|
|
165
133
|
is_dynamic: false,
|
|
166
134
|
parameters,
|
|
167
|
-
min: readNullableInt(
|
|
168
|
-
max: readNullableInt(
|
|
135
|
+
min: readNullableInt(source.get("min")),
|
|
136
|
+
max: readNullableInt(source.get("max")),
|
|
169
137
|
};
|
|
170
138
|
}
|
|
171
|
-
function
|
|
172
|
-
const
|
|
173
|
-
const innerRaw = input.parameters ?? input.inputs;
|
|
174
|
-
const parameters = parseInputs(innerRaw);
|
|
139
|
+
function buildSection(source) {
|
|
140
|
+
const parameters = inputModelsForPage(source.parseNestedInputsSource());
|
|
175
141
|
return {
|
|
176
142
|
parameter_type: "gx_section",
|
|
177
|
-
name,
|
|
178
|
-
hidden:
|
|
179
|
-
label:
|
|
180
|
-
help:
|
|
181
|
-
argument: readNullableString(
|
|
143
|
+
name: source.parseName(),
|
|
144
|
+
hidden: source.getBool("hidden", false),
|
|
145
|
+
label: source.parseLabel(),
|
|
146
|
+
help: source.parseHelp(),
|
|
147
|
+
argument: readNullableString(source.get("argument")),
|
|
182
148
|
is_dynamic: false,
|
|
183
149
|
parameters,
|
|
184
150
|
};
|
|
185
151
|
}
|
|
186
|
-
function
|
|
187
|
-
const paramType =
|
|
152
|
+
function buildLeafParam(source) {
|
|
153
|
+
const paramType = readParamType(source.get("type"));
|
|
188
154
|
if (!DATA_PARAM_TYPES.has(paramType)) {
|
|
189
155
|
throw new Error(`Unknown Galaxy parameter type '${paramType}'`);
|
|
190
156
|
}
|
|
191
|
-
const base = baseFields(
|
|
157
|
+
const base = baseFields(source);
|
|
192
158
|
switch (paramType) {
|
|
193
159
|
case "integer": {
|
|
194
|
-
const
|
|
195
|
-
const value = parseOptionalNumber(input.value, optional, "integer");
|
|
160
|
+
const value = parseOptionalNumber(source.get("value"), base.optional, "integer");
|
|
196
161
|
return {
|
|
197
162
|
...base,
|
|
198
163
|
parameter_type: "gx_integer",
|
|
199
164
|
type: "integer",
|
|
200
165
|
value,
|
|
201
|
-
min: readNullableInt(
|
|
202
|
-
max: readNullableInt(
|
|
203
|
-
validators:
|
|
166
|
+
min: readNullableInt(source.get("min")),
|
|
167
|
+
max: readNullableInt(source.get("max")),
|
|
168
|
+
validators: filterValidators(source.parseValidators(), "number"),
|
|
204
169
|
};
|
|
205
170
|
}
|
|
206
171
|
case "float": {
|
|
207
|
-
const
|
|
208
|
-
const value = parseOptionalNumber(input.value, optional, "float");
|
|
172
|
+
const value = parseOptionalNumber(source.get("value"), base.optional, "float");
|
|
209
173
|
return {
|
|
210
174
|
...base,
|
|
211
175
|
parameter_type: "gx_float",
|
|
212
176
|
type: "float",
|
|
213
177
|
value,
|
|
214
|
-
min: readNullableFloat(
|
|
215
|
-
max: readNullableFloat(
|
|
216
|
-
validators:
|
|
178
|
+
min: readNullableFloat(source.get("min")),
|
|
179
|
+
max: readNullableFloat(source.get("max")),
|
|
180
|
+
validators: filterValidators(source.parseValidators(), "number"),
|
|
217
181
|
};
|
|
218
182
|
}
|
|
219
183
|
case "text": {
|
|
220
|
-
const
|
|
184
|
+
const validators = filterValidators(source.parseValidators(), "text");
|
|
185
|
+
const optional = textIsOptional(source, validators);
|
|
221
186
|
return {
|
|
222
187
|
...base,
|
|
223
188
|
optional,
|
|
224
189
|
parameter_type: "gx_text",
|
|
225
190
|
type: "text",
|
|
226
|
-
area:
|
|
227
|
-
|
|
191
|
+
area: source.getBool("area", false),
|
|
192
|
+
default_value: textDefault(source.get("value"), optional),
|
|
228
193
|
default_options: [],
|
|
229
|
-
validators
|
|
194
|
+
validators,
|
|
230
195
|
};
|
|
231
196
|
}
|
|
232
197
|
case "boolean": {
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
const value = rawChecked == null ? (optional ? false : false) : coerceBool(rawChecked);
|
|
198
|
+
const rawChecked = source.get("checked");
|
|
199
|
+
const value = rawChecked == null ? false : coerceBool(rawChecked);
|
|
236
200
|
return {
|
|
237
201
|
...base,
|
|
238
202
|
parameter_type: "gx_boolean",
|
|
239
203
|
type: "boolean",
|
|
240
204
|
value,
|
|
241
|
-
truevalue: readNullableString(
|
|
242
|
-
falsevalue: readNullableString(
|
|
205
|
+
truevalue: readNullableString(source.get("truevalue")),
|
|
206
|
+
falsevalue: readNullableString(source.get("falsevalue")),
|
|
243
207
|
};
|
|
244
208
|
}
|
|
245
209
|
case "hidden": {
|
|
@@ -247,12 +211,13 @@ function parseLeafParam(input) {
|
|
|
247
211
|
...base,
|
|
248
212
|
parameter_type: "gx_hidden",
|
|
249
213
|
type: "hidden",
|
|
250
|
-
value: readNullableString(
|
|
251
|
-
validators:
|
|
214
|
+
value: readNullableString(source.get("value")),
|
|
215
|
+
validators: filterValidators(source.parseValidators(), "text"),
|
|
252
216
|
};
|
|
253
217
|
}
|
|
254
218
|
case "color": {
|
|
255
|
-
const
|
|
219
|
+
const rawValue = source.get("value");
|
|
220
|
+
const value = typeof rawValue === "string" ? rawValue : "#000000";
|
|
256
221
|
return {
|
|
257
222
|
...base,
|
|
258
223
|
parameter_type: "gx_color",
|
|
@@ -268,13 +233,21 @@ function parseLeafParam(input) {
|
|
|
268
233
|
// hidden_data is broken without optional=true in Python; mirror the
|
|
269
234
|
// override.
|
|
270
235
|
const optional = paramType === "data" ? base.optional : true;
|
|
236
|
+
const defaultValue = source.parseDefault();
|
|
237
|
+
const urlDefault = isDict(defaultValue) && defaultValue.location != null
|
|
238
|
+
? String(defaultValue.location)
|
|
239
|
+
: null;
|
|
271
240
|
return {
|
|
272
241
|
...base,
|
|
273
242
|
optional,
|
|
274
243
|
parameter_type: "gx_data",
|
|
275
244
|
type: "data",
|
|
276
|
-
multiple:
|
|
277
|
-
extensions: parseExtensions(
|
|
245
|
+
multiple: source.getBool("multiple", false),
|
|
246
|
+
extensions: source.parseExtensions(),
|
|
247
|
+
// The factory never reads min/max (mirrors Galaxy).
|
|
248
|
+
min: null,
|
|
249
|
+
max: null,
|
|
250
|
+
url_default: urlDefault,
|
|
278
251
|
};
|
|
279
252
|
}
|
|
280
253
|
case "data_collection": {
|
|
@@ -282,16 +255,17 @@ function parseLeafParam(input) {
|
|
|
282
255
|
...base,
|
|
283
256
|
parameter_type: "gx_data_collection",
|
|
284
257
|
type: "data_collection",
|
|
285
|
-
collection_type: readNullableString(
|
|
286
|
-
extensions: parseExtensions(
|
|
287
|
-
value:
|
|
258
|
+
collection_type: readNullableString(source.get("collection_type")),
|
|
259
|
+
extensions: source.parseExtensions(),
|
|
260
|
+
value: source.parseDefault() ?? source.get("value") ?? null,
|
|
288
261
|
};
|
|
289
262
|
}
|
|
290
263
|
case "select": {
|
|
291
|
-
const multiple =
|
|
264
|
+
const multiple = source.getBool("multiple", false);
|
|
292
265
|
const optional = base.optional;
|
|
293
|
-
|
|
294
|
-
const
|
|
266
|
+
// Dynamic options (data table / code) → `null`; otherwise the static list.
|
|
267
|
+
const options = source.hasDynamicOptions() ? null : source.parseStaticOptions();
|
|
268
|
+
const validators = filterValidators(source.parseValidators(), "select");
|
|
295
269
|
// `no_options` doesn't apply if select is optional (mirrors Python).
|
|
296
270
|
const filtered = optional ? validators.filter((v) => v.type !== "no_options") : validators;
|
|
297
271
|
return {
|
|
@@ -308,16 +282,18 @@ function parseLeafParam(input) {
|
|
|
308
282
|
...base,
|
|
309
283
|
parameter_type: "gx_drill_down",
|
|
310
284
|
type: "drill_down",
|
|
311
|
-
multiple:
|
|
312
|
-
hierarchy:
|
|
313
|
-
options:
|
|
285
|
+
multiple: source.getBool("multiple", false),
|
|
286
|
+
hierarchy: source.get("hierarchy") === "recurse" ? "recurse" : "exact",
|
|
287
|
+
options: source.hasDrillDownDynamicOptions()
|
|
288
|
+
? null
|
|
289
|
+
: (source.parseDrillDownStaticOptions() ?? []),
|
|
314
290
|
};
|
|
315
291
|
}
|
|
316
292
|
case "data_column": {
|
|
317
|
-
const multiple =
|
|
318
|
-
const acceptDefault =
|
|
293
|
+
const multiple = source.getBool("multiple", false);
|
|
294
|
+
const acceptDefault = source.getBool("accept_default", false);
|
|
319
295
|
let optional = base.optional;
|
|
320
|
-
let value =
|
|
296
|
+
let value = source.get("value");
|
|
321
297
|
if (!optional && acceptDefault)
|
|
322
298
|
optional = true;
|
|
323
299
|
if (acceptDefault && (value === null || value === undefined)) {
|
|
@@ -342,6 +318,7 @@ function parseLeafParam(input) {
|
|
|
342
318
|
type: "data_column",
|
|
343
319
|
multiple,
|
|
344
320
|
value: coerced,
|
|
321
|
+
data_ref: readNullableString(source.get("data_ref")),
|
|
345
322
|
};
|
|
346
323
|
}
|
|
347
324
|
case "group_tag": {
|
|
@@ -349,7 +326,7 @@ function parseLeafParam(input) {
|
|
|
349
326
|
...base,
|
|
350
327
|
parameter_type: "gx_group_tag",
|
|
351
328
|
type: "group_tag",
|
|
352
|
-
multiple:
|
|
329
|
+
multiple: source.getBool("multiple", false),
|
|
353
330
|
};
|
|
354
331
|
}
|
|
355
332
|
case "baseurl": {
|
|
@@ -357,7 +334,7 @@ function parseLeafParam(input) {
|
|
|
357
334
|
...base,
|
|
358
335
|
parameter_type: "gx_baseurl",
|
|
359
336
|
type: "baseurl",
|
|
360
|
-
value: readNullableString(
|
|
337
|
+
value: readNullableString(source.get("value")),
|
|
361
338
|
};
|
|
362
339
|
}
|
|
363
340
|
case "genomebuild": {
|
|
@@ -365,7 +342,7 @@ function parseLeafParam(input) {
|
|
|
365
342
|
...base,
|
|
366
343
|
parameter_type: "gx_genomebuild",
|
|
367
344
|
type: "genomebuild",
|
|
368
|
-
multiple:
|
|
345
|
+
multiple: source.getBool("multiple", false),
|
|
369
346
|
options: [],
|
|
370
347
|
};
|
|
371
348
|
}
|
|
@@ -374,32 +351,77 @@ function parseLeafParam(input) {
|
|
|
374
351
|
...base,
|
|
375
352
|
parameter_type: "gx_directory_uri",
|
|
376
353
|
type: "directory_uri",
|
|
377
|
-
value: readNullableString(
|
|
378
|
-
validators:
|
|
354
|
+
value: readNullableString(source.get("value")),
|
|
355
|
+
validators: filterValidators(source.parseValidators(), "text"),
|
|
379
356
|
};
|
|
380
357
|
}
|
|
381
358
|
default:
|
|
382
359
|
throw new Error(`Unknown Galaxy parameter type '${paramType}'`);
|
|
383
360
|
}
|
|
384
361
|
}
|
|
385
|
-
function baseFields(
|
|
362
|
+
function baseFields(source) {
|
|
386
363
|
return {
|
|
387
|
-
name:
|
|
388
|
-
hidden:
|
|
389
|
-
label:
|
|
390
|
-
help:
|
|
391
|
-
argument: readNullableString(
|
|
364
|
+
name: source.parseName(),
|
|
365
|
+
hidden: source.getBool("hidden", false),
|
|
366
|
+
label: source.parseLabel(),
|
|
367
|
+
help: source.parseHelp(),
|
|
368
|
+
argument: readNullableString(source.get("argument")),
|
|
392
369
|
is_dynamic: false,
|
|
393
|
-
optional:
|
|
370
|
+
optional: source.parseOptional(),
|
|
394
371
|
};
|
|
395
372
|
}
|
|
396
|
-
function
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
373
|
+
function readParamType(v) {
|
|
374
|
+
return typeof v === "string" ? v : v == null ? "" : String(v);
|
|
375
|
+
}
|
|
376
|
+
function textIsOptional(source, validators) {
|
|
377
|
+
// Mirrors `text_input_is_optional`: explicit `optional:` wins, otherwise a
|
|
378
|
+
// text param is optional when the empty string passes all its validators.
|
|
379
|
+
const optional = source.get("optional");
|
|
380
|
+
if (optional !== undefined && optional !== null) {
|
|
381
|
+
return coerceBool(optional);
|
|
382
|
+
}
|
|
383
|
+
return emptyStringValidates(validators);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Port of `statically_validates(validators, "")` for text params: the empty
|
|
387
|
+
* string is accepted when every static validator passes on it. A validator
|
|
388
|
+
* passes iff its base check differs from its `negate` flag (mirrors
|
|
389
|
+
* `raise_error_if_validation_fails`).
|
|
390
|
+
*/
|
|
391
|
+
function emptyStringValidates(validators) {
|
|
392
|
+
return validators.every((v) => {
|
|
393
|
+
const negate = "negate" in v && v.negate === true;
|
|
394
|
+
let passesRaw;
|
|
395
|
+
switch (v.type) {
|
|
396
|
+
case "empty_field":
|
|
397
|
+
passesRaw = false; // "" is empty
|
|
398
|
+
break;
|
|
399
|
+
case "length":
|
|
400
|
+
passesRaw = !(v.min != null && v.min > 0); // len("") === 0
|
|
401
|
+
break;
|
|
402
|
+
case "regex":
|
|
403
|
+
passesRaw = emptyMatchesRegex(v.expression);
|
|
404
|
+
break;
|
|
405
|
+
case "expression":
|
|
406
|
+
// Python evaluates the expression against value=""; TS can't, so treat
|
|
407
|
+
// it as not satisfying the empty string (conservative — matches the
|
|
408
|
+
// common truthy-`value` expression form, which is falsy for "").
|
|
409
|
+
passesRaw = false;
|
|
410
|
+
break;
|
|
411
|
+
default:
|
|
412
|
+
passesRaw = true; // non-text validators don't constrain ""
|
|
413
|
+
}
|
|
414
|
+
return passesRaw !== negate;
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
/** Whether `expression` matches the empty string anchored at the start (re.match). */
|
|
418
|
+
function emptyMatchesRegex(expression) {
|
|
419
|
+
try {
|
|
420
|
+
return new RegExp(`^(?:${expression})`, "u").test("");
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
return false;
|
|
401
424
|
}
|
|
402
|
-
return input.value === undefined || input.value === null || input.value === "";
|
|
403
425
|
}
|
|
404
426
|
function textDefault(value, optional) {
|
|
405
427
|
if (typeof value === "string")
|
|
@@ -408,55 +430,6 @@ function textDefault(value, optional) {
|
|
|
408
430
|
return optional ? null : "";
|
|
409
431
|
return String(value);
|
|
410
432
|
}
|
|
411
|
-
function parseExtensions(input) {
|
|
412
|
-
const explicit = input.extensions;
|
|
413
|
-
let raw = explicit;
|
|
414
|
-
if (raw === undefined || raw === null || (Array.isArray(raw) && raw.length === 0)) {
|
|
415
|
-
raw = input.format ?? "data";
|
|
416
|
-
}
|
|
417
|
-
let list;
|
|
418
|
-
if (Array.isArray(raw)) {
|
|
419
|
-
list = raw;
|
|
420
|
-
}
|
|
421
|
-
else if (typeof raw === "string") {
|
|
422
|
-
list = raw.split(",");
|
|
423
|
-
}
|
|
424
|
-
else {
|
|
425
|
-
list = ["data"];
|
|
426
|
-
}
|
|
427
|
-
return list.map((v) => String(v).trim().toLowerCase()).filter((v) => v !== "");
|
|
428
|
-
}
|
|
429
|
-
function parseStaticOptions(input) {
|
|
430
|
-
const opts = input.options;
|
|
431
|
-
if (!Array.isArray(opts))
|
|
432
|
-
return null;
|
|
433
|
-
const out = [];
|
|
434
|
-
for (const item of opts) {
|
|
435
|
-
if (!isDict(item))
|
|
436
|
-
continue;
|
|
437
|
-
const value = item.value;
|
|
438
|
-
if (value === undefined)
|
|
439
|
-
continue;
|
|
440
|
-
const valueStr = String(value);
|
|
441
|
-
const label = typeof item.label === "string" ? item.label : valueStr;
|
|
442
|
-
const selected = readBool(item.selected, false);
|
|
443
|
-
out.push({ label, value: valueStr, selected });
|
|
444
|
-
}
|
|
445
|
-
return out;
|
|
446
|
-
}
|
|
447
|
-
function parseDrillDownOptions(raw) {
|
|
448
|
-
if (!Array.isArray(raw))
|
|
449
|
-
return null;
|
|
450
|
-
return raw.filter(isDict).map(parseDrillDownOption);
|
|
451
|
-
}
|
|
452
|
-
function parseDrillDownOption(entry) {
|
|
453
|
-
return {
|
|
454
|
-
value: String(entry.value ?? ""),
|
|
455
|
-
name: String(entry.name ?? entry.value ?? ""),
|
|
456
|
-
options: parseDrillDownOptions(entry.options) ?? [],
|
|
457
|
-
selected: readBool(entry.selected, false),
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
433
|
function parseOptionalNumber(value, optional, kind) {
|
|
461
434
|
if (value === undefined || value === null || value === "") {
|
|
462
435
|
return null;
|
|
@@ -469,17 +442,7 @@ function parseOptionalNumber(value, optional, kind) {
|
|
|
469
442
|
}
|
|
470
443
|
return n;
|
|
471
444
|
}
|
|
472
|
-
function
|
|
473
|
-
if (!Array.isArray(raw))
|
|
474
|
-
return [];
|
|
475
|
-
const all = [];
|
|
476
|
-
for (const entry of raw) {
|
|
477
|
-
if (!isDict(entry))
|
|
478
|
-
continue;
|
|
479
|
-
const v = parseValidatorDict(entry);
|
|
480
|
-
if (v)
|
|
481
|
-
all.push(v);
|
|
482
|
-
}
|
|
445
|
+
function filterValidators(all, kind) {
|
|
483
446
|
if (kind === "number") {
|
|
484
447
|
return all.filter((v) => v.type === "in_range");
|
|
485
448
|
}
|
|
@@ -492,74 +455,4 @@ function collectValidators(raw, kind) {
|
|
|
492
455
|
// select
|
|
493
456
|
return all.filter((v) => v.type === "no_options");
|
|
494
457
|
}
|
|
495
|
-
function parseValidatorDict(entry) {
|
|
496
|
-
const type = readString(entry.type);
|
|
497
|
-
const negate = readBool(entry.negate, false);
|
|
498
|
-
switch (type) {
|
|
499
|
-
case "in_range":
|
|
500
|
-
return {
|
|
501
|
-
type: "in_range",
|
|
502
|
-
min: readNullableFloat(entry.min),
|
|
503
|
-
max: readNullableFloat(entry.max),
|
|
504
|
-
exclude_min: readBool(entry.exclude_min, false),
|
|
505
|
-
exclude_max: readBool(entry.exclude_max, false),
|
|
506
|
-
negate,
|
|
507
|
-
message: readNullableString(entry.message),
|
|
508
|
-
};
|
|
509
|
-
case "regex":
|
|
510
|
-
return { type: "regex", expression: readString(entry.expression), negate };
|
|
511
|
-
case "length":
|
|
512
|
-
return {
|
|
513
|
-
type: "length",
|
|
514
|
-
min: readNullableInt(entry.min),
|
|
515
|
-
max: readNullableInt(entry.max),
|
|
516
|
-
negate,
|
|
517
|
-
};
|
|
518
|
-
case "expression":
|
|
519
|
-
return { type: "expression", expression: readString(entry.expression), negate };
|
|
520
|
-
case "empty_field":
|
|
521
|
-
return { type: "empty_field", negate };
|
|
522
|
-
case "no_options":
|
|
523
|
-
return { type: "no_options", negate };
|
|
524
|
-
default:
|
|
525
|
-
return null;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
function isDict(v) {
|
|
529
|
-
return v != null && typeof v === "object" && !Array.isArray(v);
|
|
530
|
-
}
|
|
531
|
-
function readString(v) {
|
|
532
|
-
return typeof v === "string" ? v : v == null ? "" : String(v);
|
|
533
|
-
}
|
|
534
|
-
function readNullableString(v) {
|
|
535
|
-
if (v === undefined || v === null)
|
|
536
|
-
return null;
|
|
537
|
-
if (typeof v === "string")
|
|
538
|
-
return v;
|
|
539
|
-
return String(v);
|
|
540
|
-
}
|
|
541
|
-
function readBool(v, fallback) {
|
|
542
|
-
if (typeof v === "boolean")
|
|
543
|
-
return v;
|
|
544
|
-
if (typeof v === "string") {
|
|
545
|
-
const lower = v.toLowerCase();
|
|
546
|
-
if (lower === "true" || lower === "yes" || lower === "1")
|
|
547
|
-
return true;
|
|
548
|
-
if (lower === "false" || lower === "no" || lower === "0")
|
|
549
|
-
return false;
|
|
550
|
-
}
|
|
551
|
-
return fallback;
|
|
552
|
-
}
|
|
553
|
-
function readNullableInt(v) {
|
|
554
|
-
if (v === undefined || v === null || v === "")
|
|
555
|
-
return null;
|
|
556
|
-
const n = parseInt(String(v), 10);
|
|
557
|
-
return Number.isNaN(n) ? null : n;
|
|
558
|
-
}
|
|
559
|
-
function readNullableFloat(v) {
|
|
560
|
-
if (v === undefined || v === null || v === "")
|
|
561
|
-
return null;
|
|
562
|
-
const n = Number(v);
|
|
563
|
-
return Number.isNaN(n) ? null : n;
|
|
564
|
-
}
|
|
565
458
|
//# sourceMappingURL=inputs.js.map
|