@nodegx/preview 0.2.8 → 0.2.9

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.
@@ -4936,7 +4936,7 @@ var require_lib3 = __commonJS({
4936
4936
  return this.resolve([]);
4937
4937
  }
4938
4938
  var values2 = new Array(len);
4939
- var resolved2 = 0;
4939
+ var resolved3 = 0;
4940
4940
  var i2 = -1;
4941
4941
  var promise = new this(INTERNAL);
4942
4942
  while (++i2 < len) {
@@ -4952,7 +4952,7 @@ var require_lib3 = __commonJS({
4952
4952
  });
4953
4953
  function resolveFromAll(outValue) {
4954
4954
  values2[i3] = outValue;
4955
- if (++resolved2 === len && !called) {
4955
+ if (++resolved3 === len && !called) {
4956
4956
  called = true;
4957
4957
  handlers.resolve(promise, values2);
4958
4958
  }
@@ -6222,15 +6222,15 @@ var require_crc32 = __commonJS({
6222
6222
  "use strict";
6223
6223
  var utils = require_utils3();
6224
6224
  function makeTable() {
6225
- var c, table = [];
6225
+ var c, table2 = [];
6226
6226
  for (var n = 0; n < 256; n++) {
6227
6227
  c = n;
6228
6228
  for (var k = 0; k < 8; k++) {
6229
6229
  c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
6230
6230
  }
6231
- table[n] = c;
6231
+ table2[n] = c;
6232
6232
  }
6233
- return table;
6233
+ return table2;
6234
6234
  }
6235
6235
  var crcTable = makeTable();
6236
6236
  function crc32(crc, buf, len, pos) {
@@ -7228,15 +7228,15 @@ var require_crc322 = __commonJS({
7228
7228
  "../../node_modules/pako/lib/zlib/crc32.js"(exports2, module2) {
7229
7229
  "use strict";
7230
7230
  function makeTable() {
7231
- var c, table = [];
7231
+ var c, table2 = [];
7232
7232
  for (var n = 0; n < 256; n++) {
7233
7233
  c = n;
7234
7234
  for (var k = 0; k < 8; k++) {
7235
7235
  c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
7236
7236
  }
7237
- table[n] = c;
7237
+ table2[n] = c;
7238
7238
  }
7239
- return table;
7239
+ return table2;
7240
7240
  }
7241
7241
  var crcTable = makeTable();
7242
7242
  function crc32(crc, buf, len, pos) {
@@ -9030,7 +9030,7 @@ var require_inftrees = __commonJS({
9030
9030
  64,
9031
9031
  64
9032
9032
  ];
9033
- module2.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) {
9033
+ module2.exports = function inflate_table(type, lens, lens_index, codes, table2, table_index, work, opts) {
9034
9034
  var bits = opts.bits;
9035
9035
  var len = 0;
9036
9036
  var sym = 0;
@@ -9070,8 +9070,8 @@ var require_inftrees = __commonJS({
9070
9070
  root2 = max2;
9071
9071
  }
9072
9072
  if (max2 === 0) {
9073
- table[table_index++] = 1 << 24 | 64 << 16 | 0;
9074
- table[table_index++] = 1 << 24 | 64 << 16 | 0;
9073
+ table2[table_index++] = 1 << 24 | 64 << 16 | 0;
9074
+ table2[table_index++] = 1 << 24 | 64 << 16 | 0;
9075
9075
  opts.bits = 1;
9076
9076
  return 0;
9077
9077
  }
@@ -9146,7 +9146,7 @@ var require_inftrees = __commonJS({
9146
9146
  min2 = fill;
9147
9147
  do {
9148
9148
  fill -= incr;
9149
- table[next + (huff >> drop2) + fill] = here_bits << 24 | here_op << 16 | here_val | 0;
9149
+ table2[next + (huff >> drop2) + fill] = here_bits << 24 | here_op << 16 | here_val | 0;
9150
9150
  } while (fill !== 0);
9151
9151
  incr = 1 << len - 1;
9152
9152
  while (huff & incr) {
@@ -9185,11 +9185,11 @@ var require_inftrees = __commonJS({
9185
9185
  return 1;
9186
9186
  }
9187
9187
  low = huff & mask;
9188
- table[low] = root2 << 24 | curr << 16 | next - table_index | 0;
9188
+ table2[low] = root2 << 24 | curr << 16 | next - table_index | 0;
9189
9189
  }
9190
9190
  }
9191
9191
  if (huff !== 0) {
9192
- table[next + huff] = len - drop2 << 24 | 64 << 16 | 0;
9192
+ table2[next + huff] = len - drop2 << 24 | 64 << 16 | 0;
9193
9193
  }
9194
9194
  opts.bits = root2;
9195
9195
  return 0;
@@ -9236,7 +9236,7 @@ var require_inflate = __commonJS({
9236
9236
  var STORED = 14;
9237
9237
  var COPY_ = 15;
9238
9238
  var COPY = 16;
9239
- var TABLE2 = 17;
9239
+ var TABLE3 = 17;
9240
9240
  var LENLENS = 18;
9241
9241
  var CODELENS = 19;
9242
9242
  var LEN_ = 20;
@@ -9824,7 +9824,7 @@ var require_inflate = __commonJS({
9824
9824
  }
9825
9825
  break;
9826
9826
  case 2:
9827
- state2.mode = TABLE2;
9827
+ state2.mode = TABLE3;
9828
9828
  break;
9829
9829
  case 3:
9830
9830
  strm.msg = "invalid block type";
@@ -9882,7 +9882,7 @@ var require_inflate = __commonJS({
9882
9882
  }
9883
9883
  state2.mode = TYPE;
9884
9884
  break;
9885
- case TABLE2:
9885
+ case TABLE3:
9886
9886
  while (bits < 14) {
9887
9887
  if (have === 0) {
9888
9888
  break inf_leave;
@@ -18973,8 +18973,21 @@ var require_node2 = __commonJS({
18973
18973
  const scope = this.nodeScope;
18974
18974
  const runContext = scope && scope.runContext;
18975
18975
  if (!runContext || !runContext.beginStep || !runContext.endStep) return;
18976
- const step = runContext.beginStep({ nodeId: this.id, nodeType: this.name });
18977
- if (step !== void 0 && step !== null) runContext.endStep(step, { status: "failure", code, message, detail });
18976
+ const recordValues = !!runContext.recordValues;
18977
+ const step = runContext.beginStep({
18978
+ nodeId: this.id,
18979
+ nodeType: this.name,
18980
+ ...recordValues ? { inputs: snapshotInputValues(this) } : {}
18981
+ });
18982
+ if (step !== void 0 && step !== null) {
18983
+ runContext.endStep(step, {
18984
+ status: "failure",
18985
+ code,
18986
+ message,
18987
+ detail,
18988
+ ...recordValues ? { outputs: snapshotOutputValues(this) } : {}
18989
+ });
18990
+ }
18978
18991
  };
18979
18992
  Node17.prototype.setDiagnostic = function(key, message) {
18980
18993
  setDiagnostic(this, key, message);
@@ -18984,6 +18997,47 @@ var require_node2 = __commonJS({
18984
18997
  return diagnosticsEnabled(this);
18985
18998
  }
18986
18999
  });
19000
+ function isSignalPortType(type) {
19001
+ if (type === "signal") return true;
19002
+ return !!type && typeof type === "object" && type.name === "signal";
19003
+ }
19004
+ function snapshotInputValues(node) {
19005
+ const out = {};
19006
+ const values2 = node._inputValues || {};
19007
+ const inputs = node._inputs || {};
19008
+ let declared2 = {};
19009
+ try {
19010
+ const register = node.context && node.context.nodeRegister;
19011
+ if (register && register.hasNode(node.name)) declared2 = register.getNodeMetadata(node.name).inputs || {};
19012
+ } catch (e) {
19013
+ }
19014
+ for (const name2 of Object.keys(values2)) {
19015
+ const value2 = values2[name2];
19016
+ if (value2 === void 0 || typeof value2 === "function") continue;
19017
+ const port = inputs[name2];
19018
+ if (port && isSignalPortType(port.type)) continue;
19019
+ const meta = declared2[name2];
19020
+ if (meta && isSignalPortType(meta.type)) continue;
19021
+ out[name2] = value2;
19022
+ }
19023
+ return out;
19024
+ }
19025
+ function snapshotOutputValues(node) {
19026
+ const out = {};
19027
+ const list = node._outputList || [];
19028
+ for (const port of list) {
19029
+ if (!port || isSignalPortType(port.type)) continue;
19030
+ let value2;
19031
+ try {
19032
+ value2 = port.value;
19033
+ } catch (e) {
19034
+ continue;
19035
+ }
19036
+ if (value2 === void 0 || typeof value2 === "function") continue;
19037
+ out[port.name] = value2;
19038
+ }
19039
+ return out;
19040
+ }
18987
19041
  Node17.prototype.beginOutcome = function(inputData) {
18988
19042
  const token = { reported: void 0 };
18989
19043
  const cause = currentTraceCause(this.context);
@@ -18991,7 +19045,13 @@ var require_node2 = __commonJS({
18991
19045
  const scope = this.nodeScope;
18992
19046
  const runContext = scope && scope.runContext;
18993
19047
  if (runContext && runContext.beginStep) {
18994
- token.step = runContext.beginStep({ nodeId: this.id, nodeType: this.name, inputData });
19048
+ token.step = runContext.beginStep({
19049
+ nodeId: this.id,
19050
+ nodeType: this.name,
19051
+ inputData,
19052
+ // P123-STU-FNRUNVALUES — opt-in; absent, the step object is exactly what it always was.
19053
+ ...runContext.recordValues ? { inputs: snapshotInputValues(this) } : {}
19054
+ });
18995
19055
  }
18996
19056
  return token;
18997
19057
  };
@@ -19070,7 +19130,10 @@ var require_node2 = __commonJS({
19070
19130
  message: options && options.message,
19071
19131
  // The subject of the failure, for a record whose steps are all called `http`. See
19072
19132
  // `RuntimeStepEnd.detail` — the node already composes this for the error bus.
19073
- detail: options && options.detail
19133
+ detail: options && options.detail,
19134
+ // P123-STU-FNRUNVALUES — read now, after the signals: "the outcome is the last thing an
19135
+ // action does", so every value it produced is already on its ports.
19136
+ ...runContext.recordValues ? { outputs: snapshotOutputValues(this) } : {}
19074
19137
  });
19075
19138
  }
19076
19139
  }
@@ -24604,9 +24667,704 @@ var require_runtasks = __commonJS({
24604
24667
  }
24605
24668
  });
24606
24669
 
24670
+ // ../noodl-runtime/src/utils.ts
24671
+ var utils_exports = {};
24672
+ __export(utils_exports, {
24673
+ getAbsoluteUrl: () => getAbsoluteUrl,
24674
+ logJavaScriptNodeError: () => logJavaScriptNodeError,
24675
+ thrownMessage: () => thrownMessage
24676
+ });
24677
+ function getAbsoluteUrl(_url) {
24678
+ const url = String(_url);
24679
+ if (!url || url[0] === "/" || url.includes("://") || url.startsWith("data:")) {
24680
+ return url;
24681
+ }
24682
+ return (Noodl.baseUrl || "/") + url;
24683
+ }
24684
+ function thrownMessage(error) {
24685
+ if (error && error.message) return String(error.message);
24686
+ try {
24687
+ return String(error);
24688
+ } catch {
24689
+ return typeof error;
24690
+ }
24691
+ }
24692
+ function logJavaScriptNodeError(error) {
24693
+ const prefix = "Error in JS node run code.";
24694
+ if (error === null || typeof error !== "object" && typeof error !== "function") {
24695
+ console.log(prefix, thrownMessage(error));
24696
+ return;
24697
+ }
24698
+ const proto = Object.getPrototypeOf(error);
24699
+ const kind = proto && proto.constructor && proto.constructor.name ? proto.constructor.name : "Error";
24700
+ console.log(prefix, kind + ": " + thrownMessage(error), error.stack);
24701
+ }
24702
+ var init_utils = __esm({
24703
+ "../noodl-runtime/src/utils.ts"() {
24704
+ }
24705
+ });
24706
+
24707
+ // ../noodl-runtime/src/componentwalk.ts
24708
+ var componentwalk_exports = {};
24709
+ __export(componentwalk_exports, {
24710
+ COMPONENT_OBJECT_TYPES: () => COMPONENT_OBJECT_TYPES,
24711
+ componentAncestorNames: () => componentAncestorNames,
24712
+ componentAncestors: () => componentAncestors,
24713
+ findAncestorWithComponentObject: () => findAncestorWithComponentObject,
24714
+ findAncestorWithName: () => findAncestorWithName,
24715
+ findAncestorWithNodeType: () => findAncestorWithNodeType,
24716
+ findAncestorWithProperty: () => findAncestorWithProperty,
24717
+ findComponentAncestor: () => findComponentAncestor,
24718
+ parentComponentOf: () => parentComponentOf,
24719
+ scopeChain: () => scopeChain,
24720
+ scopeChainNames: () => scopeChainNames
24721
+ });
24722
+ function parentComponentOf(component) {
24723
+ if (!component) return void 0;
24724
+ let parent;
24725
+ if (component.getRoots().length > 0) {
24726
+ const root2 = component.getRoots()[0];
24727
+ if (root2.getVisualParentNode) {
24728
+ const visualParent = root2.getVisualParentNode();
24729
+ if (visualParent) {
24730
+ parent = visualParent.nodeScope.componentOwner;
24731
+ }
24732
+ } else if (root2.parentNodeScope) {
24733
+ parent = component.parentNodeScope.componentOwner;
24734
+ }
24735
+ } else if (component.parentNodeScope) {
24736
+ parent = component.parentNodeScope.componentOwner;
24737
+ }
24738
+ if (parent && parent.nodeScope && parent.nodeScope.componentOwner !== component) {
24739
+ return parent;
24740
+ }
24741
+ return void 0;
24742
+ }
24743
+ function componentAncestors(component) {
24744
+ const ancestors = [];
24745
+ let current = component;
24746
+ for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
24747
+ const parent = parentComponentOf(current);
24748
+ if (!parent) break;
24749
+ ancestors.push(parent);
24750
+ current = parent;
24751
+ }
24752
+ return ancestors;
24753
+ }
24754
+ function findComponentAncestor(component, predicate) {
24755
+ let current = component;
24756
+ for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
24757
+ const parent = parentComponentOf(current);
24758
+ if (!parent) return void 0;
24759
+ if (predicate(parent)) return parent;
24760
+ current = parent;
24761
+ }
24762
+ return void 0;
24763
+ }
24764
+ function findAncestorWithNodeType(component, types) {
24765
+ return findComponentAncestor(
24766
+ component,
24767
+ (candidate) => types.some((type) => candidate.nodeScope.getNodesWithType(type).length > 0)
24768
+ );
24769
+ }
24770
+ function findAncestorWithComponentObject(component) {
24771
+ return findAncestorWithNodeType(component, COMPONENT_OBJECT_TYPES);
24772
+ }
24773
+ function findAncestorWithName(component, name2) {
24774
+ return findComponentAncestor(component, (candidate) => candidate.name === name2);
24775
+ }
24776
+ function scopeChain(component) {
24777
+ const chain2 = [];
24778
+ let current = component;
24779
+ for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
24780
+ if (!current) break;
24781
+ chain2.push(current);
24782
+ if (!current.parentNodeScope) break;
24783
+ current = current.parentNodeScope.componentOwner;
24784
+ }
24785
+ return chain2;
24786
+ }
24787
+ function scopeChainNames(component) {
24788
+ return scopeChain(component).map((entry) => entry.name);
24789
+ }
24790
+ function findAncestorWithProperty(component, property2) {
24791
+ const chain2 = scopeChain(component);
24792
+ for (let i2 = 0; i2 < chain2.length; i2++) {
24793
+ if (chain2[i2][property2] !== void 0) return chain2[i2];
24794
+ }
24795
+ return void 0;
24796
+ }
24797
+ function componentAncestorNames(component) {
24798
+ return componentAncestors(component).map((ancestor) => ancestor.name);
24799
+ }
24800
+ var MAX_WALK_DEPTH, COMPONENT_OBJECT_TYPES;
24801
+ var init_componentwalk = __esm({
24802
+ "../noodl-runtime/src/componentwalk.ts"() {
24803
+ "use strict";
24804
+ MAX_WALK_DEPTH = 1e3;
24805
+ COMPONENT_OBJECT_TYPES = ["net.noodl.ComponentObject", "Component State"];
24806
+ }
24807
+ });
24808
+
24809
+ // ../noodl-runtime/src/resolvedtarget.ts
24810
+ function summariseTargets(labels) {
24811
+ const distinct = [];
24812
+ for (let i2 = 0; i2 < labels.length; i2++) {
24813
+ const label = labels[i2];
24814
+ if (label === void 0) continue;
24815
+ if (distinct.indexOf(label) === -1) distinct.push(label);
24816
+ }
24817
+ if (distinct.length === 0) return void 0;
24818
+ if (distinct.length === 1) return "\u2192 " + distinct[0];
24819
+ const listed = distinct.slice(0, MAX_NAMES_LISTED).join(", ");
24820
+ const rest2 = distinct.length - MAX_NAMES_LISTED;
24821
+ return "\u2192 " + distinct.length + " targets: " + listed + (rest2 > 0 ? ", +" + rest2 : "");
24822
+ }
24823
+ var MAX_NAMES_LISTED, ResolvedTargetReporter;
24824
+ var init_resolvedtarget = __esm({
24825
+ "../noodl-runtime/src/resolvedtarget.ts"() {
24826
+ "use strict";
24827
+ MAX_NAMES_LISTED = 3;
24828
+ ResolvedTargetReporter = class {
24829
+ constructor() {
24830
+ /** Weak, so a torn-down runtime's bookkeeping goes with it and needs no reset call. */
24831
+ this._byContext = /* @__PURE__ */ new WeakMap();
24832
+ }
24833
+ /**
24834
+ * Record what `node` bound to and push the summary to the editor.
24835
+ *
24836
+ * Safe to call every resolution; identical summaries are dropped rather than sent, so a
24837
+ * node that re-resolves each frame costs one string comparison.
24838
+ */
24839
+ report(node, target) {
24840
+ const state2 = this._stateFor(node);
24841
+ if (!state2) return;
24842
+ let instances = state2.byGraphNode.get(node.id);
24843
+ if (!instances) {
24844
+ instances = /* @__PURE__ */ new Map();
24845
+ state2.byGraphNode.set(node.id, instances);
24846
+ }
24847
+ instances.set(node, target);
24848
+ this._flush(node, state2, instances);
24849
+ }
24850
+ /** Drop an instance. Call from `_onNodeDeleted`, or this map is a leak. */
24851
+ forget(node) {
24852
+ const state2 = this._stateFor(node);
24853
+ if (!state2) return;
24854
+ const instances = state2.byGraphNode.get(node.id);
24855
+ if (!instances) return;
24856
+ instances.delete(node);
24857
+ if (instances.size === 0) {
24858
+ state2.byGraphNode.delete(node.id);
24859
+ state2.lastSent.delete(node.id);
24860
+ return;
24861
+ }
24862
+ this._flush(node, state2, instances);
24863
+ }
24864
+ _stateFor(node) {
24865
+ const context = node.context;
24866
+ if (!context) return void 0;
24867
+ let state2 = this._byContext.get(context);
24868
+ if (!state2) {
24869
+ state2 = { byGraphNode: /* @__PURE__ */ new Map(), lastSent: /* @__PURE__ */ new Map() };
24870
+ this._byContext.set(context, state2);
24871
+ }
24872
+ return state2;
24873
+ }
24874
+ _flush(node, state2, instances) {
24875
+ const labels = [];
24876
+ instances.forEach((label) => labels.push(label));
24877
+ const summary = summariseTargets(labels);
24878
+ if (state2.lastSent.has(node.id) && state2.lastSent.get(node.id) === summary) return;
24879
+ state2.lastSent.set(node.id, summary);
24880
+ const editorConnection = node.context && node.context.editorConnection;
24881
+ if (!editorConnection || !editorConnection.isRunningLocally()) return;
24882
+ if (typeof editorConnection.sendNodeSubLabel !== "function") return;
24883
+ editorConnection.sendNodeSubLabel(node.id, summary);
24884
+ }
24885
+ };
24886
+ }
24887
+ });
24888
+
24889
+ // ../noodl-runtime/src/foreachitem.ts
24890
+ var foreachitem_exports = {};
24891
+ __export(foreachitem_exports, {
24892
+ forgetForEachItem: () => forgetForEachItem,
24893
+ resolveForEachItem: () => resolveForEachItem
24894
+ });
24895
+ function resolveForEachItem(node, options = {}) {
24896
+ const chain2 = scopeChain(node.nodeScope.componentOwner);
24897
+ const wanted = options.target;
24898
+ if (wanted) {
24899
+ const named3 = firstNamed(chain2, wanted);
24900
+ if (!named3) {
24901
+ return miss(
24902
+ node,
24903
+ "repeater-item/target-not-found",
24904
+ 'No component named "' + wanted + '" contains this node',
24905
+ wanted,
24906
+ { target: wanted, scope: scopeChainNames(node.nodeScope.componentOwner) }
24907
+ );
24908
+ }
24909
+ if (named3[FOR_EACH_MODEL] === void 0) {
24910
+ return miss(
24911
+ node,
24912
+ "repeater-item/target-has-no-item",
24913
+ 'The component "' + wanted + '" has no current item \u2014 it is not used as a Repeater or Run Tasks template',
24914
+ wanted,
24915
+ { target: wanted }
24916
+ );
24917
+ }
24918
+ return hit(node, named3);
24919
+ }
24920
+ const owner = firstWithItem(chain2);
24921
+ if (!owner) {
24922
+ return miss(
24923
+ node,
24924
+ "repeater-item/no-item-in-scope",
24925
+ 'Id Source is set to "From repeater", but this node is not inside a Repeater or Run Tasks template',
24926
+ void 0,
24927
+ { scope: scopeChainNames(node.nodeScope.componentOwner) }
24928
+ );
24929
+ }
24930
+ return hit(node, owner);
24931
+ }
24932
+ function forgetForEachItem(node) {
24933
+ resolvedTargets.forget(node);
24934
+ lastMissByNode.delete(node);
24935
+ }
24936
+ function firstNamed(chain2, name2) {
24937
+ for (let i2 = 0; i2 < chain2.length; i2++) {
24938
+ if (chain2[i2].name === name2) return chain2[i2];
24939
+ }
24940
+ return void 0;
24941
+ }
24942
+ function firstWithItem(chain2) {
24943
+ for (let i2 = 0; i2 < chain2.length; i2++) {
24944
+ if (chain2[i2][FOR_EACH_MODEL] !== void 0) return chain2[i2];
24945
+ }
24946
+ return void 0;
24947
+ }
24948
+ function hit(node, owner) {
24949
+ lastMissByNode.delete(node);
24950
+ resolvedTargets.report(node, owner.name);
24951
+ return owner[FOR_EACH_MODEL];
24952
+ }
24953
+ function miss(node, code, message, target, detail) {
24954
+ resolvedTargets.report(node, void 0);
24955
+ const seen = code + "|" + (target || "");
24956
+ if (lastMissByNode.get(node) !== seen) {
24957
+ lastMissByNode.set(node, seen);
24958
+ node.raiseRuntimeError(code, message, detail);
24959
+ }
24960
+ return void 0;
24961
+ }
24962
+ var FOR_EACH_MODEL, resolvedTargets, lastMissByNode;
24963
+ var init_foreachitem = __esm({
24964
+ "../noodl-runtime/src/foreachitem.ts"() {
24965
+ "use strict";
24966
+ init_componentwalk();
24967
+ init_resolvedtarget();
24968
+ FOR_EACH_MODEL = "_forEachModel";
24969
+ resolvedTargets = new ResolvedTargetReporter();
24970
+ lastMissByNode = /* @__PURE__ */ new WeakMap();
24971
+ }
24972
+ });
24973
+
24974
+ // ../noodl-runtime/src/javascriptnodeparser.js
24975
+ var require_javascriptnodeparser = __commonJS({
24976
+ "../noodl-runtime/src/javascriptnodeparser.js"(exports2, module2) {
24977
+ "use strict";
24978
+ var Model27 = require_model2();
24979
+ var { getAbsoluteUrl: getAbsoluteUrl2 } = (init_utils(), __toCommonJS(utils_exports));
24980
+ var { findAncestorWithComponentObject: findAncestorWithComponentObject2 } = (init_componentwalk(), __toCommonJS(componentwalk_exports));
24981
+ var { resolveForEachItem: resolveForEachItem2 } = (init_foreachitem(), __toCommonJS(foreachitem_exports));
24982
+ var userFunctionsCache = {};
24983
+ function JavascriptNodeParser4(code, options) {
24984
+ this.inputs = {};
24985
+ this.outputs = {};
24986
+ this.error = void 0;
24987
+ this.code = code;
24988
+ const node = options ? options.node : void 0;
24989
+ this._initializeAPIs();
24990
+ var userCode = userFunctionsCache[code];
24991
+ if (!userCode) {
24992
+ try {
24993
+ userCode = new Function(["define", "script", "Node", "Component"], JavascriptNodeParser4.getCodePrefix() + code);
24994
+ userFunctionsCache[code] = userCode;
24995
+ } catch (e) {
24996
+ this.error = e.message;
24997
+ console.error(e);
24998
+ }
24999
+ }
25000
+ if (userCode) {
25001
+ try {
25002
+ userCode(
25003
+ this.define.bind(this),
25004
+ this.script.bind(this),
25005
+ this.apis.Node,
25006
+ node ? JavascriptNodeParser4.getComponentScopeForNode(node) : {}
25007
+ );
25008
+ this._afterSourced();
25009
+ } catch (e) {
25010
+ this.error = e.message;
25011
+ console.error(e);
25012
+ }
25013
+ }
25014
+ }
25015
+ JavascriptNodeParser4.prototype.define = function(userObject) {
25016
+ this.inputs = userObject.inputs || {};
25017
+ this.outputs = userObject.outputs || {};
25018
+ this.setup = userObject.setup;
25019
+ this.change = userObject.run || userObject.change;
25020
+ this.destroy = userObject.destroy;
25021
+ this.definedObject = userObject;
25022
+ };
25023
+ function _scriptExtend(_this) {
25024
+ var _extended = {
25025
+ inputs: _this.inputs || {},
25026
+ outputs: _this.outputs || {},
25027
+ setup: function(inputs, outputs) {
25028
+ this.inputs = inputs;
25029
+ this.outputs = outputs;
25030
+ this.setOutputs = function(states) {
25031
+ for (var key3 in states) {
25032
+ this.outputs[key3] = states[key3];
25033
+ this.flagOutputDirty(key3);
25034
+ }
25035
+ };
25036
+ if (_this.methods) {
25037
+ for (var key2 in _this.methods) {
25038
+ this[key2] = _this.methods[key2];
25039
+ }
25040
+ }
25041
+ _this.setup && _this.setup.apply(this);
25042
+ },
25043
+ destroy: function(inputs, outputs) {
25044
+ this.inputs = inputs;
25045
+ this.outputs = outputs;
25046
+ _this.destroy && _this.destroy.apply(this);
25047
+ },
25048
+ change: function(inputs, outputs) {
25049
+ this.inputs = inputs;
25050
+ this.outputs = outputs;
25051
+ var old = this._oldInputs || {};
25052
+ if (_this.changed) {
25053
+ for (var key2 in inputs) {
25054
+ if (inputs[key2] !== old[key2]) {
25055
+ var changedFunction = _this.changed[key2];
25056
+ if (typeof changedFunction === "function") changedFunction.apply(this, [inputs[key2], old[key2]]);
25057
+ }
25058
+ }
25059
+ }
25060
+ this._oldInputs = Object.assign({}, inputs);
25061
+ }
25062
+ };
25063
+ if (_this.signals) {
25064
+ for (var key in _this.signals) {
25065
+ _extended[key] = _this.signals[key];
25066
+ _extended.inputs[key] = "signal";
25067
+ }
25068
+ }
25069
+ return _extended;
25070
+ }
25071
+ JavascriptNodeParser4.prototype.script = function(userObject) {
25072
+ var _userObjectExtended = _scriptExtend(userObject);
25073
+ this.inputs = _userObjectExtended.inputs || {};
25074
+ this.outputs = _userObjectExtended.outputs || {};
25075
+ this.setup = _userObjectExtended.setup;
25076
+ this.change = _userObjectExtended.run || _userObjectExtended.change;
25077
+ this.destroy = _userObjectExtended.destroy;
25078
+ this.definedObject = _userObjectExtended;
25079
+ };
25080
+ JavascriptNodeParser4.prototype._initializeAPIs = function() {
25081
+ this.apis = {
25082
+ Node: {
25083
+ Inputs: {},
25084
+ Outputs: {},
25085
+ Signals: {},
25086
+ Setters: {}
25087
+ }
25088
+ };
25089
+ };
25090
+ JavascriptNodeParser4.prototype._afterSourced = function() {
25091
+ if (this.definedObject !== void 0) return;
25092
+ var _Node = this.apis.Node;
25093
+ this.inputs = Object.assign({}, _Node.Inputs || {});
25094
+ this.outputs = Object.assign({}, _Node.Outputs || {});
25095
+ this.setup = function(inputs, outputs) {
25096
+ const _this = this;
25097
+ _Node.setOutputs = function(_outputs) {
25098
+ for (var key2 in _outputs) {
25099
+ outputs[key2] = _outputs[key2];
25100
+ _this.flagOutputDirty(key2);
25101
+ }
25102
+ };
25103
+ _Node.OnInit && _Node.OnInit.apply(this);
25104
+ };
25105
+ this.destroy = _Node.OnDestroy || this.destory;
25106
+ this.change = (inputs, outputs, changedInputs) => {
25107
+ for (var key2 in changedInputs) {
25108
+ if (typeof _Node.Setters[key2] === "function") {
25109
+ _Node.Setters[key2](inputs[key2]);
25110
+ }
25111
+ }
25112
+ if (typeof _Node.OnInputsChanged === "function") {
25113
+ _Node.OnInputsChanged();
25114
+ }
25115
+ };
25116
+ this.definedObject = {
25117
+ inputs: this.inputs,
25118
+ outputs: this.outputs,
25119
+ setup: this.setup,
25120
+ destroy: this.destroy,
25121
+ change: this.change
25122
+ };
25123
+ if (_Node.Signals !== void 0) {
25124
+ for (var key in _Node.Signals) {
25125
+ if (typeof _Node.Signals[key] === "function") {
25126
+ this.inputs[key] = "signal";
25127
+ this.definedObject[key] = _Node.Signals[key];
25128
+ }
25129
+ }
25130
+ }
25131
+ };
25132
+ JavascriptNodeParser4.createFromCode = function(code, options) {
25133
+ return new JavascriptNodeParser4(code, options);
25134
+ };
25135
+ function failedParser(message) {
25136
+ var parser = Object.create(JavascriptNodeParser4.prototype);
25137
+ parser.inputs = {};
25138
+ parser.outputs = {};
25139
+ parser.error = message;
25140
+ parser.code = void 0;
25141
+ parser.apis = { Node: {} };
25142
+ return parser;
25143
+ }
25144
+ JavascriptNodeParser4.createFromURL = function(url, callback, options) {
25145
+ url = getAbsoluteUrl2(url);
25146
+ var settled = false;
25147
+ function settle(parser) {
25148
+ if (settled) return;
25149
+ settled = true;
25150
+ callback(parser);
25151
+ }
25152
+ var xhr = new window.XMLHttpRequest();
25153
+ xhr.open("GET", url, true);
25154
+ xhr.onreadystatechange = function() {
25155
+ if (this.readyState === 4 || this.readyState === XMLHttpRequest.DONE) {
25156
+ if (this.status !== 0 && (this.status < 200 || this.status >= 300)) {
25157
+ settle(failedParser('Could not load "' + url + '": the server answered ' + this.status));
25158
+ return;
25159
+ }
25160
+ if (this.status === 0) {
25161
+ settle(failedParser('Could not load "' + url + '": the request failed'));
25162
+ return;
25163
+ }
25164
+ settle(new JavascriptNodeParser4(this.response, options));
25165
+ }
25166
+ };
25167
+ xhr.onerror = function() {
25168
+ settle(failedParser('Could not load "' + url + '": the request failed'));
25169
+ };
25170
+ xhr.send();
25171
+ };
25172
+ JavascriptNodeParser4.parseAndAddPortsFromScript = function(script, ports, options) {
25173
+ function _exists(port) {
25174
+ if (typeof port === "string") return ports.find((p) => p.name === port) !== void 0;
25175
+ else return ports.find((p) => p.name === port.name && p.plug === port.plug) !== void 0;
25176
+ }
25177
+ function _addPortsFromMatch(match, options2) {
25178
+ if (match === void 0 || match === null) return;
25179
+ const unique = {};
25180
+ for (const _s of match) {
25181
+ let name2 = _s[1];
25182
+ if (name2 === void 0) continue;
25183
+ unique[name2] = true;
25184
+ }
25185
+ Object.keys(unique).forEach((p) => {
25186
+ if (_exists({
25187
+ name: options2.prefix + p,
25188
+ plug: options2.plug
25189
+ }))
25190
+ return;
25191
+ ports.push({
25192
+ name: options2.prefix + p,
25193
+ displayName: p,
25194
+ plug: options2.plug,
25195
+ type: options2.type,
25196
+ group: options2.group
25197
+ });
25198
+ });
25199
+ }
25200
+ if (!options.skipInputs) {
25201
+ _addPortsFromMatch(script.matchAll(/Inputs\.([A-Za-z0-9_]+)/g), {
25202
+ type: options.inputType || "*",
25203
+ plug: "input",
25204
+ group: options.inputGroup || "Inputs",
25205
+ prefix: options.inputPrefix || ""
25206
+ });
25207
+ _addPortsFromMatch(script.matchAll(/Inputs\s*\[\s*(?:'|")(.*)(?:'|")\s*\]/g), {
25208
+ type: options.inputType || "*",
25209
+ plug: "inputs",
25210
+ group: options.inputGroup || "Inputs",
25211
+ prefix: options.inputPrefix || ""
25212
+ });
25213
+ }
25214
+ if (!options.skipOutputs) {
25215
+ if (!options.skipOutputSignals) {
25216
+ _addPortsFromMatch(script.matchAll(/Outputs\.([A-Za-z0-9]+)\s*\(\s*\)/g), {
25217
+ type: "signal",
25218
+ plug: "output",
25219
+ group: "Outputs",
25220
+ prefix: options.outputPrefix || ""
25221
+ });
25222
+ _addPortsFromMatch(script.matchAll(/Outputs\s*\[\s*(?:'|")(.*)(?:'|")\s*\]\(\s*\)/g), {
25223
+ type: "signal",
25224
+ plug: "output",
25225
+ group: "Outputs",
25226
+ prefix: options.outputPrefix || ""
25227
+ });
25228
+ }
25229
+ if (!options.skipRegularOutputs) {
25230
+ _addPortsFromMatch(script.matchAll(/Outputs\.([A-Za-z0-9_]+)/g), {
25231
+ type: "*",
25232
+ plug: "output",
25233
+ group: "Outputs",
25234
+ prefix: options.outputPrefix || ""
25235
+ });
25236
+ _addPortsFromMatch(script.matchAll(/Outputs\s*\[\s*\"([^\"]*)\"\s*\]/g), {
25237
+ type: "*",
25238
+ plug: "output",
25239
+ group: "Outputs",
25240
+ prefix: options.outputPrefix || ""
25241
+ });
25242
+ }
25243
+ }
25244
+ };
25245
+ JavascriptNodeParser4.prototype.getPorts = function() {
25246
+ var ports = [];
25247
+ var self2 = this;
25248
+ Object.keys(this.inputs).forEach(function(name2) {
25249
+ var inputPort = self2.inputs[name2];
25250
+ var port = {
25251
+ name: name2,
25252
+ plug: "input"
25253
+ };
25254
+ if (typeof inputPort === "string") {
25255
+ port.type = {
25256
+ name: inputPort
25257
+ };
25258
+ port.group = "Inputs";
25259
+ } else {
25260
+ for (var p in inputPort) {
25261
+ port[p] = inputPort[p];
25262
+ }
25263
+ }
25264
+ ports.push(port);
25265
+ });
25266
+ Object.keys(this.outputs).forEach(function(name2) {
25267
+ ports.push({
25268
+ name: name2,
25269
+ type: {
25270
+ name: self2.outputs[name2]
25271
+ },
25272
+ plug: "output",
25273
+ group: "Outputs"
25274
+ });
25275
+ });
25276
+ JavascriptNodeParser4.parseAndAddPortsFromScript(this.code, ports, {});
25277
+ return ports;
25278
+ };
25279
+ var _componentScopes = {};
25280
+ function _findParentComponentStateModelId(node) {
25281
+ const parent = findAncestorWithComponentObject2(node.nodeScope.componentOwner);
25282
+ if (!parent) return;
25283
+ return "componentState" + parent.getInstanceId();
25284
+ }
25285
+ JavascriptNodeParser4.getComponentScopeForNode = function(node) {
25286
+ const componentId = node.nodeScope.componentOwner.getInstanceId();
25287
+ if (_componentScopes[componentId] === void 0) {
25288
+ _componentScopes[componentId] = {};
25289
+ const componentObject = (node.nodeScope.modelScope || Model27).get("componentState" + componentId);
25290
+ _componentScopes[componentId].Object = componentObject;
25291
+ }
25292
+ const parentComponentObjectId = _findParentComponentStateModelId(node);
25293
+ const parentComponentObject = parentComponentObjectId !== void 0 ? (node.nodeScope.modelScope || Model27).get(parentComponentObjectId) : void 0;
25294
+ _componentScopes[componentId].ParentObject = parentComponentObject;
25295
+ Object.defineProperty(_componentScopes[componentId], "RepeaterObject", {
25296
+ configurable: true,
25297
+ enumerable: true,
25298
+ get: function() {
25299
+ return resolveForEachItem2(node);
25300
+ }
25301
+ });
25302
+ return _componentScopes[componentId];
25303
+ };
25304
+ JavascriptNodeParser4.getCodePrefix = function() {
25305
+ return "const Script = (typeof Node !== 'undefined')?Node:undefined;\n";
25306
+ };
25307
+ JavascriptNodeParser4.createNoodlAPI = function() {
25308
+ return typeof window !== "undefined" && window.Noodl !== void 0 ? window.Noodl : {};
25309
+ };
25310
+ module2.exports = JavascriptNodeParser4;
25311
+ }
25312
+ });
25313
+
25314
+ // ../noodl-runtime/src/printedcode.ts
25315
+ function table() {
25316
+ return globalThis[TABLE];
25317
+ }
25318
+ function hasPrintedCode() {
25319
+ return table() !== void 0;
25320
+ }
25321
+ function sameParams(a, b) {
25322
+ return a.length === b.length && a.every((p, i2) => p === b[i2]);
25323
+ }
25324
+ function findPrintedCode(params, body, async) {
25325
+ const list = table()?.get(body);
25326
+ return list && list.find((e) => e.async === async && sameParams(e.params, params));
25327
+ }
25328
+ function findPrintedBody(body, async) {
25329
+ const list = table()?.get(body);
25330
+ return list && list.find((e) => e.async === async);
25331
+ }
25332
+ function compileCode(params, body, options) {
25333
+ const async = !!(options && options.async);
25334
+ const printed = findPrintedCode(params, body, async);
25335
+ if (printed) return printed.fn;
25336
+ if (table()?.refuseOthers) throw new Error(NOT_PRINTED_MESSAGE);
25337
+ const Ctor = async ? AsyncFunction : Function;
25338
+ return new Ctor(...params, body);
25339
+ }
25340
+ function functionNodeBody(script) {
25341
+ const JavascriptNodeParser4 = require_javascriptnodeparser();
25342
+ return JavascriptNodeParser4.getCodePrefix() + script;
25343
+ }
25344
+ function expressionNodeBody(expression) {
25345
+ return EXPRESSION_PREAMBLE + "return (" + expression + ");";
25346
+ }
25347
+ var NOT_PRINTED_MESSAGE, TABLE, AsyncFunction, FUNCTION_NODE_PARAMS, EXPRESSION_PREAMBLE, REST_REQUEST_PARAMS, REST_RESPONSE_PARAMS, MAP_COLLECTION_PARAMS;
25348
+ var init_printedcode = __esm({
25349
+ "../noodl-runtime/src/printedcode.ts"() {
25350
+ NOT_PRINTED_MESSAGE = "This code was not printed when the app was deployed, and code cannot be compiled here. Deploy the app again.";
25351
+ TABLE = Symbol.for("nodegx.printedCode");
25352
+ AsyncFunction = Object.getPrototypeOf(async function() {
25353
+ }).constructor;
25354
+ FUNCTION_NODE_PARAMS = ["Inputs", "Outputs", "Noodl", "Component", "Scripts"];
25355
+ EXPRESSION_PREAMBLE = [
25356
+ 'var min = Math.min, max = Math.max, cos = Math.cos, sin = Math.sin, tan = Math.tan, sqrt = Math.sqrt, pi = Math.PI, round = Math.round, floor = Math.floor, ceil = Math.ceil, abs = Math.abs, random = Math.random, pow = Math.pow, log = Math.log, exp = Math.exp;try { var NoodlContext = (typeof Noodl !== "undefined") ? Noodl : (typeof global !== "undefined" && global.Noodl) || {}; var Variables = NoodlContext.Variables || {}; var Objects = NoodlContext.Objects || {}; var Arrays = NoodlContext.Arrays || {};} catch (e) { var Variables = {}, Objects = {}, Arrays = {};}'
25357
+ ].join("");
25358
+ REST_REQUEST_PARAMS = ["Inputs", "Outputs", "Request"];
25359
+ REST_RESPONSE_PARAMS = ["Inputs", "Outputs", "Response"];
25360
+ MAP_COLLECTION_PARAMS = ["map", "object"];
25361
+ }
25362
+ });
25363
+
24607
25364
  // ../noodl-runtime/src/nodes/std-library/data/restnode.ts
24608
25365
  var require_restnode = __commonJS({
24609
25366
  "../noodl-runtime/src/nodes/std-library/data/restnode.ts"(exports2, module2) {
25367
+ init_printedcode();
24610
25368
  var defaultRequestScript = "//Add custom code to setup the request object before the request\n//is made.\n//\n//*Request.resource contains the resource path of the request.\n//*Request.method contains the method, GET, POST, PUT or DELETE.\n//*Request.headers is a map where you can add additional headers.\n//*Request.parameters is a map the parameters that will be appended\n// to the url.\n//*Request.content contains the content of the request as a javascript\n// object.\n//\n";
24611
25369
  var defaultResponseScript = "// Add custom code to convert the response content to outputs\n//\n//*Response.status The status code of the response\n//*Response.content The content of the response as a javascript\n// object.\n//*Response.request The request object that resulted in the response.\n//\n//*Inputs and *Outputs contain the inputs and outputs of the node.\n";
24612
25370
  var RestNode = {
@@ -24695,7 +25453,7 @@ var require_restnode = __commonJS({
24695
25453
  group: "Scripts",
24696
25454
  set: function(script) {
24697
25455
  try {
24698
- this._internal.requestFunc = new Function("Inputs", "Outputs", "Request", script);
25456
+ this._internal.requestFunc = compileCode(REST_REQUEST_PARAMS, script);
24699
25457
  } catch (e) {
24700
25458
  console.log(e);
24701
25459
  }
@@ -24712,7 +25470,7 @@ var require_restnode = __commonJS({
24712
25470
  group: "Scripts",
24713
25471
  set: function(script) {
24714
25472
  try {
24715
- this._internal.responseFunc = new Function("Inputs", "Outputs", "Response", script);
25473
+ this._internal.responseFunc = compileCode(REST_RESPONSE_PARAMS, script);
24716
25474
  } catch (e) {
24717
25475
  console.log(e);
24718
25476
  }
@@ -25702,656 +26460,13 @@ var require_lodash = __commonJS({
25702
26460
  }
25703
26461
  });
25704
26462
 
25705
- // ../noodl-runtime/src/utils.ts
25706
- var utils_exports = {};
25707
- __export(utils_exports, {
25708
- getAbsoluteUrl: () => getAbsoluteUrl,
25709
- logJavaScriptNodeError: () => logJavaScriptNodeError,
25710
- thrownMessage: () => thrownMessage
25711
- });
25712
- function getAbsoluteUrl(_url) {
25713
- const url = String(_url);
25714
- if (!url || url[0] === "/" || url.includes("://") || url.startsWith("data:")) {
25715
- return url;
25716
- }
25717
- return (Noodl.baseUrl || "/") + url;
25718
- }
25719
- function thrownMessage(error) {
25720
- if (error && error.message) return String(error.message);
25721
- try {
25722
- return String(error);
25723
- } catch {
25724
- return typeof error;
25725
- }
25726
- }
25727
- function logJavaScriptNodeError(error) {
25728
- const prefix = "Error in JS node run code.";
25729
- if (error === null || typeof error !== "object" && typeof error !== "function") {
25730
- console.log(prefix, thrownMessage(error));
25731
- return;
25732
- }
25733
- const proto = Object.getPrototypeOf(error);
25734
- const kind = proto && proto.constructor && proto.constructor.name ? proto.constructor.name : "Error";
25735
- console.log(prefix, kind + ": " + thrownMessage(error), error.stack);
25736
- }
25737
- var init_utils = __esm({
25738
- "../noodl-runtime/src/utils.ts"() {
25739
- }
25740
- });
25741
-
25742
- // ../noodl-runtime/src/componentwalk.ts
25743
- var componentwalk_exports = {};
25744
- __export(componentwalk_exports, {
25745
- COMPONENT_OBJECT_TYPES: () => COMPONENT_OBJECT_TYPES,
25746
- componentAncestorNames: () => componentAncestorNames,
25747
- componentAncestors: () => componentAncestors,
25748
- findAncestorWithComponentObject: () => findAncestorWithComponentObject,
25749
- findAncestorWithName: () => findAncestorWithName,
25750
- findAncestorWithNodeType: () => findAncestorWithNodeType,
25751
- findAncestorWithProperty: () => findAncestorWithProperty,
25752
- findComponentAncestor: () => findComponentAncestor,
25753
- parentComponentOf: () => parentComponentOf,
25754
- scopeChain: () => scopeChain,
25755
- scopeChainNames: () => scopeChainNames
25756
- });
25757
- function parentComponentOf(component) {
25758
- if (!component) return void 0;
25759
- let parent;
25760
- if (component.getRoots().length > 0) {
25761
- const root2 = component.getRoots()[0];
25762
- if (root2.getVisualParentNode) {
25763
- const visualParent = root2.getVisualParentNode();
25764
- if (visualParent) {
25765
- parent = visualParent.nodeScope.componentOwner;
25766
- }
25767
- } else if (root2.parentNodeScope) {
25768
- parent = component.parentNodeScope.componentOwner;
25769
- }
25770
- } else if (component.parentNodeScope) {
25771
- parent = component.parentNodeScope.componentOwner;
25772
- }
25773
- if (parent && parent.nodeScope && parent.nodeScope.componentOwner !== component) {
25774
- return parent;
25775
- }
25776
- return void 0;
25777
- }
25778
- function componentAncestors(component) {
25779
- const ancestors = [];
25780
- let current = component;
25781
- for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
25782
- const parent = parentComponentOf(current);
25783
- if (!parent) break;
25784
- ancestors.push(parent);
25785
- current = parent;
25786
- }
25787
- return ancestors;
25788
- }
25789
- function findComponentAncestor(component, predicate) {
25790
- let current = component;
25791
- for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
25792
- const parent = parentComponentOf(current);
25793
- if (!parent) return void 0;
25794
- if (predicate(parent)) return parent;
25795
- current = parent;
25796
- }
25797
- return void 0;
25798
- }
25799
- function findAncestorWithNodeType(component, types) {
25800
- return findComponentAncestor(
25801
- component,
25802
- (candidate) => types.some((type) => candidate.nodeScope.getNodesWithType(type).length > 0)
25803
- );
25804
- }
25805
- function findAncestorWithComponentObject(component) {
25806
- return findAncestorWithNodeType(component, COMPONENT_OBJECT_TYPES);
25807
- }
25808
- function findAncestorWithName(component, name2) {
25809
- return findComponentAncestor(component, (candidate) => candidate.name === name2);
25810
- }
25811
- function scopeChain(component) {
25812
- const chain2 = [];
25813
- let current = component;
25814
- for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
25815
- if (!current) break;
25816
- chain2.push(current);
25817
- if (!current.parentNodeScope) break;
25818
- current = current.parentNodeScope.componentOwner;
25819
- }
25820
- return chain2;
25821
- }
25822
- function scopeChainNames(component) {
25823
- return scopeChain(component).map((entry) => entry.name);
25824
- }
25825
- function findAncestorWithProperty(component, property2) {
25826
- const chain2 = scopeChain(component);
25827
- for (let i2 = 0; i2 < chain2.length; i2++) {
25828
- if (chain2[i2][property2] !== void 0) return chain2[i2];
25829
- }
25830
- return void 0;
25831
- }
25832
- function componentAncestorNames(component) {
25833
- return componentAncestors(component).map((ancestor) => ancestor.name);
25834
- }
25835
- var MAX_WALK_DEPTH, COMPONENT_OBJECT_TYPES;
25836
- var init_componentwalk = __esm({
25837
- "../noodl-runtime/src/componentwalk.ts"() {
25838
- "use strict";
25839
- MAX_WALK_DEPTH = 1e3;
25840
- COMPONENT_OBJECT_TYPES = ["net.noodl.ComponentObject", "Component State"];
25841
- }
25842
- });
25843
-
25844
- // ../noodl-runtime/src/resolvedtarget.ts
25845
- function summariseTargets(labels) {
25846
- const distinct = [];
25847
- for (let i2 = 0; i2 < labels.length; i2++) {
25848
- const label = labels[i2];
25849
- if (label === void 0) continue;
25850
- if (distinct.indexOf(label) === -1) distinct.push(label);
25851
- }
25852
- if (distinct.length === 0) return void 0;
25853
- if (distinct.length === 1) return "\u2192 " + distinct[0];
25854
- const listed = distinct.slice(0, MAX_NAMES_LISTED).join(", ");
25855
- const rest2 = distinct.length - MAX_NAMES_LISTED;
25856
- return "\u2192 " + distinct.length + " targets: " + listed + (rest2 > 0 ? ", +" + rest2 : "");
25857
- }
25858
- var MAX_NAMES_LISTED, ResolvedTargetReporter;
25859
- var init_resolvedtarget = __esm({
25860
- "../noodl-runtime/src/resolvedtarget.ts"() {
25861
- "use strict";
25862
- MAX_NAMES_LISTED = 3;
25863
- ResolvedTargetReporter = class {
25864
- constructor() {
25865
- /** Weak, so a torn-down runtime's bookkeeping goes with it and needs no reset call. */
25866
- this._byContext = /* @__PURE__ */ new WeakMap();
25867
- }
25868
- /**
25869
- * Record what `node` bound to and push the summary to the editor.
25870
- *
25871
- * Safe to call every resolution; identical summaries are dropped rather than sent, so a
25872
- * node that re-resolves each frame costs one string comparison.
25873
- */
25874
- report(node, target) {
25875
- const state2 = this._stateFor(node);
25876
- if (!state2) return;
25877
- let instances = state2.byGraphNode.get(node.id);
25878
- if (!instances) {
25879
- instances = /* @__PURE__ */ new Map();
25880
- state2.byGraphNode.set(node.id, instances);
25881
- }
25882
- instances.set(node, target);
25883
- this._flush(node, state2, instances);
25884
- }
25885
- /** Drop an instance. Call from `_onNodeDeleted`, or this map is a leak. */
25886
- forget(node) {
25887
- const state2 = this._stateFor(node);
25888
- if (!state2) return;
25889
- const instances = state2.byGraphNode.get(node.id);
25890
- if (!instances) return;
25891
- instances.delete(node);
25892
- if (instances.size === 0) {
25893
- state2.byGraphNode.delete(node.id);
25894
- state2.lastSent.delete(node.id);
25895
- return;
25896
- }
25897
- this._flush(node, state2, instances);
25898
- }
25899
- _stateFor(node) {
25900
- const context = node.context;
25901
- if (!context) return void 0;
25902
- let state2 = this._byContext.get(context);
25903
- if (!state2) {
25904
- state2 = { byGraphNode: /* @__PURE__ */ new Map(), lastSent: /* @__PURE__ */ new Map() };
25905
- this._byContext.set(context, state2);
25906
- }
25907
- return state2;
25908
- }
25909
- _flush(node, state2, instances) {
25910
- const labels = [];
25911
- instances.forEach((label) => labels.push(label));
25912
- const summary = summariseTargets(labels);
25913
- if (state2.lastSent.has(node.id) && state2.lastSent.get(node.id) === summary) return;
25914
- state2.lastSent.set(node.id, summary);
25915
- const editorConnection = node.context && node.context.editorConnection;
25916
- if (!editorConnection || !editorConnection.isRunningLocally()) return;
25917
- if (typeof editorConnection.sendNodeSubLabel !== "function") return;
25918
- editorConnection.sendNodeSubLabel(node.id, summary);
25919
- }
25920
- };
25921
- }
25922
- });
25923
-
25924
- // ../noodl-runtime/src/foreachitem.ts
25925
- var foreachitem_exports = {};
25926
- __export(foreachitem_exports, {
25927
- forgetForEachItem: () => forgetForEachItem,
25928
- resolveForEachItem: () => resolveForEachItem
25929
- });
25930
- function resolveForEachItem(node, options = {}) {
25931
- const chain2 = scopeChain(node.nodeScope.componentOwner);
25932
- const wanted = options.target;
25933
- if (wanted) {
25934
- const named2 = firstNamed(chain2, wanted);
25935
- if (!named2) {
25936
- return miss(
25937
- node,
25938
- "repeater-item/target-not-found",
25939
- 'No component named "' + wanted + '" contains this node',
25940
- wanted,
25941
- { target: wanted, scope: scopeChainNames(node.nodeScope.componentOwner) }
25942
- );
25943
- }
25944
- if (named2[FOR_EACH_MODEL] === void 0) {
25945
- return miss(
25946
- node,
25947
- "repeater-item/target-has-no-item",
25948
- 'The component "' + wanted + '" has no current item \u2014 it is not used as a Repeater or Run Tasks template',
25949
- wanted,
25950
- { target: wanted }
25951
- );
25952
- }
25953
- return hit(node, named2);
25954
- }
25955
- const owner = firstWithItem(chain2);
25956
- if (!owner) {
25957
- return miss(
25958
- node,
25959
- "repeater-item/no-item-in-scope",
25960
- 'Id Source is set to "From repeater", but this node is not inside a Repeater or Run Tasks template',
25961
- void 0,
25962
- { scope: scopeChainNames(node.nodeScope.componentOwner) }
25963
- );
25964
- }
25965
- return hit(node, owner);
25966
- }
25967
- function forgetForEachItem(node) {
25968
- resolvedTargets.forget(node);
25969
- lastMissByNode.delete(node);
25970
- }
25971
- function firstNamed(chain2, name2) {
25972
- for (let i2 = 0; i2 < chain2.length; i2++) {
25973
- if (chain2[i2].name === name2) return chain2[i2];
25974
- }
25975
- return void 0;
25976
- }
25977
- function firstWithItem(chain2) {
25978
- for (let i2 = 0; i2 < chain2.length; i2++) {
25979
- if (chain2[i2][FOR_EACH_MODEL] !== void 0) return chain2[i2];
25980
- }
25981
- return void 0;
25982
- }
25983
- function hit(node, owner) {
25984
- lastMissByNode.delete(node);
25985
- resolvedTargets.report(node, owner.name);
25986
- return owner[FOR_EACH_MODEL];
25987
- }
25988
- function miss(node, code, message, target, detail) {
25989
- resolvedTargets.report(node, void 0);
25990
- const seen = code + "|" + (target || "");
25991
- if (lastMissByNode.get(node) !== seen) {
25992
- lastMissByNode.set(node, seen);
25993
- node.raiseRuntimeError(code, message, detail);
25994
- }
25995
- return void 0;
25996
- }
25997
- var FOR_EACH_MODEL, resolvedTargets, lastMissByNode;
25998
- var init_foreachitem = __esm({
25999
- "../noodl-runtime/src/foreachitem.ts"() {
26000
- "use strict";
26001
- init_componentwalk();
26002
- init_resolvedtarget();
26003
- FOR_EACH_MODEL = "_forEachModel";
26004
- resolvedTargets = new ResolvedTargetReporter();
26005
- lastMissByNode = /* @__PURE__ */ new WeakMap();
26006
- }
26007
- });
26008
-
26009
- // ../noodl-runtime/src/javascriptnodeparser.js
26010
- var require_javascriptnodeparser = __commonJS({
26011
- "../noodl-runtime/src/javascriptnodeparser.js"(exports2, module2) {
26012
- "use strict";
26013
- var Model27 = require_model2();
26014
- var { getAbsoluteUrl: getAbsoluteUrl2 } = (init_utils(), __toCommonJS(utils_exports));
26015
- var { findAncestorWithComponentObject: findAncestorWithComponentObject2 } = (init_componentwalk(), __toCommonJS(componentwalk_exports));
26016
- var { resolveForEachItem: resolveForEachItem2 } = (init_foreachitem(), __toCommonJS(foreachitem_exports));
26017
- var userFunctionsCache = {};
26018
- function JavascriptNodeParser4(code, options) {
26019
- this.inputs = {};
26020
- this.outputs = {};
26021
- this.error = void 0;
26022
- this.code = code;
26023
- const node = options ? options.node : void 0;
26024
- this._initializeAPIs();
26025
- var userCode = userFunctionsCache[code];
26026
- if (!userCode) {
26027
- try {
26028
- userCode = new Function(["define", "script", "Node", "Component"], JavascriptNodeParser4.getCodePrefix() + code);
26029
- userFunctionsCache[code] = userCode;
26030
- } catch (e) {
26031
- this.error = e.message;
26032
- console.error(e);
26033
- }
26034
- }
26035
- if (userCode) {
26036
- try {
26037
- userCode(
26038
- this.define.bind(this),
26039
- this.script.bind(this),
26040
- this.apis.Node,
26041
- node ? JavascriptNodeParser4.getComponentScopeForNode(node) : {}
26042
- );
26043
- this._afterSourced();
26044
- } catch (e) {
26045
- this.error = e.message;
26046
- console.error(e);
26047
- }
26048
- }
26049
- }
26050
- JavascriptNodeParser4.prototype.define = function(userObject) {
26051
- this.inputs = userObject.inputs || {};
26052
- this.outputs = userObject.outputs || {};
26053
- this.setup = userObject.setup;
26054
- this.change = userObject.run || userObject.change;
26055
- this.destroy = userObject.destroy;
26056
- this.definedObject = userObject;
26057
- };
26058
- function _scriptExtend(_this) {
26059
- var _extended = {
26060
- inputs: _this.inputs || {},
26061
- outputs: _this.outputs || {},
26062
- setup: function(inputs, outputs) {
26063
- this.inputs = inputs;
26064
- this.outputs = outputs;
26065
- this.setOutputs = function(states) {
26066
- for (var key3 in states) {
26067
- this.outputs[key3] = states[key3];
26068
- this.flagOutputDirty(key3);
26069
- }
26070
- };
26071
- if (_this.methods) {
26072
- for (var key2 in _this.methods) {
26073
- this[key2] = _this.methods[key2];
26074
- }
26075
- }
26076
- _this.setup && _this.setup.apply(this);
26077
- },
26078
- destroy: function(inputs, outputs) {
26079
- this.inputs = inputs;
26080
- this.outputs = outputs;
26081
- _this.destroy && _this.destroy.apply(this);
26082
- },
26083
- change: function(inputs, outputs) {
26084
- this.inputs = inputs;
26085
- this.outputs = outputs;
26086
- var old = this._oldInputs || {};
26087
- if (_this.changed) {
26088
- for (var key2 in inputs) {
26089
- if (inputs[key2] !== old[key2]) {
26090
- var changedFunction = _this.changed[key2];
26091
- if (typeof changedFunction === "function") changedFunction.apply(this, [inputs[key2], old[key2]]);
26092
- }
26093
- }
26094
- }
26095
- this._oldInputs = Object.assign({}, inputs);
26096
- }
26097
- };
26098
- if (_this.signals) {
26099
- for (var key in _this.signals) {
26100
- _extended[key] = _this.signals[key];
26101
- _extended.inputs[key] = "signal";
26102
- }
26103
- }
26104
- return _extended;
26105
- }
26106
- JavascriptNodeParser4.prototype.script = function(userObject) {
26107
- var _userObjectExtended = _scriptExtend(userObject);
26108
- this.inputs = _userObjectExtended.inputs || {};
26109
- this.outputs = _userObjectExtended.outputs || {};
26110
- this.setup = _userObjectExtended.setup;
26111
- this.change = _userObjectExtended.run || _userObjectExtended.change;
26112
- this.destroy = _userObjectExtended.destroy;
26113
- this.definedObject = _userObjectExtended;
26114
- };
26115
- JavascriptNodeParser4.prototype._initializeAPIs = function() {
26116
- this.apis = {
26117
- Node: {
26118
- Inputs: {},
26119
- Outputs: {},
26120
- Signals: {},
26121
- Setters: {}
26122
- }
26123
- };
26124
- };
26125
- JavascriptNodeParser4.prototype._afterSourced = function() {
26126
- if (this.definedObject !== void 0) return;
26127
- var _Node = this.apis.Node;
26128
- this.inputs = Object.assign({}, _Node.Inputs || {});
26129
- this.outputs = Object.assign({}, _Node.Outputs || {});
26130
- this.setup = function(inputs, outputs) {
26131
- const _this = this;
26132
- _Node.setOutputs = function(_outputs) {
26133
- for (var key2 in _outputs) {
26134
- outputs[key2] = _outputs[key2];
26135
- _this.flagOutputDirty(key2);
26136
- }
26137
- };
26138
- _Node.OnInit && _Node.OnInit.apply(this);
26139
- };
26140
- this.destroy = _Node.OnDestroy || this.destory;
26141
- this.change = (inputs, outputs, changedInputs) => {
26142
- for (var key2 in changedInputs) {
26143
- if (typeof _Node.Setters[key2] === "function") {
26144
- _Node.Setters[key2](inputs[key2]);
26145
- }
26146
- }
26147
- if (typeof _Node.OnInputsChanged === "function") {
26148
- _Node.OnInputsChanged();
26149
- }
26150
- };
26151
- this.definedObject = {
26152
- inputs: this.inputs,
26153
- outputs: this.outputs,
26154
- setup: this.setup,
26155
- destroy: this.destroy,
26156
- change: this.change
26157
- };
26158
- if (_Node.Signals !== void 0) {
26159
- for (var key in _Node.Signals) {
26160
- if (typeof _Node.Signals[key] === "function") {
26161
- this.inputs[key] = "signal";
26162
- this.definedObject[key] = _Node.Signals[key];
26163
- }
26164
- }
26165
- }
26166
- };
26167
- JavascriptNodeParser4.createFromCode = function(code, options) {
26168
- return new JavascriptNodeParser4(code, options);
26169
- };
26170
- function failedParser(message) {
26171
- var parser = Object.create(JavascriptNodeParser4.prototype);
26172
- parser.inputs = {};
26173
- parser.outputs = {};
26174
- parser.error = message;
26175
- parser.code = void 0;
26176
- parser.apis = { Node: {} };
26177
- return parser;
26178
- }
26179
- JavascriptNodeParser4.createFromURL = function(url, callback, options) {
26180
- url = getAbsoluteUrl2(url);
26181
- var settled = false;
26182
- function settle(parser) {
26183
- if (settled) return;
26184
- settled = true;
26185
- callback(parser);
26186
- }
26187
- var xhr = new window.XMLHttpRequest();
26188
- xhr.open("GET", url, true);
26189
- xhr.onreadystatechange = function() {
26190
- if (this.readyState === 4 || this.readyState === XMLHttpRequest.DONE) {
26191
- if (this.status !== 0 && (this.status < 200 || this.status >= 300)) {
26192
- settle(failedParser('Could not load "' + url + '": the server answered ' + this.status));
26193
- return;
26194
- }
26195
- if (this.status === 0) {
26196
- settle(failedParser('Could not load "' + url + '": the request failed'));
26197
- return;
26198
- }
26199
- settle(new JavascriptNodeParser4(this.response, options));
26200
- }
26201
- };
26202
- xhr.onerror = function() {
26203
- settle(failedParser('Could not load "' + url + '": the request failed'));
26204
- };
26205
- xhr.send();
26206
- };
26207
- JavascriptNodeParser4.parseAndAddPortsFromScript = function(script, ports, options) {
26208
- function _exists(port) {
26209
- if (typeof port === "string") return ports.find((p) => p.name === port) !== void 0;
26210
- else return ports.find((p) => p.name === port.name && p.plug === port.plug) !== void 0;
26211
- }
26212
- function _addPortsFromMatch(match, options2) {
26213
- if (match === void 0 || match === null) return;
26214
- const unique = {};
26215
- for (const _s of match) {
26216
- let name2 = _s[1];
26217
- if (name2 === void 0) continue;
26218
- unique[name2] = true;
26219
- }
26220
- Object.keys(unique).forEach((p) => {
26221
- if (_exists({
26222
- name: options2.prefix + p,
26223
- plug: options2.plug
26224
- }))
26225
- return;
26226
- ports.push({
26227
- name: options2.prefix + p,
26228
- displayName: p,
26229
- plug: options2.plug,
26230
- type: options2.type,
26231
- group: options2.group
26232
- });
26233
- });
26234
- }
26235
- if (!options.skipInputs) {
26236
- _addPortsFromMatch(script.matchAll(/Inputs\.([A-Za-z0-9_]+)/g), {
26237
- type: options.inputType || "*",
26238
- plug: "input",
26239
- group: options.inputGroup || "Inputs",
26240
- prefix: options.inputPrefix || ""
26241
- });
26242
- _addPortsFromMatch(script.matchAll(/Inputs\s*\[\s*(?:'|")(.*)(?:'|")\s*\]/g), {
26243
- type: options.inputType || "*",
26244
- plug: "inputs",
26245
- group: options.inputGroup || "Inputs",
26246
- prefix: options.inputPrefix || ""
26247
- });
26248
- }
26249
- if (!options.skipOutputs) {
26250
- if (!options.skipOutputSignals) {
26251
- _addPortsFromMatch(script.matchAll(/Outputs\.([A-Za-z0-9]+)\s*\(\s*\)/g), {
26252
- type: "signal",
26253
- plug: "output",
26254
- group: "Outputs",
26255
- prefix: options.outputPrefix || ""
26256
- });
26257
- _addPortsFromMatch(script.matchAll(/Outputs\s*\[\s*(?:'|")(.*)(?:'|")\s*\]\(\s*\)/g), {
26258
- type: "signal",
26259
- plug: "output",
26260
- group: "Outputs",
26261
- prefix: options.outputPrefix || ""
26262
- });
26263
- }
26264
- if (!options.skipRegularOutputs) {
26265
- _addPortsFromMatch(script.matchAll(/Outputs\.([A-Za-z0-9_]+)/g), {
26266
- type: "*",
26267
- plug: "output",
26268
- group: "Outputs",
26269
- prefix: options.outputPrefix || ""
26270
- });
26271
- _addPortsFromMatch(script.matchAll(/Outputs\s*\[\s*\"([^\"]*)\"\s*\]/g), {
26272
- type: "*",
26273
- plug: "output",
26274
- group: "Outputs",
26275
- prefix: options.outputPrefix || ""
26276
- });
26277
- }
26278
- }
26279
- };
26280
- JavascriptNodeParser4.prototype.getPorts = function() {
26281
- var ports = [];
26282
- var self2 = this;
26283
- Object.keys(this.inputs).forEach(function(name2) {
26284
- var inputPort = self2.inputs[name2];
26285
- var port = {
26286
- name: name2,
26287
- plug: "input"
26288
- };
26289
- if (typeof inputPort === "string") {
26290
- port.type = {
26291
- name: inputPort
26292
- };
26293
- port.group = "Inputs";
26294
- } else {
26295
- for (var p in inputPort) {
26296
- port[p] = inputPort[p];
26297
- }
26298
- }
26299
- ports.push(port);
26300
- });
26301
- Object.keys(this.outputs).forEach(function(name2) {
26302
- ports.push({
26303
- name: name2,
26304
- type: {
26305
- name: self2.outputs[name2]
26306
- },
26307
- plug: "output",
26308
- group: "Outputs"
26309
- });
26310
- });
26311
- JavascriptNodeParser4.parseAndAddPortsFromScript(this.code, ports, {});
26312
- return ports;
26313
- };
26314
- var _componentScopes = {};
26315
- function _findParentComponentStateModelId(node) {
26316
- const parent = findAncestorWithComponentObject2(node.nodeScope.componentOwner);
26317
- if (!parent) return;
26318
- return "componentState" + parent.getInstanceId();
26319
- }
26320
- JavascriptNodeParser4.getComponentScopeForNode = function(node) {
26321
- const componentId = node.nodeScope.componentOwner.getInstanceId();
26322
- if (_componentScopes[componentId] === void 0) {
26323
- _componentScopes[componentId] = {};
26324
- const componentObject = (node.nodeScope.modelScope || Model27).get("componentState" + componentId);
26325
- _componentScopes[componentId].Object = componentObject;
26326
- }
26327
- const parentComponentObjectId = _findParentComponentStateModelId(node);
26328
- const parentComponentObject = parentComponentObjectId !== void 0 ? (node.nodeScope.modelScope || Model27).get(parentComponentObjectId) : void 0;
26329
- _componentScopes[componentId].ParentObject = parentComponentObject;
26330
- Object.defineProperty(_componentScopes[componentId], "RepeaterObject", {
26331
- configurable: true,
26332
- enumerable: true,
26333
- get: function() {
26334
- return resolveForEachItem2(node);
26335
- }
26336
- });
26337
- return _componentScopes[componentId];
26338
- };
26339
- JavascriptNodeParser4.getCodePrefix = function() {
26340
- return "const Script = (typeof Node !== 'undefined')?Node:undefined;\n";
26341
- };
26342
- JavascriptNodeParser4.createNoodlAPI = function() {
26343
- return typeof window !== "undefined" && window.Noodl !== void 0 ? window.Noodl : {};
26344
- };
26345
- module2.exports = JavascriptNodeParser4;
26346
- }
26347
- });
26348
-
26349
26463
  // ../noodl-runtime/src/nodes/std-library/expression.ts
26350
26464
  var require_expression = __commonJS({
26351
26465
  "../noodl-runtime/src/nodes/std-library/expression.ts"(exports2, module2) {
26352
26466
  "use strict";
26353
26467
  init_expression_ports();
26354
26468
  init_logic_search_tags();
26469
+ init_printedcode();
26355
26470
  init_outcome();
26356
26471
  init_run_on_value_change();
26357
26472
  var Node17 = require_node2();
@@ -26580,11 +26695,27 @@ var require_expression = __commonJS({
26580
26695
  const args = Object.keys(this._internal.scope);
26581
26696
  this._internal.compiledWith = args.slice();
26582
26697
  args.push("Noodl");
26698
+ const printed = findPrintedBody(expression, false);
26699
+ if (printed) {
26700
+ this._internal.compiledWith = printed.params.slice(0, -1);
26701
+ this._internal.compileError = void 0;
26702
+ return printed.fn;
26703
+ }
26704
+ if (hasPrintedCode()) {
26705
+ try {
26706
+ const fn = compileCode(args, expression);
26707
+ this._internal.compileError = void 0;
26708
+ return fn;
26709
+ } catch (e) {
26710
+ this._internal.compileError = e.message;
26711
+ return void 0;
26712
+ }
26713
+ }
26583
26714
  const key = expression + args.join(" ");
26584
26715
  if (compiledFunctionsCache2.hasOwnProperty(key) === false) {
26585
- args.push(expression);
26716
+ const params = args.slice();
26586
26717
  try {
26587
- compiledFunctionsCache2[key] = construct(Function, args);
26718
+ compiledFunctionsCache2[key] = compileCode(params, expression);
26588
26719
  this._internal.compileError = void 0;
26589
26720
  } catch (e) {
26590
26721
  this._internal.compileError = e.message;
@@ -26616,7 +26747,7 @@ var require_expression = __commonJS({
26616
26747
  description: "JavaScript expression whose value becomes Result. Every name it reads becomes an input port, except JavaScript's own (String, Number, JSON, Date, parseInt, Math and the rest), the Math shortcuts (round, min, pi\u2026) and keywords such as typeof; a port can never be called one of those, nor run, expression or evaluateAtLoad, which are this node's own inputs",
26617
26748
  set: function(value2) {
26618
26749
  const internal2 = this._internal;
26619
- internal2.currentExpression = functionPreamble + "return (" + value2 + ");";
26750
+ internal2.currentExpression = expressionNodeBody(value2);
26620
26751
  internal2.compiledFunction = void 0;
26621
26752
  const newInputs = expressionPorts(value2);
26622
26753
  internal2.referencedPorts = newInputs;
@@ -26815,17 +26946,7 @@ var require_expression = __commonJS({
26815
26946
  }
26816
26947
  }
26817
26948
  };
26818
- var functionPreamble = [
26819
- 'var min = Math.min, max = Math.max, cos = Math.cos, sin = Math.sin, tan = Math.tan, sqrt = Math.sqrt, pi = Math.PI, round = Math.round, floor = Math.floor, ceil = Math.ceil, abs = Math.abs, random = Math.random, pow = Math.pow, log = Math.log, exp = Math.exp;try { var NoodlContext = (typeof Noodl !== "undefined") ? Noodl : (typeof global !== "undefined" && global.Noodl) || {}; var Variables = NoodlContext.Variables || {}; var Objects = NoodlContext.Objects || {}; var Arrays = NoodlContext.Arrays || {};} catch (e) { var Variables = {}, Objects = {}, Arrays = {};}'
26820
- ].join("");
26821
26949
  var NOT_EVALUATED = {};
26822
- function construct(constructor, args) {
26823
- function F() {
26824
- return constructor.apply(this, args);
26825
- }
26826
- F.prototype = constructor.prototype;
26827
- return new F();
26828
- }
26829
26950
  var compiledFunctionsCache2 = {};
26830
26951
  function reservedNameMessage(names) {
26831
26952
  const list = names.length > 1 ? names.slice(0, -1).join(", ") + " and " + names[names.length - 1] : names.join("");
@@ -26929,10 +27050,10 @@ function rawPositionFromStack(stack) {
26929
27050
  function stackLineOffset() {
26930
27051
  if (cachedOffset !== void 0) return cachedOffset;
26931
27052
  try {
26932
- const AsyncFunction = Object.getPrototypeOf(async function() {
27053
+ const AsyncFunction2 = Object.getPrototypeOf(async function() {
26933
27054
  }).constructor;
26934
27055
  let captured;
26935
- const probe = new AsyncFunction(
27056
+ const probe = new AsyncFunction2(
26936
27057
  "Inputs",
26937
27058
  "Outputs",
26938
27059
  "Noodl",
@@ -26987,12 +27108,12 @@ function undeclaredPortNameMessage(name2, side, isSignal = false) {
26987
27108
  function noOutputWrittenMessage(ports) {
26988
27109
  if (ports.length === 0) return "";
26989
27110
  const first2 = ports[0];
26990
- const named2 = ports.map((p) => '"' + p.label + '"').join(", ");
27111
+ const named3 = ports.map((p) => '"' + p.label + '"').join(", ");
26991
27112
  const which = ports.length === 1 ? "it" : '"' + first2.label + '"';
26992
27113
  if (first2.isSignal) {
26993
- return "The script ran but produced no output: " + named2 + " never fired. Fire " + which + " in the script with " + portUsage("Outputs", first2.label, true) + ".";
27114
+ return "The script ran but produced no output: " + named3 + " never fired. Fire " + which + " in the script with " + portUsage("Outputs", first2.label, true) + ".";
26994
27115
  }
26995
- return "The script ran but produced no output: " + named2 + " stayed empty. Write " + which + " in the script with " + portUsage("Outputs", first2.label, false) + " \u2014 assigning to a plain variable of the same name does not reach the port.";
27116
+ return "The script ran but produced no output: " + named3 + " stayed empty. Write " + which + " in the script with " + portUsage("Outputs", first2.label, false) + " \u2014 assigning to a plain variable of the same name does not reach the port.";
26996
27117
  }
26997
27118
  function proplistLabels(model2, parameter) {
26998
27119
  const rows = model2 && model2.parameters && model2.parameters[parameter];
@@ -27196,6 +27317,7 @@ var require_simplejavascript = __commonJS({
27196
27317
  init_scriptfiles();
27197
27318
  init_function_ports();
27198
27319
  init_tracecause();
27320
+ init_printedcode();
27199
27321
  var Node17 = require_node2();
27200
27322
  var JavascriptNodeParser4 = require_javascriptnodeparser();
27201
27323
  var { logJavaScriptNodeError: logJavaScriptNodeError2, thrownMessage: thrownMessage3 } = (init_utils(), __toCommonJS(utils_exports));
@@ -27722,16 +27844,7 @@ var require_simplejavascript = __commonJS({
27722
27844
  parseScript: function(script) {
27723
27845
  let func;
27724
27846
  try {
27725
- const AsyncFunction = Object.getPrototypeOf(async function() {
27726
- }).constructor;
27727
- func = new AsyncFunction(
27728
- "Inputs",
27729
- "Outputs",
27730
- "Noodl",
27731
- "Component",
27732
- "Scripts",
27733
- JavascriptNodeParser4.getCodePrefix() + script
27734
- );
27847
+ func = compileCode(FUNCTION_NODE_PARAMS, functionNodeBody(script), { async: true });
27735
27848
  this._internal.parseError = void 0;
27736
27849
  this._internal.lastReportedError = void 0;
27737
27850
  } catch (e) {
@@ -27799,9 +27912,9 @@ var require_simplejavascript = __commonJS({
27799
27912
  return;
27800
27913
  }
27801
27914
  try {
27802
- const AsyncFunction = Object.getPrototypeOf(async function() {
27915
+ const AsyncFunction2 = Object.getPrototypeOf(async function() {
27803
27916
  }).constructor;
27804
- new AsyncFunction("Inputs", "Outputs", "Noodl", "Component", script);
27917
+ new AsyncFunction2("Inputs", "Outputs", "Noodl", "Component", script);
27805
27918
  context.editorConnection.clearWarning(node.component.name, node.id, "js-function-parse-waring");
27806
27919
  } catch (e) {
27807
27920
  context.editorConnection.sendWarning(node.component.name, node.id, "js-function-parse-waring", {
@@ -28304,6 +28417,7 @@ var require_logic_builder = __commonJS({
28304
28417
  init_logic_builder_io2();
28305
28418
  init_logic_builder_probe();
28306
28419
  init_logic_search_tags();
28420
+ init_printedcode();
28307
28421
  init_outcome();
28308
28422
  var EdgeTriggeredInput7 = require_edgetriggeredinput();
28309
28423
  var LogicBuilderNode = {
@@ -28658,47 +28772,49 @@ var require_logic_builder = __commonJS({
28658
28772
  return null;
28659
28773
  }
28660
28774
  try {
28661
- const fn = new Function(
28662
- "Inputs",
28663
- "Outputs",
28664
- "Noodl",
28665
- "Variables",
28666
- "Objects",
28667
- "Arrays",
28668
- "sendSignalOnOutput",
28669
- "__triggerSignal__",
28670
- /**
28671
- * LGC-003 §1 — the ninth and tenth parameters, and the reason there is only ever one
28672
- * generated string.
28673
- *
28674
- * The editor emits `__p("<blockId>", …)` around every value block and `__s("<blockId>")`
28675
- * before every statement, always — there is no debug build and no release build, so
28676
- * there is no class of defect that appears only when nobody is watching. What changes
28677
- * is which functions land here: the shared identity pair, or a recorder.
28678
- *
28679
- * ⚠️ **Declared unconditionally, including for code generated before this existed.**
28680
- * A `generatedCode` string saved by an older editor mentions neither name, and an
28681
- * unused parameter costs nothing — whereas making the list conditional on the code
28682
- * would put a `code.indexOf('__p')` on the compile path and give the runtime two
28683
- * shapes of compiled function to reason about.
28684
- */
28685
- "__p",
28686
- "__s",
28687
- /**
28688
- * The eleventh parameter, and the only one that shadows a global rather than adding a
28689
- * name (FIX-004 redaction ruling b).
28690
- *
28691
- * ⚠️ **Order is the contract.** This list and the argument list in `_executeLogic` are
28692
- * positional, so a parameter added here and not there — or added in a different place —
28693
- * silently shifts every argument after it. `__triggerSignal__` was already once built
28694
- * and then not passed, which read as `undefined` inside every block program ever run.
28695
- * A spec asserts this node's parameter names in order for that reason.
28696
- *
28697
- * Declared unconditionally, exactly as `__p`/`__s` are: code generated before this
28698
- * existed says `console.log`, which is the whole point, and code that never mentions
28699
- * `console` pays one unused parameter.
28700
- */
28701
- "console",
28775
+ const fn = compileCode(
28776
+ [
28777
+ "Inputs",
28778
+ "Outputs",
28779
+ "Noodl",
28780
+ "Variables",
28781
+ "Objects",
28782
+ "Arrays",
28783
+ "sendSignalOnOutput",
28784
+ "__triggerSignal__",
28785
+ /**
28786
+ * LGC-003 §1 — the ninth and tenth parameters, and the reason there is only ever one
28787
+ * generated string.
28788
+ *
28789
+ * The editor emits `__p("<blockId>", …)` around every value block and `__s("<blockId>")`
28790
+ * before every statement, always — there is no debug build and no release build, so
28791
+ * there is no class of defect that appears only when nobody is watching. What changes
28792
+ * is which functions land here: the shared identity pair, or a recorder.
28793
+ *
28794
+ * ⚠️ **Declared unconditionally, including for code generated before this existed.**
28795
+ * A `generatedCode` string saved by an older editor mentions neither name, and an
28796
+ * unused parameter costs nothing — whereas making the list conditional on the code
28797
+ * would put a `code.indexOf('__p')` on the compile path and give the runtime two
28798
+ * shapes of compiled function to reason about.
28799
+ */
28800
+ "__p",
28801
+ "__s",
28802
+ /**
28803
+ * The eleventh parameter, and the only one that shadows a global rather than adding a
28804
+ * name (FIX-004 redaction ruling b).
28805
+ *
28806
+ * ⚠️ **Order is the contract.** This list and the argument list in `_executeLogic` are
28807
+ * positional, so a parameter added here and not there — or added in a different place —
28808
+ * silently shifts every argument after it. `__triggerSignal__` was already once built
28809
+ * and then not passed, which read as `undefined` inside every block program ever run.
28810
+ * A spec asserts this node's parameter names in order for that reason.
28811
+ *
28812
+ * Declared unconditionally, exactly as `__p`/`__s` are: code generated before this
28813
+ * existed says `console.log`, which is the whole point, and code that never mentions
28814
+ * `console` pays one unused parameter.
28815
+ */
28816
+ "console"
28817
+ ],
28702
28818
  code
28703
28819
  );
28704
28820
  return fn;
@@ -30148,9 +30264,9 @@ var init_SseConnectionPool = __esm({
30148
30264
  // ../noodl-runtime/src/api/backends/realtime/SseTransport.ts
30149
30265
  function entryIsAbout(entry, collection) {
30150
30266
  if (!entry || typeof entry !== "object") return true;
30151
- const named2 = entry.collection;
30152
- if (typeof named2 !== "string") return true;
30153
- return named2 === collection;
30267
+ const named3 = entry.collection;
30268
+ if (typeof named3 !== "string") return true;
30269
+ return named3 === collection;
30154
30270
  }
30155
30271
  var NODEGX_SSE, POCKETBASE_SSE, SseTransport;
30156
30272
  var init_SseTransport = __esm({
@@ -30809,6 +30925,19 @@ function recordFieldPorts(ctx, options) {
30809
30925
  }
30810
30926
  return ports;
30811
30927
  }
30928
+ function recordBuiltInDatePorts(ctx, existingPorts, options = {}) {
30929
+ if (!ctx.selectedCollection || !isParseWireContext(ctx)) return [];
30930
+ const have = new Set(existingPorts.map((port) => port.name));
30931
+ const ports = [];
30932
+ for (const field of RECORD_BUILT_IN_DATES) {
30933
+ if (have.has(`prop-${field}`)) continue;
30934
+ ports.push({ name: `prop-${field}`, displayName: field, type: { name: "date" }, plug: "output", group: "Properties" });
30935
+ if (options.includeChangedSignals && !have.has(`changed-${field}`)) {
30936
+ ports.push({ name: `changed-${field}`, displayName: `${field} Changed`, type: "signal", plug: "output", group: "Events" });
30937
+ }
30938
+ }
30939
+ return ports;
30940
+ }
30812
30941
  function recordPortType(field) {
30813
30942
  if (field.nativeType && Object.prototype.hasOwnProperty.call(PARSE_PORT_TYPES, field.nativeType)) {
30814
30943
  return { name: PARSE_PORT_TYPES[field.nativeType] };
@@ -30919,7 +31048,7 @@ function parseTypeNameFor(field) {
30919
31048
  function recordFilterBackendType(ctx, fallback) {
30920
31049
  return ctx.backendType || fallback;
30921
31050
  }
30922
- var PARSE_PORT_TYPES, PARSE_SYSTEM_CLASSES;
31051
+ var PARSE_PORT_TYPES, PARSE_SYSTEM_CLASSES, RECORD_BUILT_IN_DATES;
30923
31052
  var init_record_ports = __esm({
30924
31053
  "../noodl-runtime/src/nodes/std-library/data/record-ports.ts"() {
30925
31054
  init_resolveBackend_pure();
@@ -30934,6 +31063,7 @@ var init_record_ports = __esm({
30934
31063
  { label: "User", value: "_User" },
30935
31064
  { label: "Role", value: "_Role" }
30936
31065
  ]);
31066
+ RECORD_BUILT_IN_DATES = Object.freeze(["createdAt", "updatedAt"]);
30937
31067
  }
30938
31068
  });
30939
31069
 
@@ -31233,8 +31363,8 @@ function relationsFromDirectus(rows) {
31233
31363
  function relationsFromPostgrestSpec(spec) {
31234
31364
  const definitions = spec?.definitions ?? {};
31235
31365
  const result2 = [];
31236
- const analyse = (table) => {
31237
- const properties2 = definitions[table]?.properties ?? {};
31366
+ const analyse = (table2) => {
31367
+ const properties2 = definitions[table2]?.properties ?? {};
31238
31368
  const foreignKeys = [];
31239
31369
  let primaryKeyCount = 0;
31240
31370
  for (const [column, definition4] of Object.entries(properties2)) {
@@ -31246,8 +31376,8 @@ function relationsFromPostgrestSpec(spec) {
31246
31376
  }
31247
31377
  return { foreignKeys, primaryKeyCount };
31248
31378
  };
31249
- for (const table of Object.keys(definitions)) {
31250
- const { foreignKeys, primaryKeyCount } = analyse(table);
31379
+ for (const table2 of Object.keys(definitions)) {
31380
+ const { foreignKeys, primaryKeyCount } = analyse(table2);
31251
31381
  const isJunction = foreignKeys.length === 2 && primaryKeyCount === 2 && foreignKeys.every((fk) => fk.primaryKey);
31252
31382
  if (isJunction) {
31253
31383
  const [left, right] = foreignKeys;
@@ -31264,7 +31394,7 @@ function relationsFromPostgrestSpec(spec) {
31264
31394
  cardinality: "many",
31265
31395
  write: {
31266
31396
  kind: "junction",
31267
- collection: table,
31397
+ collection: table2,
31268
31398
  sourceField: near.column,
31269
31399
  targetField: far.column,
31270
31400
  // The pair *is* the primary key, so a duplicate is a `23505` and
@@ -31278,7 +31408,7 @@ function relationsFromPostgrestSpec(spec) {
31278
31408
  }
31279
31409
  for (const fk of foreignKeys) {
31280
31410
  result2.push({
31281
- collection: table,
31411
+ collection: table2,
31282
31412
  field: fk.column,
31283
31413
  target: fk.target,
31284
31414
  cardinality: "one",
@@ -31286,8 +31416,8 @@ function relationsFromPostgrestSpec(spec) {
31286
31416
  });
31287
31417
  result2.push({
31288
31418
  collection: fk.target,
31289
- field: table,
31290
- target: table,
31419
+ field: table2,
31420
+ target: table2,
31291
31421
  cardinality: "many",
31292
31422
  write: { kind: "foreignKey", field: fk.column, on: "target" }
31293
31423
  });
@@ -31560,11 +31690,11 @@ var init_filter = __esm({
31560
31690
 
31561
31691
  // ../nodegx-backend-contract/src/descriptors/helpers.ts
31562
31692
  function filterTable(fallback, overrides) {
31563
- const table = {};
31693
+ const table2 = {};
31564
31694
  for (const operator of FILTER_OPERATORS) {
31565
- table[operator] = overrides[operator] ?? fallback;
31695
+ table2[operator] = overrides[operator] ?? fallback;
31566
31696
  }
31567
- return Object.freeze(table);
31697
+ return Object.freeze(table2);
31568
31698
  }
31569
31699
  var supported, unsupported, degraded, conditional;
31570
31700
  var init_helpers = __esm({
@@ -33060,12 +33190,12 @@ var init_operational = __esm({
33060
33190
  });
33061
33191
 
33062
33192
  // ../nodegx-backend-contract/src/targetGoes.ts
33063
- function whenTargetGoesProblems(table, columns) {
33193
+ function whenTargetGoesProblems(table2, columns) {
33064
33194
  const out = [];
33065
33195
  for (const col of columns) {
33066
33196
  const rule = col.whenTargetGoes;
33067
33197
  if (rule === void 0) continue;
33068
- const at = `"${table}.${col.name}"`;
33198
+ const at = `"${table2}.${col.name}"`;
33069
33199
  if (typeof rule !== "string" || !WHEN_TARGET_GOES.includes(rule)) {
33070
33200
  out.push(`${at} says "${String(rule)}" for when what it points at goes; it must be one of ${WHEN_TARGET_GOES.join(", ")}.`);
33071
33201
  } else if (col.type !== "Pointer") {
@@ -33080,12 +33210,12 @@ function whenTargetGoesProblems(table, columns) {
33080
33210
  }
33081
33211
  function rulesByTarget(schema) {
33082
33212
  const out = /* @__PURE__ */ new Map();
33083
- for (const table of schema.listTables()) {
33084
- for (const col of schema.getTableSchema(table)?.columns || []) {
33213
+ for (const table2 of schema.listTables()) {
33214
+ for (const col of schema.getTableSchema(table2)?.columns || []) {
33085
33215
  const rule = col.whenTargetGoes;
33086
33216
  if (col.type !== "Pointer" || !col.targetClass || !rule || !WHEN_TARGET_GOES.includes(rule)) continue;
33087
33217
  const list = out.get(col.targetClass) || [];
33088
- list.push({ collection: table, field: col.name, rule });
33218
+ list.push({ collection: table2, field: col.name, rule });
33089
33219
  out.set(col.targetClass, list);
33090
33220
  }
33091
33221
  }
@@ -33093,18 +33223,18 @@ function rulesByTarget(schema) {
33093
33223
  }
33094
33224
  function relations(schema) {
33095
33225
  const out = [];
33096
- for (const table of schema.listTables())
33097
- for (const col of schema.getTableSchema(table)?.columns || []) if (col.type === "Relation") out.push([table, col.name, col.targetClass || ""]);
33226
+ for (const table2 of schema.listTables())
33227
+ for (const col of schema.getTableSchema(table2)?.columns || []) if (col.type === "Relation") out.push([table2, col.name, col.targetClass || ""]);
33098
33228
  return out;
33099
33229
  }
33100
33230
  function pairsOf(rels, schema, collection, objectId) {
33101
33231
  const out = [];
33102
- for (const [table, field, target] of rels) {
33103
- if (table === collection) {
33104
- const ids = schema.getRelatedIds(table, objectId, field);
33105
- for (const relatedId of Array.isArray(ids) ? ids : []) out.push({ collection: table, objectId, field, relatedId: String(relatedId) });
33232
+ for (const [table2, field, target] of rels) {
33233
+ if (table2 === collection) {
33234
+ const ids = schema.getRelatedIds(table2, objectId, field);
33235
+ for (const relatedId of Array.isArray(ids) ? ids : []) out.push({ collection: table2, objectId, field, relatedId: String(relatedId) });
33106
33236
  }
33107
- if (target === collection) for (const owner of schema.getRelationOwners(table, field, objectId)) out.push({ collection: table, objectId: owner, field, relatedId: objectId });
33237
+ if (target === collection) for (const owner of schema.getRelationOwners(table2, field, objectId)) out.push({ collection: table2, objectId: owner, field, relatedId: objectId });
33108
33238
  }
33109
33239
  return out;
33110
33240
  }
@@ -33119,7 +33249,7 @@ async function linkedIds(ctx, collection, field, id) {
33119
33249
  async function planDelete(ctx, collection, objectId) {
33120
33250
  const rules2 = rulesByTarget(ctx.schema);
33121
33251
  const rels = relations(ctx.schema);
33122
- if (!rules2.has(collection) && !rels.some(([table, , target]) => table === collection || target === collection)) return null;
33252
+ if (!rules2.has(collection) && !rels.some(([table2, , target]) => table2 === collection || target === collection)) return null;
33123
33253
  if (await ctx.count(collection, { objectId }) === 0) return null;
33124
33254
  const key = (c, id) => `${c}\0${id}`;
33125
33255
  const gone = [{ collection, objectId }];
@@ -33240,9 +33370,9 @@ function idOf(v) {
33240
33370
  if (typeof v === "string" && v) return v;
33241
33371
  return void 0;
33242
33372
  }
33243
- function targetOf(ctx, table, field) {
33244
- const col = ctx.schema.getTableSchema(table)?.columns?.find((c) => c.name === field);
33245
- if (!col?.targetClass) throw new Error(`${table}.${field} is not a link the schema knows the target of`);
33373
+ function targetOf(ctx, table2, field) {
33374
+ const col = ctx.schema.getTableSchema(table2)?.columns?.find((c) => c.name === field);
33375
+ if (!col?.targetClass) throw new Error(`${table2}.${field} is not a link the schema knows the target of`);
33246
33376
  return col.targetClass;
33247
33377
  }
33248
33378
  async function dryRunMigration(ctx, plan) {
@@ -33937,7 +34067,8 @@ var init_ParseWireAdapter = __esm({
33937
34067
  runId !== void 0 ? { "X-NodeGX-Run": runId } : {},
33938
34068
  options.headers || {}
33939
34069
  );
33940
- fetch(endpoint + path8, {
34070
+ const send = typeof _noodl_cloudservices !== "undefined" && _noodl_cloudservices.fetch ? _noodl_cloudservices.fetch : fetch;
34071
+ send(endpoint + path8, {
33941
34072
  method: options.method || "GET",
33942
34073
  headers,
33943
34074
  body: JSON.stringify(options.content)
@@ -33992,8 +34123,9 @@ var init_ParseWireAdapter = __esm({
33992
34123
  // P99 HLT-023: pass the server's words on, as `fetch` and the rest do. Dropped here, a
33993
34124
  // refusal that names its cause (the per-run ceiling, a 429 with its class) reached the
33994
34125
  // function as "Failed to query."
33995
- error: function(res) {
33996
- options.error(res && res.error);
34126
+ // P115-HST006-STALEROWS: and the status, so a reader can tell a refusal (403) from a blip.
34127
+ error: function(res, status) {
34128
+ options.error(res && res.error, status);
33997
34129
  }
33998
34130
  });
33999
34131
  }
@@ -35272,8 +35404,8 @@ function savedItemToNeutral(item, resolve5, options) {
35272
35404
  if (isSavedGroup(item)) return savedFilterToNeutral(item, resolve5, options);
35273
35405
  const condition = item;
35274
35406
  const isConnected = condition.valueSource === "connected" && !!condition.valuePortName;
35275
- const resolved2 = isConnected && resolve5 ? resolve5(condition.valuePortName) : void 0;
35276
- const value2 = isConnected ? resolved2 !== void 0 || options.dropUnresolvedConnected ? resolved2 : condition.value : condition.value;
35407
+ const resolved3 = isConnected && resolve5 ? resolve5(condition.valuePortName) : void 0;
35408
+ const value2 = isConnected ? resolved3 !== void 0 || options.dropUnresolvedConnected ? resolved3 : condition.value : condition.value;
35277
35409
  if (condition.kind === "relation") {
35278
35410
  if (value2 === void 0 || value2 === null || value2 === "") return null;
35279
35411
  return {
@@ -37609,7 +37741,8 @@ var init_RestDataAdapter = __esm({
37609
37741
  const total = options.count ? readTotalCount(profile, body, headers, rows.length) : void 0;
37610
37742
  options.success(records, total);
37611
37743
  },
37612
- fail: (message) => options.error(message)
37744
+ fail: (message, status) => options.error(message, status)
37745
+ // P115-HST006-STALEROWS: a refusal is told apart
37613
37746
  }
37614
37747
  );
37615
37748
  }
@@ -39158,8 +39291,19 @@ var require_cloudstore = __commonJS({
39158
39291
  }
39159
39292
  return obj;
39160
39293
  }
39294
+ function _schemaOf(collectionName2) {
39295
+ const collection = collectionName2 !== void 0 ? CloudStore7._collections[collectionName2] : void 0;
39296
+ if (!collection) return void 0;
39297
+ if (collection.schema) return collection.schema;
39298
+ if (!Array.isArray(collection.columns)) return void 0;
39299
+ const properties2 = {};
39300
+ for (const column of collection.columns) {
39301
+ if (column && column.name) properties2[column.name] = { type: column.type, targetClass: column.targetClass };
39302
+ }
39303
+ return { properties: properties2 };
39304
+ }
39161
39305
  function _serializeObject(data, collectionName2, modelScope) {
39162
- if (CloudStore7._collections[collectionName2]) var schema = CloudStore7._collections[collectionName2].schema;
39306
+ var schema = _schemaOf(collectionName2);
39163
39307
  for (var key in data) {
39164
39308
  var _type = schema && schema.properties && schema.properties[key] ? schema.properties[key].type : void 0;
39165
39309
  if (data[key] === void 0 || data[key] === null) {
@@ -39244,14 +39388,14 @@ var require_cloudstore = __commonJS({
39244
39388
  function _fromJSON(item, collectionName2, modelScope) {
39245
39389
  const m = (modelScope || Model27).get(item.objectId);
39246
39390
  m._class = collectionName2;
39247
- if (collectionName2 !== void 0 && CloudStore7._collections[collectionName2] !== void 0)
39248
- var schema = CloudStore7._collections[collectionName2].schema;
39391
+ var schema = _schemaOf(collectionName2);
39249
39392
  for (var key in item) {
39250
39393
  if (key === "objectId" || key === "ACL") continue;
39251
39394
  var _type = schema && schema.properties && schema.properties[key] ? schema.properties[key].type : void 0;
39252
39395
  if (_type === void 0 && item[key] && item[key].__type === "Pointer" && item[key].objectId !== void 0) {
39253
39396
  _type = "Pointer";
39254
39397
  }
39398
+ if (_type === void 0 && (key === "createdAt" || key === "updatedAt")) _type = "Date";
39255
39399
  const value2 = _deserializeJSON(item[key], _type, modelScope);
39256
39400
  if (Array.isArray(value2) && sameList(m.get(key), value2)) continue;
39257
39401
  m.set(key, value2);
@@ -39468,8 +39612,19 @@ function convertVisualFilter(query, options) {
39468
39612
  });
39469
39613
  return Object.keys(where2).length === 0 ? void 0 : where2;
39470
39614
  }
39615
+ function instantOf(operand) {
39616
+ let at;
39617
+ if (operand instanceof Date) at = operand.getTime();
39618
+ else if (operand && operand.__type === "Date" && typeof operand.iso === "string") at = Date.parse(operand.iso);
39619
+ else if (typeof operand === "string") at = Date.parse(operand);
39620
+ return at === void 0 || Number.isNaN(at) ? void 0 : at;
39621
+ }
39471
39622
  function matchesOperator(value2, op, condition) {
39472
39623
  const operand = condition[op];
39624
+ if (value2 instanceof Date && Object.prototype.hasOwnProperty.call(DATE_COMPARISONS, op)) {
39625
+ const at = instantOf(operand);
39626
+ if (at !== void 0) return DATE_COMPARISONS[op](value2.getTime(), at);
39627
+ }
39473
39628
  switch (op) {
39474
39629
  case "$eq":
39475
39630
  return operand && operand.__type === "Pointer" ? value2 === operand.objectId : value2 == operand;
@@ -39548,8 +39703,8 @@ function convertVisualSorting(sorting) {
39548
39703
  }
39549
39704
  function convertFilterOp(filter2, options) {
39550
39705
  try {
39551
- const resolved2 = resolveRelatedClasses(filter2, options.modelScope);
39552
- return toParseWhere(resolved2, {
39706
+ const resolved3 = resolveRelatedClasses(filter2, options.modelScope);
39707
+ return toParseWhere(resolved3, {
39553
39708
  backend: backendType(),
39554
39709
  schema: schemaFor(options.collectionName)
39555
39710
  });
@@ -39561,13 +39716,21 @@ function convertFilterOp(filter2, options) {
39561
39716
  throw e;
39562
39717
  }
39563
39718
  }
39564
- var CloudStore, ModelImport2, Model5;
39719
+ var CloudStore, ModelImport2, Model5, DATE_COMPARISONS;
39565
39720
  var init_queryutils = __esm({
39566
39721
  "../noodl-runtime/src/api/queryutils.ts"() {
39567
39722
  init_translators2();
39568
39723
  CloudStore = require_cloudstore();
39569
39724
  ModelImport2 = require_model2();
39570
39725
  Model5 = ModelImport2;
39726
+ DATE_COMPARISONS = {
39727
+ $eq: (a, b) => a === b,
39728
+ $ne: (a, b) => a !== b,
39729
+ $lt: (a, b) => a < b,
39730
+ $lte: (a, b) => a <= b,
39731
+ $gt: (a, b) => a > b,
39732
+ $gte: (a, b) => a >= b
39733
+ };
39571
39734
  }
39572
39735
  });
39573
39736
 
@@ -40148,8 +40311,9 @@ var require_dbcollectionnode2 = __commonJS({
40148
40311
  this.setCollection(_c);
40149
40312
  this.sendSignalOnOutput("fetched");
40150
40313
  },
40151
- error: (err) => {
40152
- if (this._internal.collection === void 0) this.setCollection(_c);
40314
+ error: (err, status) => {
40315
+ const refused = status === 401 || status === 403;
40316
+ if (refused || this._internal.collection === void 0) this.setCollection(_c);
40153
40317
  this.setError(err || "Failed to fetch.");
40154
40318
  }
40155
40319
  });
@@ -40973,7 +41137,9 @@ var require_dbmodelnode2 = __commonJS({
40973
41137
  includeChangedSignals: true
40974
41138
  }) : [];
40975
41139
  ports.push(...fieldPorts);
40976
- ports.push(...recordWiredFieldPorts(node, fieldPorts, { plug: "output" }));
41140
+ const datePorts = recordBuiltInDatePorts(ctx, fieldPorts, { includeChangedSignals: true });
41141
+ ports.push(...datePorts);
41142
+ ports.push(...recordWiredFieldPorts(node, [...fieldPorts, ...datePorts], { plug: "output" }));
40977
41143
  sendSchemaPorts(editorConnection, node.id, ports, { staticPorts: staticPortNames(ModelNodeDefinition3) });
40978
41144
  }
40979
41145
  var DbModelNodeModule = {
@@ -45169,6 +45335,7 @@ var require_mapcollectionnode = __commonJS({
45169
45335
  "../noodl-runtime/src/nodes/std-library/data/mapcollectionnode.ts"(exports2, module2) {
45170
45336
  "use strict";
45171
45337
  init_outcome();
45338
+ init_printedcode();
45172
45339
  init_itemsinput();
45173
45340
  var Node17 = require_node2();
45174
45341
  var Collection5 = require_collection();
@@ -45287,7 +45454,7 @@ var require_mapcollectionnode = __commonJS({
45287
45454
  compileMapScript: function(code) {
45288
45455
  this._internal.mapCode = code;
45289
45456
  try {
45290
- this._internal.mapFunc = new Function("map", "object", code);
45457
+ this._internal.mapFunc = compileCode(MAP_COLLECTION_PARAMS, code);
45291
45458
  } catch (e) {
45292
45459
  this._internal.mapFunc = void 0;
45293
45460
  this._internal.mapCompileError = e.message || String(e);
@@ -47774,12 +47941,12 @@ var require_datetostring = __commonJS({
47774
47941
  if (rendered.indexOf(needle) === -1) return;
47775
47942
  rendered = rendered.split(needle).join(render());
47776
47943
  };
47777
- const named2 = (options) => new Intl.DateTimeFormat(locale, zone ? { ...options, timeZone: zone } : options).format(t);
47944
+ const named3 = (options) => new Intl.DateTimeFormat(locale, zone ? { ...options, timeZone: zone } : options).format(t);
47778
47945
  const hours12 = (fields.hours + 11) % 12 + 1;
47779
47946
  const meridiem = fields.hours < 12 ? "am" : "pm";
47780
- substitute("dayName", () => named2({ weekday: "long" }));
47781
- substitute("dayShort", () => named2({ weekday: "short" }));
47782
- substitute("monthName", () => named2({ month: "long" }));
47947
+ substitute("dayName", () => named3({ weekday: "long" }));
47948
+ substitute("dayShort", () => named3({ weekday: "short" }));
47949
+ substitute("monthName", () => named3({ month: "long" }));
47783
47950
  substitute("hours12", () => ("0" + hours12).slice(-2));
47784
47951
  substitute("h12", () => String(hours12));
47785
47952
  substitute("ampm", () => meridiem);
@@ -50467,9 +50634,9 @@ var init_EntityDecoder = __esm({
50467
50634
  replacement = ncrResult;
50468
50635
  tier = LIMIT_TIER_BASE;
50469
50636
  } else {
50470
- const resolved2 = this._resolveName(token);
50471
- replacement = resolved2?.value;
50472
- tier = resolved2?.tier;
50637
+ const resolved3 = this._resolveName(token);
50638
+ replacement = resolved3?.value;
50639
+ tier = resolved3?.tier;
50473
50640
  }
50474
50641
  if (replacement === void 0) {
50475
50642
  i2++;
@@ -51147,7 +51314,7 @@ var init_DocTypeReader = __esm({
51147
51314
  });
51148
51315
 
51149
51316
  // ../../node_modules/anynum/digitTable.js
51150
- var SCRIPT_ZEROS, NOT_DIGIT, HIGH_MAP, LOW_MAX, LOW_MIN, TABLE_OFFSET, TABLE_SIZE, TABLE;
51317
+ var SCRIPT_ZEROS, NOT_DIGIT, HIGH_MAP, LOW_MAX, LOW_MIN, TABLE_OFFSET, TABLE_SIZE, TABLE2;
51151
51318
  var init_digitTable = __esm({
51152
51319
  "../../node_modules/anynum/digitTable.js"() {
51153
51320
  SCRIPT_ZEROS = [
@@ -51287,12 +51454,12 @@ var init_digitTable = __esm({
51287
51454
  LOW_MIN = 1632;
51288
51455
  TABLE_OFFSET = LOW_MIN;
51289
51456
  TABLE_SIZE = LOW_MAX - LOW_MIN + 1;
51290
- TABLE = new Uint8Array(TABLE_SIZE).fill(NOT_DIGIT);
51457
+ TABLE2 = new Uint8Array(TABLE_SIZE).fill(NOT_DIGIT);
51291
51458
  for (const zero of SCRIPT_ZEROS) {
51292
51459
  for (let d = 0; d < 10; d++) {
51293
51460
  const cp = zero + d;
51294
51461
  if (cp <= LOW_MAX) {
51295
- TABLE[cp - TABLE_OFFSET] = d;
51462
+ TABLE2[cp - TABLE_OFFSET] = d;
51296
51463
  } else {
51297
51464
  HIGH_MAP.set(cp, d);
51298
51465
  }
@@ -51330,7 +51497,7 @@ function anynum(str2) {
51330
51497
  }
51331
51498
  continue;
51332
51499
  }
51333
- if (TABLE[cc - TABLE_OFFSET] !== NOT_DIGIT || MINUS_SET.has(cc)) {
51500
+ if (TABLE2[cc - TABLE_OFFSET] !== NOT_DIGIT || MINUS_SET.has(cc)) {
51334
51501
  firstHit = i2;
51335
51502
  break;
51336
51503
  }
@@ -51368,7 +51535,7 @@ function anynum(str2) {
51368
51535
  chars.push("-");
51369
51536
  continue;
51370
51537
  }
51371
- const d = TABLE[cc - TABLE_OFFSET];
51538
+ const d = TABLE2[cc - TABLE_OFFSET];
51372
51539
  chars.push(d !== NOT_DIGIT ? String.fromCharCode(d + 48) : str2[i2]);
51373
51540
  }
51374
51541
  return chars.join("");
@@ -54316,9 +54483,9 @@ function firstOf(...values2) {
54316
54483
  function toISODate(value2) {
54317
54484
  const raw = text(value2).trim().replace(/\s*\([^)]*\)$/, "");
54318
54485
  if (!raw) return null;
54319
- const named2 = /\s([A-Z]{1,5})$/.exec(raw);
54320
- if (named2 && ZONE_NAMES_READ.indexOf(named2[1]) === -1) return null;
54321
- const zoned = !!named2 || /(?:Z|[+-]\d{2}:?\d{2})$/.test(raw);
54486
+ const named3 = /\s([A-Z]{1,5})$/.exec(raw);
54487
+ if (named3 && ZONE_NAMES_READ.indexOf(named3[1]) === -1) return null;
54488
+ const zoned = !!named3 || /(?:Z|[+-]\d{2}:?\d{2})$/.test(raw);
54322
54489
  const asUTC = zoned || /^\d{4}-\d{2}-\d{2}$/.test(raw) ? raw : /^\d{4}-\d{2}-\d{2}T/.test(raw) ? raw + "Z" : raw + " GMT";
54323
54490
  const ms = Date.parse(asUTC);
54324
54491
  return isNaN(ms) ? null : new Date(ms).toISOString();
@@ -57377,9 +57544,9 @@ function captureGroups(m) {
57377
57544
  }
57378
57545
  function namedCaptureGroups(m) {
57379
57546
  const out = {};
57380
- const named2 = m.groups;
57381
- if (named2) {
57382
- for (const key in named2) out[key] = named2[key] === void 0 ? "" : named2[key];
57547
+ const named3 = m.groups;
57548
+ if (named3) {
57549
+ for (const key in named3) out[key] = named3[key] === void 0 ? "" : named3[key];
57383
57550
  }
57384
57551
  return out;
57385
57552
  }
@@ -60977,6 +61144,7 @@ var require_globalstoresubscribenode = __commonJS({
60977
61144
  description: "The watched value: one key gives that key, several give an object of just those keys, none gives the whole store",
60978
61145
  group: "Data",
60979
61146
  getter: function() {
61147
+ if (!this._internal.unsubscribe) return void 0;
60980
61148
  return this.projectValue(globalStoreManager.getState(this._internal.storeName));
60981
61149
  }
60982
61150
  },
@@ -68312,8 +68480,8 @@ function sourceName(el) {
68312
68480
  return label.length > 60 ? label.slice(0, 57) + "\u2026" : label || "item";
68313
68481
  }
68314
68482
  function zoneName(zone, el) {
68315
- const named2 = String(zone._internal.dropZoneName || "").trim();
68316
- if (named2) return named2;
68483
+ const named3 = String(zone._internal.dropZoneName || "").trim();
68484
+ if (named3) return named3;
68317
68485
  const label = el && el.getAttribute("aria-label");
68318
68486
  if (label) return label;
68319
68487
  const all = orderedZones(zone);
@@ -72721,8 +72889,8 @@ function readColor(value2, depth = 0) {
72721
72889
  const asVar = VAR_FN.exec(text2);
72722
72890
  if (asVar) {
72723
72891
  if (depth >= 8) return null;
72724
- const resolved2 = cssVariableValue(asVar[1]);
72725
- if (resolved2) return readColor(resolved2, depth + 1);
72892
+ const resolved3 = cssVariableValue(asVar[1]);
72893
+ if (resolved3) return readColor(resolved3, depth + 1);
72726
72894
  if (asVar[2] !== void 0) return readColor(asVar[2], depth + 1);
72727
72895
  return null;
72728
72896
  }
@@ -76852,7 +77020,14 @@ var init_TextInput = __esm({
76852
77020
  ref: props.useLabel ? void 0 : noodlRootRef(this.props.noodlNode),
76853
77021
  ...props.useLabel ? void 0 : dataAttributeProps(props.dom),
76854
77022
  style: props.useLabel ? { ...clearedRootStyles(style2), ...inputWrapperStyle } : inputWrapperStyle,
76855
- "noodl-style-tag": "inputWrapper"
77023
+ "noodl-style-tag": "inputWrapper",
77024
+ onMouseDown: (e) => {
77025
+ const field = this.ref.current;
77026
+ if (!field || !props.enabled || e.button !== 0 || field.contains(e.target)) return;
77027
+ e.preventDefault();
77028
+ window.addEventListener("click", preventGlobalFocusChange, true);
77029
+ this.focus();
77030
+ }
76856
77031
  },
76857
77032
  props.useIcon && props.iconPlacement === "left" ? _renderIcon() : null,
76858
77033
  inputContent,
@@ -82051,18 +82226,18 @@ function Columns(props) {
82051
82226
  return () => observer.disconnect();
82052
82227
  }, [masonry, children.length, containerWidth]);
82053
82228
  const columnLayout = readColumnLayoutString(props.layoutString);
82054
- const resolved2 = columnLayout === null ? null : resolveColumnLayout(columnLayout, props, containerWidth, children.length);
82055
- const breakpoint = resolved2?.breakpoint ?? "Default";
82229
+ const resolved3 = columnLayout === null ? null : resolveColumnLayout(columnLayout, props, containerWidth, children.length);
82230
+ const breakpoint = resolved3?.breakpoint ?? "Default";
82056
82231
  (0, import_react17.useEffect)(() => {
82057
82232
  props.onBreakpointChanged?.(breakpoint);
82058
82233
  if (breakpoint === "Medium") props.onAtMedium?.();
82059
82234
  else if (breakpoint === "Small") props.onAtSmall?.();
82060
82235
  }, [breakpoint]);
82061
82236
  if (!props.children) return null;
82062
- if (resolved2 === null) {
82237
+ if (resolved3 === null) {
82063
82238
  return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, props.children);
82064
82239
  }
82065
- const { layout, columnAmount, fractionSize } = resolved2;
82240
+ const { layout, columnAmount, fractionSize } = resolved3;
82066
82241
  columnAmountRef.current = columnAmount;
82067
82242
  const columnLefts = masonry ? computeColumnOffsets(layout, fractionSize) : null;
82068
82243
  const packed = masonry && masonryOffsets !== null && masonryOffsets.tops.length === children.length;
@@ -98015,8 +98190,8 @@ var init_parentcomponentobject = __esm({
98015
98190
  const self2 = this.nodeScope.componentOwner;
98016
98191
  const wanted = this._internal.targetComponent;
98017
98192
  if (wanted) {
98018
- const named2 = findAncestorWithName(self2, wanted);
98019
- if (!named2) {
98193
+ const named3 = findAncestorWithName(self2, wanted);
98194
+ if (!named3) {
98020
98195
  this._internal.parentComponentName = void 0;
98021
98196
  resolvedTargets2.report(this, void 0);
98022
98197
  this.reportMiss("parent-component-object/target-not-found", 'No ancestor component named "' + wanted + '"', {
@@ -98025,7 +98200,7 @@ var init_parentcomponentobject = __esm({
98025
98200
  });
98026
98201
  return;
98027
98202
  }
98028
- if (!COMPONENT_OBJECT_TYPES.some((type) => named2.nodeScope.getNodesWithType(type).length > 0)) {
98203
+ if (!COMPONENT_OBJECT_TYPES.some((type) => named3.nodeScope.getNodesWithType(type).length > 0)) {
98029
98204
  this._internal.parentComponentName = void 0;
98030
98205
  resolvedTargets2.report(this, void 0);
98031
98206
  this.reportMiss(
@@ -98035,11 +98210,11 @@ var init_parentcomponentobject = __esm({
98035
98210
  );
98036
98211
  return;
98037
98212
  }
98038
- this._internal.parentComponentName = named2.name;
98213
+ this._internal.parentComponentName = named3.name;
98039
98214
  this._internal.lastMissCode = void 0;
98040
98215
  this._internal.lastError = void 0;
98041
- resolvedTargets2.report(this, named2.name);
98042
- return "componentState" + named2.getInstanceId();
98216
+ resolvedTargets2.report(this, named3.name);
98217
+ return "componentState" + named3.getInstanceId();
98043
98218
  }
98044
98219
  const parent = findAncestorWithComponentObject(self2);
98045
98220
  if (!parent) {
@@ -98218,22 +98393,22 @@ var init_setparentcomponentobjectproperties = __esm({
98218
98393
  const self2 = this.nodeScope.componentOwner;
98219
98394
  const wanted = this._internal.targetComponent;
98220
98395
  if (wanted) {
98221
- const named2 = findAncestorWithName(self2, wanted);
98222
- if (!named2) {
98396
+ const named3 = findAncestorWithName(self2, wanted);
98397
+ if (!named3) {
98223
98398
  return {
98224
98399
  missCode: "set-parent-component-object-properties/target-not-found",
98225
98400
  missMessage: 'No ancestor component named "' + wanted + '"',
98226
98401
  missDetail: { target: wanted, ancestors: componentAncestorNames(self2) }
98227
98402
  };
98228
98403
  }
98229
- if (!COMPONENT_OBJECT_TYPES.some((type) => named2.nodeScope.getNodesWithType(type).length > 0)) {
98404
+ if (!COMPONENT_OBJECT_TYPES.some((type) => named3.nodeScope.getNodesWithType(type).length > 0)) {
98230
98405
  return {
98231
98406
  missCode: "set-parent-component-object-properties/target-has-no-object",
98232
98407
  missMessage: 'The component "' + wanted + '" has no Component Object node',
98233
98408
  missDetail: { target: wanted }
98234
98409
  };
98235
98410
  }
98236
- return { id: "componentState" + named2.getInstanceId(), name: named2.name };
98411
+ return { id: "componentState" + named3.getInstanceId(), name: named3.name };
98237
98412
  }
98238
98413
  const parent = findAncestorWithComponentObject(self2);
98239
98414
  if (!parent) {
@@ -100538,15 +100713,15 @@ var init_closepopup = __esm({
100538
100713
  const candidates = popups.map((component) => component.name);
100539
100714
  const wanted = this._internal.targetComponent;
100540
100715
  if (wanted) {
100541
- const named2 = popups.find((component) => component.name === wanted);
100542
- if (!named2) {
100716
+ const named3 = popups.find((component) => component.name === wanted);
100717
+ if (!named3) {
100543
100718
  return {
100544
100719
  candidates,
100545
100720
  missCode: "close-popup/target-not-found",
100546
100721
  missMessage: 'This node is not inside a popup named "' + wanted + '"' + (candidates.length ? " \u2014 it is inside: " + candidates.join(", ") : "")
100547
100722
  };
100548
100723
  }
100549
- return { popup: named2, close: named2._popupCloseHandler, candidates };
100724
+ return { popup: named3, close: named3._popupCloseHandler, candidates };
100550
100725
  }
100551
100726
  if (this._internal.closeCallback) {
100552
100727
  return { popup: popups[0], close: this._internal.closeCallback, candidates };
@@ -100958,7 +101133,9 @@ var init_userservice = __esm({
100958
101133
  this.adapter = new ParseAuthAdapter({
100959
101134
  // The module-scope serialiser, exactly as before — `_User` properties have
100960
101135
  // always been serialised against the process-wide Model store.
100961
- serializeObject: (data, collectionName2) => import_cloudstore2.default._serializeObject(data, collectionName2)
101136
+ // P115-HST006-VIEWERTS2554: the third argument (the model scope) is named, undefined, as JavaScript already
101137
+ // passed it: the runtime's generated types declare all three, and the production viewer build type-checks.
101138
+ serializeObject: (data, collectionName2) => import_cloudstore2.default._serializeObject(data, collectionName2, void 0)
100962
101139
  });
100963
101140
  this._bridge(this.adapter);
100964
101141
  if (this._consumeAuthReturn()) return;
@@ -101011,12 +101188,12 @@ var init_userservice = __esm({
101011
101188
  */
101012
101189
  _handle(backendId) {
101013
101190
  if (backendId && backendId !== ACTIVE_BACKEND) {
101014
- const named2 = resolveBackendFromRuntime(backendId);
101015
- return named2 ? named2.handle : void 0;
101191
+ const named3 = resolveBackendFromRuntime(backendId);
101192
+ return named3 ? named3.handle : void 0;
101016
101193
  }
101017
101194
  if (!this.endpoint) {
101018
- const resolved2 = resolveBackendFromRuntime(ACTIVE_BACKEND);
101019
- if (resolved2) return resolved2.handle;
101195
+ const resolved3 = resolveBackendFromRuntime(ACTIVE_BACKEND);
101196
+ if (resolved3) return resolved3.handle;
101020
101197
  }
101021
101198
  return {
101022
101199
  id: "_active_",
@@ -111609,9 +111786,9 @@ var require_fast_uri = __commonJS({
111609
111786
  }
111610
111787
  function resolve5(baseURI, relativeURI, options) {
111611
111788
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
111612
- const resolved2 = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
111789
+ const resolved3 = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
111613
111790
  schemelessOptions.skipEscape = true;
111614
- return serialize(resolved2, schemelessOptions);
111791
+ return serialize(resolved3, schemelessOptions);
111615
111792
  }
111616
111793
  function resolveComponent(base, relative3, options, skipNormalization) {
111617
111794
  const target = {};
@@ -114922,7 +115099,7 @@ var require_package = __commonJS({
114922
115099
  "package.json"(exports2, module2) {
114923
115100
  module2.exports = {
114924
115101
  name: "@nodegx/preview",
114925
- version: "0.2.8",
115102
+ version: "0.2.9",
114926
115103
  description: "Standalone live-preview harness: renders a NodeGX (OpenNoodl) v2 project in a browser with no editor process, and reloads it when the files on disk change.",
114927
115104
  license: "GPL-3.0-only",
114928
115105
  homepage: "https://nodegx.io",
@@ -184419,6 +184596,13 @@ var CommentsModel = class extends import_model15.default {
184419
184596
 
184420
184597
  // ../noodl-editor/src/editor/src/models/warningsmodel.ts
184421
184598
  var import_model16 = __toESM(require_model());
184599
+ function sameWarning(a, b) {
184600
+ try {
184601
+ return JSON.stringify(a) === JSON.stringify(b);
184602
+ } catch {
184603
+ return false;
184604
+ }
184605
+ }
184422
184606
  var WarningsModel = class _WarningsModel extends import_model16.default {
184423
184607
  constructor() {
184424
184608
  super();
@@ -184431,13 +184615,23 @@ var WarningsModel = class _WarningsModel extends import_model16.default {
184431
184615
  static {
184432
184616
  this.instance = new _WarningsModel();
184433
184617
  }
184618
+ /**
184619
+ * P132-HIDDENPANELCHURN: a set that changes nothing says nothing. `readNameList` clears its warning on every read,
184620
+ * and the Components panel reads page info (so names) on every `warningsChanged`: when a clear of a warning that was
184621
+ * not there still announced a change, the two fed each other once per `setTimeout(1)`, ~480 times a second, for as
184622
+ * long as a project was open (the panel, the top bar and every mounted dialog re-rendering each time).
184623
+ * The same object set again still announces: its owner may have changed it in place.
184624
+ */
184434
184625
  setWarning(ref, warning) {
184435
184626
  var w = this.getWarningsForRef(ref, warning !== void 0);
184436
184627
  if (!warning) {
184437
- if (w) delete w[ref.key];
184628
+ if (!w || w[ref.key] === void 0) return;
184629
+ delete w[ref.key];
184438
184630
  } else {
184439
184631
  warning.level = warning.level || "warning";
184632
+ const had = w[ref.key];
184440
184633
  w[ref.key] = { ref, warning };
184634
+ if (had && had.warning !== warning && sameWarning(had.warning, warning)) return;
184441
184635
  }
184442
184636
  this.scheduleNotifyChanged();
184443
184637
  }
@@ -189412,11 +189606,11 @@ var TokenResolver = class _TokenResolver {
189412
189606
  }
189413
189607
  const token = this.tokens.get(tokenName);
189414
189608
  if (!token) return void 0;
189415
- const resolved2 = this._resolveValue(token.value, depth);
189416
- if (resolved2 !== void 0) {
189417
- this.cache.set(tokenName, resolved2);
189609
+ const resolved3 = this._resolveValue(token.value, depth);
189610
+ if (resolved3 !== void 0) {
189611
+ this.cache.set(tokenName, resolved3);
189418
189612
  }
189419
- return resolved2;
189613
+ return resolved3;
189420
189614
  }
189421
189615
  /**
189422
189616
  * P102 CMP-001 §3 — resolve every `var()` **inside** a value, so a preview can paint it.
@@ -191324,11 +191518,11 @@ var ParameterValueResolver = class {
191324
191518
  * ```
191325
191519
  */
191326
191520
  static toString(paramValue) {
191327
- const resolved2 = this.resolve(paramValue, "display" /* Display */);
191328
- if (typeof resolved2 === "object" && resolved2 !== null) {
191521
+ const resolved3 = this.resolve(paramValue, "display" /* Display */);
191522
+ if (typeof resolved3 === "object" && resolved3 !== null) {
191329
191523
  return "";
191330
191524
  }
191331
- return String(resolved2 ?? "");
191525
+ return String(resolved3 ?? "");
191332
191526
  }
191333
191527
  /**
191334
191528
  * Safely converts any parameter value to a number for display.
@@ -191347,15 +191541,15 @@ var ParameterValueResolver = class {
191347
191541
  * ```
191348
191542
  */
191349
191543
  static toNumber(paramValue) {
191350
- const resolved2 = this.resolve(paramValue, "display" /* Display */);
191351
- if (typeof resolved2 === "object" && resolved2 !== null) {
191544
+ const resolved3 = this.resolve(paramValue, "display" /* Display */);
191545
+ if (typeof resolved3 === "object" && resolved3 !== null) {
191352
191546
  return void 0;
191353
191547
  }
191354
191548
  const rawValue = isExpressionParameter(paramValue) ? paramValue.fallback : paramValue;
191355
191549
  if (rawValue === null || rawValue === void 0) {
191356
191550
  return void 0;
191357
191551
  }
191358
- const num = Number(resolved2);
191552
+ const num = Number(resolved3);
191359
191553
  return isNaN(num) ? void 0 : num;
191360
191554
  }
191361
191555
  /**
@@ -191375,11 +191569,11 @@ var ParameterValueResolver = class {
191375
191569
  * ```
191376
191570
  */
191377
191571
  static toBoolean(paramValue) {
191378
- const resolved2 = this.resolve(paramValue, "display" /* Display */);
191379
- if (typeof resolved2 === "object" && resolved2 !== null) {
191572
+ const resolved3 = this.resolve(paramValue, "display" /* Display */);
191573
+ if (typeof resolved3 === "object" && resolved3 !== null) {
191380
191574
  return false;
191381
191575
  }
191382
- return Boolean(resolved2);
191576
+ return Boolean(resolved3);
191383
191577
  }
191384
191578
  /**
191385
191579
  * Checks if a parameter value is an expression parameter.
@@ -191425,7 +191619,7 @@ var NodeGraphNode = class _NodeGraphNode extends import_model22.default {
191425
191619
  }
191426
191620
  /** Get the label of the node */
191427
191621
  get label() {
191428
- if (!this._label) return this.type.labelForNode(this);
191622
+ if (!this._label) return this.derivedTitle ?? this.type.labelForNode(this);
191429
191623
  return this._label;
191430
191624
  }
191431
191625
  /** Set the label of the node */
@@ -191433,6 +191627,12 @@ var NodeGraphNode = class _NodeGraphNode extends import_model22.default {
191433
191627
  this._label = value2;
191434
191628
  this.notifyListeners("labelChanged");
191435
191629
  }
191630
+ /** Set the derived title. `undefined` clears it. */
191631
+ setDerivedTitle(title) {
191632
+ if (this.derivedTitle === title) return;
191633
+ this.derivedTitle = title;
191634
+ this.notifyListeners("derivedTitleChanged");
191635
+ }
191436
191636
  /** Set the runtime sub-label. `undefined` clears it. */
191437
191637
  setRuntimeSubLabel(subLabel) {
191438
191638
  if (this.runtimeSubLabel === subLabel) return;
@@ -194046,9 +194246,9 @@ function conditionIsUnsatisfied(condition, params) {
194046
194246
  return result2 === false;
194047
194247
  }
194048
194248
  function resolveAgainstDefaults(params, defaults) {
194049
- const resolved2 = { ...defaults };
194050
- for (const [name2, value2] of Object.entries(params)) if (value2 !== void 0) resolved2[name2] = value2;
194051
- return resolved2;
194249
+ const resolved3 = { ...defaults };
194250
+ for (const [name2, value2] of Object.entries(params)) if (value2 !== void 0) resolved3[name2] = value2;
194251
+ return resolved3;
194052
194252
  }
194053
194253
  function conditionForInput(groups, portName) {
194054
194254
  if (!groups) return void 0;
@@ -194087,6 +194287,7 @@ var NUMBER_WITH_UNIT = /^\s*(-?\d+(?:\.\d+)?)\s*(px|%|vw|vh|em|rem|deg|s|ms)\s*$
194087
194287
  function isPlainObject2(value2) {
194088
194288
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
194089
194289
  }
194290
+ var TOKEN_IN_VALUE = /var\(--[A-Za-z0-9_-]+\)/;
194090
194291
  function isTokenReference2(value2) {
194091
194292
  return typeof value2 === "string" && value2.startsWith("var(");
194092
194293
  }
@@ -194158,10 +194359,11 @@ function unitsFormat(type) {
194158
194359
  suggestion: JSON.stringify({ value: Number(parsed[1]), unit: parsed[2] })
194159
194360
  };
194160
194361
  }
194362
+ const token = typeof value2 === "string" ? TOKEN_IN_VALUE.exec(value2)?.[0] : void 0;
194161
194363
  return {
194162
194364
  severity: "error",
194163
- message: `expects a number or { "value", "unit" } object. Got ${describeValue2(value2)}.`,
194164
- suggestion: JSON.stringify({ value: 16, unit: unit2 })
194365
+ message: `expects a number, a { "value", "unit" } object or a var(--token) reference. Got ${describeValue2(value2)}.` + (token ? ` This port takes a token alone, not inside an expression: use ${token}, or add a token that holds the size you want.` : ""),
194366
+ suggestion: JSON.stringify(token ?? { value: 16, unit: unit2 })
194165
194367
  };
194166
194368
  }
194167
194369
  };
@@ -194631,13 +194833,13 @@ function checkParameterValues(nodes, catalog, options) {
194631
194833
  });
194632
194834
  }
194633
194835
  if (dynamicSkips.length > 0) {
194634
- const named2 = dynamicSkips.map((n) => `"${n}"`).join(", ");
194836
+ const named3 = dynamicSkips.map((n) => `"${n}"`).join(", ");
194635
194837
  const rawNote = catalog.dynamicPortNote(node.type) ?? "this node determines ports at runtime";
194636
194838
  const note = /[.!?]$/.test(rawNote.trim()) ? rawNote.trim() : `${rawNote.trim()}.`;
194637
194839
  diagnostics.push({
194638
194840
  code: "dynamic-port-skipped" /* DynamicPortSkipped */,
194639
194841
  severity: "info",
194640
- message: `${dynamicSkips.length === 1 ? "Parameter" : "Parameters"} ${named2} on ${node.type} ${dynamicSkips.length === 1 ? "names" : "name"} no port the catalog can see, and ${dynamicSkips.length === 1 ? "it was" : "they were"} not checked: ` + note + " So this node is unverified by that check rather than verified as correct.",
194842
+ message: `${dynamicSkips.length === 1 ? "Parameter" : "Parameters"} ${named3} on ${node.type} ${dynamicSkips.length === 1 ? "names" : "name"} no port the catalog can see, and ${dynamicSkips.length === 1 ? "it was" : "they were"} not checked: ` + note + " So this node is unverified by that check rather than verified as correct.",
194641
194843
  location: {
194642
194844
  component,
194643
194845
  nodeId: node.id,
@@ -194832,8 +195034,8 @@ function parentAxis(parent, catalog) {
194832
195034
  const declared2 = PARENT_MAIN_AXIS[parent.type];
194833
195035
  if (declared2 === void 0) return void 0;
194834
195036
  if (declared2 !== "fromFlexDirection") return declared2;
194835
- const resolved2 = resolveAgainstDefaults(parent.parameters ?? {}, catalog.inputDefaults(parent.type));
194836
- const flexDirection = resolved2["flexDirection"];
195037
+ const resolved3 = resolveAgainstDefaults(parent.parameters ?? {}, catalog.inputDefaults(parent.type));
195038
+ const flexDirection = resolved3["flexDirection"];
194837
195039
  if (flexDirection === "row") return "row";
194838
195040
  if (flexDirection === "column" || flexDirection === void 0) return "column";
194839
195041
  return void 0;
@@ -196476,9 +196678,9 @@ var dialogWithoutName = {
196476
196678
  if (typeof accessibleName === "string" && accessibleName.trim() !== "") continue;
196477
196679
  const target = node.parameters?.target;
196478
196680
  if (typeof target !== "string" || target.trim() === "") continue;
196479
- const resolved2 = byName.has(target) ? target : void 0;
196480
- if (resolved2 === void 0) continue;
196481
- if (subtreeHasHeading(resolved2, byName, /* @__PURE__ */ new Set())) continue;
196681
+ const resolved3 = byName.has(target) ? target : void 0;
196682
+ if (resolved3 === void 0) continue;
196683
+ if (subtreeHasHeading(resolved3, byName, /* @__PURE__ */ new Set())) continue;
196482
196684
  diagnostics.push({
196483
196685
  code: "dialog-without-name" /* DialogWithoutName */,
196484
196686
  severity: "warning",
@@ -196660,9 +196862,9 @@ var CODE_PREFIX = "const Script = (typeof Node !== 'undefined')?Node:undefined;\
196660
196862
  var PARAMS2 = ["Inputs", "Outputs", "Noodl", "Component", "Scripts"];
196661
196863
  function functionScriptCompileError(script) {
196662
196864
  try {
196663
- const AsyncFunction = Object.getPrototypeOf(async function() {
196865
+ const AsyncFunction2 = Object.getPrototypeOf(async function() {
196664
196866
  }).constructor;
196665
- new AsyncFunction(...PARAMS2, CODE_PREFIX + script);
196867
+ new AsyncFunction2(...PARAMS2, CODE_PREFIX + script);
196666
196868
  return void 0;
196667
196869
  } catch (e) {
196668
196870
  const message = e instanceof Error ? e.message : String(e);
@@ -197029,6 +197231,90 @@ var rowOfWordsFillsItsColumn = {
197029
197231
  }
197030
197232
  };
197031
197233
 
197234
+ // ../noodl-editor/src/editor/src/validation/rules/bandWithoutShell.ts
197235
+ var GROUP2 = "Group";
197236
+ var resolved2 = (node, catalog) => resolveAgainstDefaults(node.parameters ?? {}, catalog.inputDefaults(node.type));
197237
+ var named2 = (nodes) => nodes.slice(0, 4).map((n) => n.label ? `"${n.label}"` : n.type).join(", ") + (nodes.length > 4 ? ", \u2026" : "");
197238
+ var isSet2 = (value2) => value2 !== void 0 && value2 !== null && value2 !== "" && value2 !== 0;
197239
+ function isFullWidth(value2) {
197240
+ if (widthIsPercentage(value2) !== true) return false;
197241
+ const n = typeof value2 === "object" && value2 !== null ? value2.value : parseFloat(String(value2));
197242
+ return Number(n) >= 100;
197243
+ }
197244
+ function spans(params) {
197245
+ return isFullWidth(params["width"]) && !isSet2(params["maxWidth"]) && !isSet2(params["paddingLeft"]) && !isSet2(params["paddingRight"]);
197246
+ }
197247
+ var isCard = (params) => isSet2(params["borderRadius"]) || painted(params["borderStyle"]);
197248
+ var SECTION_ELEMENTS = /* @__PURE__ */ new Set(["section", "header", "footer"]);
197249
+ var painted = (value2) => isSet2(value2) && value2 !== "transparent" && value2 !== "none";
197250
+ function isBand(node, catalog) {
197251
+ if (node.type !== GROUP2) return false;
197252
+ const params = resolved2(node, catalog);
197253
+ if (!spans(params)) return false;
197254
+ if ((params["flexDirection"] ?? "column") !== "column") return false;
197255
+ if (params["alignItems"] !== "center") return false;
197256
+ if (params["position"] === "absolute" || params["position"] === "fixed") return false;
197257
+ if (isCard(params)) return false;
197258
+ return isSet2(params["paddingTop"]) || isSet2(params["paddingBottom"]) || painted(params["backgroundColor"]) || painted(params["backgroundGradient"]) || painted(params["backgroundImage"]) || SECTION_ELEMENTS.has(String(params["as"] ?? ""));
197259
+ }
197260
+ var bandWithoutShell = {
197261
+ code: "band-without-shell" /* BandWithoutShell */,
197262
+ description: "A full-width band holds its content directly instead of inside one shell, so the content runs to the window edge.",
197263
+ defaultEnabled: true,
197264
+ run(ctx) {
197265
+ const out = [];
197266
+ for (const { component, nodeById } of ctx.components) {
197267
+ const inFlowChildren2 = (parent) => (parent.children ?? []).map((id) => nodeById.get(id)).filter((n) => {
197268
+ if (!n) return false;
197269
+ if (isComponentRef(n.type)) return true;
197270
+ if (!ctx.catalog.getNode(n.type)?.isVisual) return false;
197271
+ const p = resolved2(n, ctx.catalog);
197272
+ return p["position"] !== "absolute" && p["position"] !== "fixed";
197273
+ });
197274
+ const guarded = (n, depth = 0) => {
197275
+ if (isComponentRef(n.type)) return true;
197276
+ if (n.type !== GROUP2) return false;
197277
+ const p = resolved2(n, ctx.catalog);
197278
+ if (isSet2(p["maxWidth"]) || isSet2(p["paddingLeft"]) || isSet2(p["paddingRight"])) return true;
197279
+ const kids = inFlowChildren2(n);
197280
+ return depth < 4 && kids.length > 0 && kids.every((k) => guarded(k, depth + 1));
197281
+ };
197282
+ for (const band of component.nodes) {
197283
+ if (!isBand(band, ctx.catalog)) continue;
197284
+ let placed = true;
197285
+ for (let up = band.parent ? nodeById.get(band.parent) : void 0; up; up = up.parent ? nodeById.get(up.parent) : void 0) {
197286
+ if (up.type === "Page") break;
197287
+ const p = up.type === GROUP2 ? resolved2(up, ctx.catalog) : void 0;
197288
+ if (!p || !spans(p) || isCard(p)) {
197289
+ placed = false;
197290
+ break;
197291
+ }
197292
+ }
197293
+ if (!placed) continue;
197294
+ const inside = inFlowChildren2(band);
197295
+ if (inside.length === 0) continue;
197296
+ if (inside.some((n) => isBand(n, ctx.catalog))) continue;
197297
+ const bare = inside.filter((n) => !guarded(n));
197298
+ if (bare.length === 0) continue;
197299
+ const what = bare.length === inside.length && inside.length > 1 ? `it holds ${inside.length} things directly (${named2(inside)}) instead of one shell` : `${named2(bare)} ${bare.length === 1 ? "sits" : "sit"} in it outside a shell`;
197300
+ out.push({
197301
+ code: "band-without-shell" /* BandWithoutShell */,
197302
+ severity: "warning",
197303
+ message: `This is a full-width band (a section of the page), but ${what}, so its words and pictures run to the edge of the window on a desktop. Put everything it holds inside ONE Group with the style vocabulary's "shell" look (maxWidth 1200px, paddingLeft and paddingRight var(--space-6), sizeMode contentHeight), and make that Group the band's only child.`,
197304
+ location: {
197305
+ component: component.name,
197306
+ nodeId: band.id,
197307
+ nodeType: band.type,
197308
+ ...band.label ? { nodeLabel: band.label } : {}
197309
+ },
197310
+ suggestion: 'one child Group with the "shell" look'
197311
+ });
197312
+ }
197313
+ }
197314
+ return out;
197315
+ }
197316
+ };
197317
+
197032
197318
  // ../noodl-editor/src/editor/src/validation/rules/clickAreaHoldsAControl.ts
197033
197319
  var CONTROL_TYPES = /* @__PURE__ */ new Map([
197034
197320
  ["net.noodl.controls.button", "Button"],
@@ -197200,6 +197486,8 @@ var ALL_RULES = [
197200
197486
  // read from the arrangement like the two above, and live so a person sees it while editing.
197201
197487
  contentRowSplitsItsChildren,
197202
197488
  rowOfWordsFillsItsColumn,
197489
+ // P112 OWN-028 AC3 — beside the two above: a band's content outside a shell, read from the arrangement, live.
197490
+ bandWithoutShell,
197203
197491
  oversizedPage,
197204
197492
  // LEG-002 — last, and deliberately: it is the only rule in the set that
197205
197493
  // reports a matter of legibility rather than of correctness, and a reader
@@ -197429,21 +197717,21 @@ function answering(port) {
197429
197717
  });
197430
197718
  }
197431
197719
  async function keepOwnBackend(projectDir, log2) {
197432
- const named2 = namedBackend(projectDir);
197433
- if (!named2) return { first: { state: "none" }, stop: () => void 0 };
197720
+ const named3 = namedBackend(projectDir);
197721
+ if (!named3) return { first: { state: "none" }, stop: () => void 0 };
197434
197722
  const root2 = backendsRoot();
197435
197723
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
197436
197724
  let child = null;
197437
197725
  let stopped = false;
197438
- const recordFile = path6.join(root2, named2.id, "runtime.json");
197726
+ const recordFile = path6.join(root2, named3.id, "runtime.json");
197439
197727
  const writeRecord = (pid, entry, name2) => {
197440
197728
  const record = {
197441
197729
  version: 1,
197442
- backendId: named2.id,
197730
+ backendId: named3.id,
197443
197731
  backendName: name2,
197444
197732
  pid,
197445
- port: named2.port,
197446
- endpoint: named2.endpoint,
197733
+ port: named3.port,
197734
+ endpoint: named3.endpoint,
197447
197735
  entry,
197448
197736
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
197449
197737
  owner: { kind: "preview", pid: process.pid, startedAt, projectDir },
@@ -197462,20 +197750,20 @@ async function keepOwnBackend(projectDir, log2) {
197462
197750
  }
197463
197751
  };
197464
197752
  const look = async () => {
197465
- const configFile = path6.join(root2, named2.id, "config.json");
197466
- if (!fs5.existsSync(configFile)) return { state: "missing", id: named2.id, root: root2 };
197467
- if (child && child.exitCode === null) return { state: "running", id: named2.id, port: named2.port, owner: "this preview" };
197468
- if (await answering(named2.port)) {
197753
+ const configFile = path6.join(root2, named3.id, "config.json");
197754
+ if (!fs5.existsSync(configFile)) return { state: "missing", id: named3.id, root: root2 };
197755
+ if (child && child.exitCode === null) return { state: "running", id: named3.id, port: named3.port, owner: "this preview" };
197756
+ if (await answering(named3.port)) {
197469
197757
  let owner = "another process";
197470
197758
  try {
197471
197759
  owner = JSON.parse(fs5.readFileSync(recordFile, "utf8"))?.owner?.kind ?? owner;
197472
197760
  } catch {
197473
197761
  }
197474
- return { state: "running", id: named2.id, port: named2.port, owner };
197762
+ return { state: "running", id: named3.id, port: named3.port, owner };
197475
197763
  }
197476
197764
  const entry = resolveServiceEntry();
197477
- if (!entry) return { state: "no-service", id: named2.id };
197478
- let name2 = named2.id;
197765
+ if (!entry) return { state: "no-service", id: named3.id };
197766
+ let name2 = named3.id;
197479
197767
  try {
197480
197768
  name2 = JSON.parse(fs5.readFileSync(configFile, "utf8")).name || name2;
197481
197769
  } catch {
@@ -197484,11 +197772,11 @@ async function keepOwnBackend(projectDir, log2) {
197484
197772
  entry,
197485
197773
  "serve",
197486
197774
  "--data-dir",
197487
- path6.join(root2, named2.id),
197775
+ path6.join(root2, named3.id),
197488
197776
  "--port",
197489
- String(named2.port),
197777
+ String(named3.port),
197490
197778
  "--backend-id",
197491
- named2.id,
197779
+ named3.id,
197492
197780
  "--backend-name",
197493
197781
  name2,
197494
197782
  "--parent-pid",
@@ -197519,7 +197807,7 @@ async function keepOwnBackend(projectDir, log2) {
197519
197807
  proc.kill("SIGKILL");
197520
197808
  } catch {
197521
197809
  }
197522
- return { state: "failed", id: named2.id, why: ready };
197810
+ return { state: "failed", id: named3.id, why: ready };
197523
197811
  }
197524
197812
  child = proc;
197525
197813
  writeRecord(proc.pid, entry, name2);
@@ -197527,13 +197815,13 @@ async function keepOwnBackend(projectDir, log2) {
197527
197815
  if (ownRecord()) fs5.rmSync(recordFile, { force: true });
197528
197816
  if (!stopped) log2(` ! the app's backend stopped; looking again in ${HEARTBEAT_MS / 1e3} s`);
197529
197817
  });
197530
- return { state: "started", id: named2.id, port: named2.port, pid: proc.pid };
197818
+ return { state: "started", id: named3.id, port: named3.port, pid: proc.pid };
197531
197819
  };
197532
197820
  const say = (s, quiet) => {
197533
- if (s.state === "started") log2(` \u2713 started the app's backend (${s.id}) on ${named2.endpoint}`);
197821
+ if (s.state === "started") log2(` \u2713 started the app's backend (${s.id}) on ${named3.endpoint}`);
197534
197822
  else if (s.state === "failed") log2(` \u2717 the app's backend (${s.id}) did not start: ${s.why}`);
197535
197823
  else if (quiet) return;
197536
- else if (s.state === "running") log2(` \u2713 the app's backend (${s.id}) is already running on ${named2.endpoint} (${s.owner})`);
197824
+ else if (s.state === "running") log2(` \u2713 the app's backend (${s.id}) is already running on ${named3.endpoint} (${s.owner})`);
197537
197825
  else if (s.state === "missing")
197538
197826
  log2(` ! the app names a backend (${s.id}) that is not on this machine (${s.root}) \u2014 its saves and records will fail`);
197539
197827
  else if (s.state === "no-service") log2(` ! the app names a backend (${s.id}) but this preview has no backend service to start it with`);