@styx-api/core 0.3.0 → 0.4.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.cjs CHANGED
@@ -15,7 +15,7 @@ function isObject$3(x) {
15
15
  function isString$3(x) {
16
16
  return typeof x === "string";
17
17
  }
18
- function isNumber$1(x) {
18
+ function isNumber$2(x) {
19
19
  return typeof x === "number";
20
20
  }
21
21
  function isArray$3(x) {
@@ -100,7 +100,7 @@ var ArgdumpParser = class {
100
100
  const choices = action.choices;
101
101
  if (isArray$3(choices) && choices.length > 0) {
102
102
  const alts = [];
103
- for (const choice of choices) if (isString$3(choice) || isNumber$1(choice)) alts.push({
103
+ for (const choice of choices) if (isString$3(choice) || isNumber$2(choice)) alts.push({
104
104
  kind: "literal",
105
105
  attrs: { str: String(choice) }
106
106
  });
@@ -233,7 +233,7 @@ var ArgdumpParser = class {
233
233
  countMin: 1
234
234
  }
235
235
  };
236
- if (isNumber$1(nargs) && Number.isInteger(nargs) && nargs >= 0) {
236
+ if (isNumber$2(nargs) && Number.isInteger(nargs) && nargs >= 0) {
237
237
  if (nargs === 1) return node;
238
238
  return {
239
239
  kind: "repeat",
@@ -253,7 +253,7 @@ var ArgdumpParser = class {
253
253
  const name = this.preferredName(action) ?? (isString$3(dest) ? dest : void 0);
254
254
  const hasName = name !== void 0;
255
255
  const hasHelp = isString$3(help) && !isSuppressed(help);
256
- const hasDefault = (isString$3(defaultVal) || isNumber$1(defaultVal) || typeof defaultVal === "boolean") && !isSuppressed(defaultVal);
256
+ const hasDefault = (isString$3(defaultVal) || isNumber$2(defaultVal) || typeof defaultVal === "boolean") && !isSuppressed(defaultVal);
257
257
  if (!hasName && !hasHelp && !hasDefault) return void 0;
258
258
  return {
259
259
  ...hasName && { name },
@@ -854,7 +854,7 @@ function isObject$2(x) {
854
854
  function isString$2(x) {
855
855
  return typeof x === "string";
856
856
  }
857
- function isNumber(x) {
857
+ function isNumber$1(x) {
858
858
  return typeof x === "number";
859
859
  }
860
860
  function isArray$2(x) {
@@ -952,7 +952,7 @@ var BoutiquesParser = class {
952
952
  const title = btInput.name;
953
953
  const description = btInput.description;
954
954
  const defaultValue = btInput["default-value"];
955
- const hasDefault = isString$2(defaultValue) || isNumber(defaultValue) || typeof defaultValue === "boolean";
955
+ const hasDefault = isString$2(defaultValue) || isNumber$1(defaultValue) || typeof defaultValue === "boolean";
956
956
  if (!isString$2(name) && !isString$2(title) && !isString$2(description) && !hasDefault) return;
957
957
  return {
958
958
  ...isString$2(name) && { name },
@@ -1076,7 +1076,7 @@ var BoutiquesParser = class {
1076
1076
  kind: "literal",
1077
1077
  attrs: { str: choice }
1078
1078
  });
1079
- else if (isNumber(choice)) alts.push({
1079
+ else if (isNumber$1(choice)) alts.push({
1080
1080
  kind: "literal",
1081
1081
  attrs: { str: String(choice) }
1082
1082
  });
@@ -1113,11 +1113,11 @@ var BoutiquesParser = class {
1113
1113
  kind: "int",
1114
1114
  attrs: {}
1115
1115
  };
1116
- if (isNumber(btInput.minimum)) {
1116
+ if (isNumber$1(btInput.minimum)) {
1117
1117
  node.attrs.minValue = Math.floor(btInput.minimum);
1118
1118
  if (btInput["exclusive-minimum"] === true) node.attrs.minValue += 1;
1119
1119
  }
1120
- if (isNumber(btInput.maximum)) {
1120
+ if (isNumber$1(btInput.maximum)) {
1121
1121
  node.attrs.maxValue = Math.floor(btInput.maximum);
1122
1122
  if (btInput["exclusive-maximum"] === true) node.attrs.maxValue -= 1;
1123
1123
  }
@@ -1129,8 +1129,8 @@ var BoutiquesParser = class {
1129
1129
  kind: "float",
1130
1130
  attrs: {}
1131
1131
  };
1132
- if (isNumber(btInput.minimum)) node.attrs.minValue = btInput.minimum;
1133
- if (isNumber(btInput.maximum)) node.attrs.maxValue = btInput.maximum;
1132
+ if (isNumber$1(btInput.minimum)) node.attrs.minValue = btInput.minimum;
1133
+ if (isNumber$1(btInput.maximum)) node.attrs.maxValue = btInput.maximum;
1134
1134
  if (meta) node.meta = meta;
1135
1135
  return node;
1136
1136
  }
@@ -1235,8 +1235,8 @@ var BoutiquesParser = class {
1235
1235
  attrs: {
1236
1236
  node,
1237
1237
  ...isString$2(btInput["list-separator"]) && { join: btInput["list-separator"] },
1238
- ...isNumber(btInput["min-list-entries"]) && { countMin: btInput["min-list-entries"] },
1239
- ...isNumber(btInput["max-list-entries"]) && { countMax: btInput["max-list-entries"] }
1238
+ ...isNumber$1(btInput["min-list-entries"]) && { countMin: btInput["min-list-entries"] },
1239
+ ...isNumber$1(btInput["max-list-entries"]) && { countMax: btInput["max-list-entries"] }
1240
1240
  }
1241
1241
  };
1242
1242
  }
@@ -1486,6 +1486,9 @@ function isObject$1(x) {
1486
1486
  function isString$1(x) {
1487
1487
  return typeof x === "string";
1488
1488
  }
1489
+ function isNumber(x) {
1490
+ return typeof x === "number" && Number.isFinite(x);
1491
+ }
1489
1492
  function isArray$1(x) {
1490
1493
  return Array.isArray(x);
1491
1494
  }
@@ -1532,9 +1535,10 @@ function emptyExpr$1() {
1532
1535
  * - option, 1 arg -> opt(seq(lit(-switch), value)) (flat optional)
1533
1536
  * - option, >1 arg / multi -> opt|rep(seq(lit(-switch), ...)) (sub-struct)
1534
1537
  *
1535
- * Type mapping mirrors the v1 `mrt2bt.js` converter's `set_type`. The dump does
1536
- * not carry choice values, so a `choice` argument degrades to a plain string
1537
- * (as it did in v1). Per-command quirks v1 hand-coded that the flat dump cannot
1538
+ * Type mapping mirrors the v1 `mrt2bt.js` converter's `set_type`, plus `choice`
1539
+ * values: when the dump carries `choices` it lowers to an enum (an alternative
1540
+ * of literals), else a plain string (older dumps that omit the values - as v1
1541
+ * always did). Per-command quirks v1 hand-coded that the flat dump cannot
1538
1542
  * express (e.g. dwi2fod/mtnormalise paired in/out args) are intentionally NOT
1539
1543
  * special-cased here - they are patched on the niwrap side post-dump, keeping
1540
1544
  * this frontend format-general.
@@ -1617,6 +1621,19 @@ var MrtrixParser = class {
1617
1621
  };
1618
1622
  }
1619
1623
  /**
1624
+ * Integer/float bounds, when the dump carries them. The C++ hook serializes
1625
+ * `Argument::limits.{i,f}.{min,max}` as `min`/`max`, omitting the unbounded
1626
+ * sentinels - so a present value is a real, tool-enforced bound.
1627
+ */
1628
+ numericBounds(arg) {
1629
+ const lo = arg.min;
1630
+ const hi = arg.max;
1631
+ return {
1632
+ ...isNumber(lo) && { minValue: lo },
1633
+ ...isNumber(hi) && { maxValue: hi }
1634
+ };
1635
+ }
1636
+ /**
1620
1637
  * Lower one MRtrix argument to its terminal node (carrying name + doc) and,
1621
1638
  * for output types, an accompanying `Output`.
1622
1639
  */
@@ -1628,11 +1645,31 @@ var MrtrixParser = class {
1628
1645
  }
1629
1646
  const name = meta.name;
1630
1647
  switch (argType) {
1631
- case "integer": return { node: int(meta) };
1632
- case "float": return { node: float(meta) };
1648
+ case "integer": {
1649
+ const node = int(meta);
1650
+ Object.assign(node.attrs, this.numericBounds(arg));
1651
+ return { node };
1652
+ }
1653
+ case "float": {
1654
+ const node = float(meta);
1655
+ Object.assign(node.attrs, this.numericBounds(arg));
1656
+ return { node };
1657
+ }
1633
1658
  case "text":
1634
- case "choice":
1635
- case "undefined": return { node: str(meta) };
1659
+ case "undefined":
1660
+ case "boolean": return { node: str(meta) };
1661
+ case "choice": {
1662
+ const choices = arg.choices;
1663
+ if (isArray$1(choices)) {
1664
+ const alts = choices.filter(isString$1).map((c) => lit(c));
1665
+ if (alts.length > 0) {
1666
+ const node = alt(...alts);
1667
+ node.meta = meta;
1668
+ return { node };
1669
+ }
1670
+ }
1671
+ return { node: str(meta) };
1672
+ }
1636
1673
  case "int seq": {
1637
1674
  const node = repJoin(",", int());
1638
1675
  node.meta = meta;
package/dist/index.mjs CHANGED
@@ -14,7 +14,7 @@ function isObject$3(x) {
14
14
  function isString$3(x) {
15
15
  return typeof x === "string";
16
16
  }
17
- function isNumber$1(x) {
17
+ function isNumber$2(x) {
18
18
  return typeof x === "number";
19
19
  }
20
20
  function isArray$3(x) {
@@ -99,7 +99,7 @@ var ArgdumpParser = class {
99
99
  const choices = action.choices;
100
100
  if (isArray$3(choices) && choices.length > 0) {
101
101
  const alts = [];
102
- for (const choice of choices) if (isString$3(choice) || isNumber$1(choice)) alts.push({
102
+ for (const choice of choices) if (isString$3(choice) || isNumber$2(choice)) alts.push({
103
103
  kind: "literal",
104
104
  attrs: { str: String(choice) }
105
105
  });
@@ -232,7 +232,7 @@ var ArgdumpParser = class {
232
232
  countMin: 1
233
233
  }
234
234
  };
235
- if (isNumber$1(nargs) && Number.isInteger(nargs) && nargs >= 0) {
235
+ if (isNumber$2(nargs) && Number.isInteger(nargs) && nargs >= 0) {
236
236
  if (nargs === 1) return node;
237
237
  return {
238
238
  kind: "repeat",
@@ -252,7 +252,7 @@ var ArgdumpParser = class {
252
252
  const name = this.preferredName(action) ?? (isString$3(dest) ? dest : void 0);
253
253
  const hasName = name !== void 0;
254
254
  const hasHelp = isString$3(help) && !isSuppressed(help);
255
- const hasDefault = (isString$3(defaultVal) || isNumber$1(defaultVal) || typeof defaultVal === "boolean") && !isSuppressed(defaultVal);
255
+ const hasDefault = (isString$3(defaultVal) || isNumber$2(defaultVal) || typeof defaultVal === "boolean") && !isSuppressed(defaultVal);
256
256
  if (!hasName && !hasHelp && !hasDefault) return void 0;
257
257
  return {
258
258
  ...hasName && { name },
@@ -853,7 +853,7 @@ function isObject$2(x) {
853
853
  function isString$2(x) {
854
854
  return typeof x === "string";
855
855
  }
856
- function isNumber(x) {
856
+ function isNumber$1(x) {
857
857
  return typeof x === "number";
858
858
  }
859
859
  function isArray$2(x) {
@@ -951,7 +951,7 @@ var BoutiquesParser = class {
951
951
  const title = btInput.name;
952
952
  const description = btInput.description;
953
953
  const defaultValue = btInput["default-value"];
954
- const hasDefault = isString$2(defaultValue) || isNumber(defaultValue) || typeof defaultValue === "boolean";
954
+ const hasDefault = isString$2(defaultValue) || isNumber$1(defaultValue) || typeof defaultValue === "boolean";
955
955
  if (!isString$2(name) && !isString$2(title) && !isString$2(description) && !hasDefault) return;
956
956
  return {
957
957
  ...isString$2(name) && { name },
@@ -1075,7 +1075,7 @@ var BoutiquesParser = class {
1075
1075
  kind: "literal",
1076
1076
  attrs: { str: choice }
1077
1077
  });
1078
- else if (isNumber(choice)) alts.push({
1078
+ else if (isNumber$1(choice)) alts.push({
1079
1079
  kind: "literal",
1080
1080
  attrs: { str: String(choice) }
1081
1081
  });
@@ -1112,11 +1112,11 @@ var BoutiquesParser = class {
1112
1112
  kind: "int",
1113
1113
  attrs: {}
1114
1114
  };
1115
- if (isNumber(btInput.minimum)) {
1115
+ if (isNumber$1(btInput.minimum)) {
1116
1116
  node.attrs.minValue = Math.floor(btInput.minimum);
1117
1117
  if (btInput["exclusive-minimum"] === true) node.attrs.minValue += 1;
1118
1118
  }
1119
- if (isNumber(btInput.maximum)) {
1119
+ if (isNumber$1(btInput.maximum)) {
1120
1120
  node.attrs.maxValue = Math.floor(btInput.maximum);
1121
1121
  if (btInput["exclusive-maximum"] === true) node.attrs.maxValue -= 1;
1122
1122
  }
@@ -1128,8 +1128,8 @@ var BoutiquesParser = class {
1128
1128
  kind: "float",
1129
1129
  attrs: {}
1130
1130
  };
1131
- if (isNumber(btInput.minimum)) node.attrs.minValue = btInput.minimum;
1132
- if (isNumber(btInput.maximum)) node.attrs.maxValue = btInput.maximum;
1131
+ if (isNumber$1(btInput.minimum)) node.attrs.minValue = btInput.minimum;
1132
+ if (isNumber$1(btInput.maximum)) node.attrs.maxValue = btInput.maximum;
1133
1133
  if (meta) node.meta = meta;
1134
1134
  return node;
1135
1135
  }
@@ -1234,8 +1234,8 @@ var BoutiquesParser = class {
1234
1234
  attrs: {
1235
1235
  node,
1236
1236
  ...isString$2(btInput["list-separator"]) && { join: btInput["list-separator"] },
1237
- ...isNumber(btInput["min-list-entries"]) && { countMin: btInput["min-list-entries"] },
1238
- ...isNumber(btInput["max-list-entries"]) && { countMax: btInput["max-list-entries"] }
1237
+ ...isNumber$1(btInput["min-list-entries"]) && { countMin: btInput["min-list-entries"] },
1238
+ ...isNumber$1(btInput["max-list-entries"]) && { countMax: btInput["max-list-entries"] }
1239
1239
  }
1240
1240
  };
1241
1241
  }
@@ -1485,6 +1485,9 @@ function isObject$1(x) {
1485
1485
  function isString$1(x) {
1486
1486
  return typeof x === "string";
1487
1487
  }
1488
+ function isNumber(x) {
1489
+ return typeof x === "number" && Number.isFinite(x);
1490
+ }
1488
1491
  function isArray$1(x) {
1489
1492
  return Array.isArray(x);
1490
1493
  }
@@ -1531,9 +1534,10 @@ function emptyExpr$1() {
1531
1534
  * - option, 1 arg -> opt(seq(lit(-switch), value)) (flat optional)
1532
1535
  * - option, >1 arg / multi -> opt|rep(seq(lit(-switch), ...)) (sub-struct)
1533
1536
  *
1534
- * Type mapping mirrors the v1 `mrt2bt.js` converter's `set_type`. The dump does
1535
- * not carry choice values, so a `choice` argument degrades to a plain string
1536
- * (as it did in v1). Per-command quirks v1 hand-coded that the flat dump cannot
1537
+ * Type mapping mirrors the v1 `mrt2bt.js` converter's `set_type`, plus `choice`
1538
+ * values: when the dump carries `choices` it lowers to an enum (an alternative
1539
+ * of literals), else a plain string (older dumps that omit the values - as v1
1540
+ * always did). Per-command quirks v1 hand-coded that the flat dump cannot
1537
1541
  * express (e.g. dwi2fod/mtnormalise paired in/out args) are intentionally NOT
1538
1542
  * special-cased here - they are patched on the niwrap side post-dump, keeping
1539
1543
  * this frontend format-general.
@@ -1616,6 +1620,19 @@ var MrtrixParser = class {
1616
1620
  };
1617
1621
  }
1618
1622
  /**
1623
+ * Integer/float bounds, when the dump carries them. The C++ hook serializes
1624
+ * `Argument::limits.{i,f}.{min,max}` as `min`/`max`, omitting the unbounded
1625
+ * sentinels - so a present value is a real, tool-enforced bound.
1626
+ */
1627
+ numericBounds(arg) {
1628
+ const lo = arg.min;
1629
+ const hi = arg.max;
1630
+ return {
1631
+ ...isNumber(lo) && { minValue: lo },
1632
+ ...isNumber(hi) && { maxValue: hi }
1633
+ };
1634
+ }
1635
+ /**
1619
1636
  * Lower one MRtrix argument to its terminal node (carrying name + doc) and,
1620
1637
  * for output types, an accompanying `Output`.
1621
1638
  */
@@ -1627,11 +1644,31 @@ var MrtrixParser = class {
1627
1644
  }
1628
1645
  const name = meta.name;
1629
1646
  switch (argType) {
1630
- case "integer": return { node: int(meta) };
1631
- case "float": return { node: float(meta) };
1647
+ case "integer": {
1648
+ const node = int(meta);
1649
+ Object.assign(node.attrs, this.numericBounds(arg));
1650
+ return { node };
1651
+ }
1652
+ case "float": {
1653
+ const node = float(meta);
1654
+ Object.assign(node.attrs, this.numericBounds(arg));
1655
+ return { node };
1656
+ }
1632
1657
  case "text":
1633
- case "choice":
1634
- case "undefined": return { node: str(meta) };
1658
+ case "undefined":
1659
+ case "boolean": return { node: str(meta) };
1660
+ case "choice": {
1661
+ const choices = arg.choices;
1662
+ if (isArray$1(choices)) {
1663
+ const alts = choices.filter(isString$1).map((c) => lit(c));
1664
+ if (alts.length > 0) {
1665
+ const node = alt(...alts);
1666
+ node.meta = meta;
1667
+ return { node };
1668
+ }
1669
+ }
1670
+ return { node: str(meta) };
1671
+ }
1635
1672
  case "int seq": {
1636
1673
  const node = repJoin(",", int());
1637
1674
  node.meta = meta;