@sdeverywhere/runtime 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,13 +1,30 @@
1
1
  # @sdeverywhere/runtime
2
2
 
3
- This package provides a simplified API around a system dynamics model that
4
- has been produced by [SDEverywhere](https://github.com/climateinteractive/SDEverywhere)
5
- and compiled to a WebAssembly (Wasm) module via [Emscripten](https://emscripten.org).
3
+ This package provides a simplified API around a System Dynamics model as generated by [SDEverywhere](https://github.com/climateinteractive/SDEverywhere) and compiled to a WebAssembly (Wasm) module via [Emscripten](https://emscripten.org).
4
+
5
+ ## Quick Start
6
+
7
+ The best way to get started with SDEverywhere is to follow the [Quick Start](https://github.com/climateinteractive/SDEverywhere#quick-start) instructions.
8
+ If you follow those instructions, the `@sdeverywhere/runtime` package will be added to your project automatically, in which case you can skip the next section and jump straight to the ["Usage"](#usage) section below.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ # npm
14
+ npm install @sdeverywhere/runtime
15
+
16
+ # pnpm
17
+ pnpm add @sdeverywhere/runtime
18
+
19
+ # yarn
20
+ yarn add @sdeverywhere/runtime
21
+ ```
6
22
 
7
23
  ## Usage
8
24
 
9
- NOTE: If you use the `@sdeverywhere/create` package, most of the initialization
10
- steps listed below are already handled for you in the generated `core` package,
25
+ _NOTE:_ If you followed the "Quick Start" instructions and/or used the
26
+ `@sdeverywhere/create` package to generate your project, the initialization
27
+ steps listed below are already implemented for you in the generated `core` package,
11
28
  and you can work directly with a `ModelRunner` and/or `ModelScheduler` instance.
12
29
 
13
30
  ### 1. Initialize the `WasmModel`
package/dist/index.cjs CHANGED
@@ -1,7 +1,21 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
4
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
5
19
  var __export = (target, all) => {
6
20
  for (var name in all)
7
21
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -15,39 +29,75 @@ var __copyProps = (to, from, except, desc) => {
15
29
  return to;
16
30
  };
17
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+ var __async = (__this, __arguments, generator) => {
33
+ return new Promise((resolve, reject) => {
34
+ var fulfilled = (value) => {
35
+ try {
36
+ step(generator.next(value));
37
+ } catch (e) {
38
+ reject(e);
39
+ }
40
+ };
41
+ var rejected = (value) => {
42
+ try {
43
+ step(generator.throw(value));
44
+ } catch (e) {
45
+ reject(e);
46
+ }
47
+ };
48
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
49
+ step((generator = generator.apply(__this, __arguments)).next());
50
+ });
51
+ };
18
52
 
19
53
  // src/index.ts
20
54
  var src_exports = {};
21
55
  __export(src_exports, {
56
+ ModelListing: () => ModelListing,
22
57
  ModelScheduler: () => ModelScheduler,
23
58
  Outputs: () => Outputs,
24
59
  Series: () => Series,
25
60
  WasmBuffer: () => WasmBuffer,
26
61
  WasmModel: () => WasmModel,
62
+ createFloat64WasmBuffer: () => createFloat64WasmBuffer,
27
63
  createInputValue: () => createInputValue,
64
+ createInt32WasmBuffer: () => createInt32WasmBuffer,
28
65
  createWasmModelRunner: () => createWasmModelRunner,
29
66
  initWasmModelAndBuffers: () => initWasmModelAndBuffers,
30
67
  perfElapsed: () => perfElapsed,
31
- perfNow: () => perfNow
68
+ perfNow: () => perfNow,
69
+ updateOutputIndices: () => updateOutputIndices
32
70
  });
33
71
  module.exports = __toCommonJS(src_exports);
34
72
 
35
73
  // src/wasm-model/wasm-buffer.ts
36
74
  var WasmBuffer = class {
37
- constructor(wasmModule, numElements) {
75
+ /**
76
+ * @param wasmModule The `WasmModule` used to initialize the memory.
77
+ * @param byteOffset The byte offset within the wasm heap.
78
+ * @param heapArray The array view on the underlying heap buffer.
79
+ */
80
+ constructor(wasmModule, byteOffset, heapArray) {
38
81
  this.wasmModule = wasmModule;
39
- const sizeOfFloat64 = 8;
40
- const lengthInBytes = numElements * sizeOfFloat64;
41
- this.byteOffset = wasmModule._malloc(lengthInBytes);
42
- const float64Offset = this.byteOffset / sizeOfFloat64;
43
- this.heapArray = wasmModule.HEAPF64.subarray(float64Offset, float64Offset + numElements);
82
+ this.byteOffset = byteOffset;
83
+ this.heapArray = heapArray;
44
84
  }
85
+ /**
86
+ * @return An `ArrType` view on the underlying heap buffer.
87
+ */
45
88
  getArrayView() {
46
89
  return this.heapArray;
47
90
  }
91
+ /**
92
+ * @return The raw address of the underlying heap buffer.
93
+ * @hidden This is intended for use by `WasmModel` only.
94
+ */
48
95
  getAddress() {
49
96
  return this.byteOffset;
50
97
  }
98
+ /**
99
+ * Dispose the buffer by freeing the allocated heap memory.
100
+ */
51
101
  dispose() {
52
102
  if (this.heapArray) {
53
103
  this.wasmModule._free(this.byteOffset);
@@ -56,9 +106,29 @@ var WasmBuffer = class {
56
106
  }
57
107
  }
58
108
  };
109
+ function createInt32WasmBuffer(wasmModule, numElements) {
110
+ const elemSizeInBytes = 4;
111
+ const lengthInBytes = numElements * elemSizeInBytes;
112
+ const byteOffset = wasmModule._malloc(lengthInBytes);
113
+ const elemOffset = byteOffset / elemSizeInBytes;
114
+ const heapArray = wasmModule.HEAP32.subarray(elemOffset, elemOffset + numElements);
115
+ return new WasmBuffer(wasmModule, byteOffset, heapArray);
116
+ }
117
+ function createFloat64WasmBuffer(wasmModule, numElements) {
118
+ const elemSizeInBytes = 8;
119
+ const lengthInBytes = numElements * elemSizeInBytes;
120
+ const byteOffset = wasmModule._malloc(lengthInBytes);
121
+ const elemOffset = byteOffset / elemSizeInBytes;
122
+ const heapArray = wasmModule.HEAPF64.subarray(elemOffset, elemOffset + numElements);
123
+ return new WasmBuffer(wasmModule, byteOffset, heapArray);
124
+ }
59
125
 
60
126
  // src/wasm-model/wasm-model.ts
127
+ var indicesPerOutput = 4;
61
128
  var WasmModel = class {
129
+ /**
130
+ * @param wasmModule The `WasmModule` that provides access to the native functions.
131
+ */
62
132
  constructor(wasmModule) {
63
133
  function getNumberValue(funcName) {
64
134
  const wasmGetValue = wasmModule.cwrap(funcName, "number", []);
@@ -67,24 +137,59 @@ var WasmModel = class {
67
137
  this.startTime = getNumberValue("getInitialTime");
68
138
  this.endTime = getNumberValue("getFinalTime");
69
139
  this.saveFreq = getNumberValue("getSaveper");
140
+ try {
141
+ this.maxOutputIndices = getNumberValue("getMaxOutputIndices");
142
+ } catch (e) {
143
+ this.maxOutputIndices = 0;
144
+ }
70
145
  this.numSavePoints = Math.round((this.endTime - this.startTime) / this.saveFreq) + 1;
71
- this.wasmRunModel = wasmModule.cwrap("runModelWithBuffers", null, ["number", "number"]);
146
+ this.wasmRunModel = wasmModule.cwrap("runModelWithBuffers", null, ["number", "number", "number"]);
72
147
  }
73
- runModel(inputs, outputs) {
74
- this.wasmRunModel(inputs.getAddress(), outputs.getAddress());
148
+ /**
149
+ * Run the model, using inputs from the `inputs` buffer, and writing outputs into
150
+ * the `outputs` buffer.
151
+ *
152
+ * @param inputs The buffer containing inputs in the order expected by the model.
153
+ * @param outputs The buffer into which the model will store output values.
154
+ * @param outputIndices The buffer used to control which variables are written to `outputs`.
155
+ */
156
+ runModel(inputs, outputs, outputIndices) {
157
+ this.wasmRunModel(inputs.getAddress(), outputs.getAddress(), (outputIndices == null ? void 0 : outputIndices.getAddress()) || 0);
75
158
  }
76
159
  };
77
160
  function initWasmModelAndBuffers(wasmModule, numInputs, outputVarIds) {
78
161
  const model = new WasmModel(wasmModule);
79
- const inputsBuffer = new WasmBuffer(wasmModule, numInputs);
80
- const outputsBuffer = new WasmBuffer(wasmModule, outputVarIds.length * model.numSavePoints);
162
+ const inputsBuffer = createFloat64WasmBuffer(wasmModule, numInputs);
163
+ const outputVarCount = Math.max(outputVarIds.length, model.maxOutputIndices);
164
+ const outputsBuffer = createFloat64WasmBuffer(wasmModule, outputVarCount * model.numSavePoints);
165
+ let outputIndicesBuffer;
166
+ if (model.maxOutputIndices > 0) {
167
+ outputIndicesBuffer = createInt32WasmBuffer(wasmModule, model.maxOutputIndices * indicesPerOutput);
168
+ }
81
169
  return {
82
170
  model,
83
171
  inputsBuffer,
84
172
  outputsBuffer,
173
+ outputIndicesBuffer,
85
174
  outputVarIds
86
175
  };
87
176
  }
177
+ function updateOutputIndices(indicesArray, outputVarSpecs) {
178
+ var _a;
179
+ if (indicesArray.length < outputVarSpecs.length * indicesPerOutput) {
180
+ throw new Error("Length of indicesArray must be large enough to accommodate the given outputVarSpecs");
181
+ }
182
+ let offset = 0;
183
+ for (const outputVarSpec of outputVarSpecs) {
184
+ const subCount = ((_a = outputVarSpec.subscriptIndices) == null ? void 0 : _a.length) || 0;
185
+ indicesArray[offset + 0] = outputVarSpec.varIndex;
186
+ indicesArray[offset + 1] = subCount > 0 ? outputVarSpec.subscriptIndices[0] : 0;
187
+ indicesArray[offset + 2] = subCount > 1 ? outputVarSpec.subscriptIndices[1] : 0;
188
+ indicesArray[offset + 3] = subCount > 2 ? outputVarSpec.subscriptIndices[2] : 0;
189
+ offset += indicesPerOutput;
190
+ }
191
+ indicesArray.fill(0, offset);
192
+ }
88
193
 
89
194
  // src/model-runner/inputs.ts
90
195
  function createInputValue(varId, defaultValue, initialValue) {
@@ -108,21 +213,43 @@ function createInputValue(varId, defaultValue, initialValue) {
108
213
 
109
214
  // src/model-runner/outputs.ts
110
215
  var import_neverthrow = require("neverthrow");
111
- var Series = class {
216
+ var Series = class _Series {
217
+ /**
218
+ * @param varId The ID for the output variable (as used by SDEverywhere).
219
+ * @param points The data points for the variable, one point per time increment.
220
+ */
112
221
  constructor(varId, points) {
113
222
  this.varId = varId;
114
223
  this.points = points;
115
224
  }
225
+ /**
226
+ * Return the Y value at the given time. Note that this does not attempt to interpolate
227
+ * if there is no data point defined for the given time and will return undefined in
228
+ * that case.
229
+ *
230
+ * @param time The x (time) value.
231
+ * @return The y value for the given time, or undefined if there is no data point defined
232
+ * for the given time.
233
+ */
116
234
  getValueAtTime(time) {
117
235
  var _a;
118
236
  return (_a = this.points.find((p) => p.x === time)) == null ? void 0 : _a.y;
119
237
  }
238
+ /**
239
+ * Create a new `Series` instance that is a copy of this one.
240
+ */
120
241
  copy() {
121
- const pointsCopy = this.points.map((p) => ({ ...p }));
122
- return new Series(this.varId, pointsCopy);
242
+ const pointsCopy = this.points.map((p) => __spreadValues({}, p));
243
+ return new _Series(this.varId, pointsCopy);
123
244
  }
124
245
  };
125
246
  var Outputs = class {
247
+ /**
248
+ * @param varIds The output variable identifiers.
249
+ * @param startTime The start time for the model.
250
+ * @param endTime The end time for the model.
251
+ * @param saveFreq The frequency with which output values are saved (aka `SAVEPER`).
252
+ */
126
253
  constructor(varIds, startTime, endTime, saveFreq = 1) {
127
254
  this.varIds = varIds;
128
255
  this.startTime = startTime;
@@ -139,6 +266,32 @@ var Outputs = class {
139
266
  this.varSeries[i] = new Series(varId, points);
140
267
  }
141
268
  }
269
+ /**
270
+ * The optional set of specs that dictate which variables from the model will be
271
+ * stored in this `Outputs` instance. If undefined, the default set of outputs
272
+ * will be stored (as configured in `varIds`).
273
+ * @hidden This is not yet part of the public API; it is exposed here for use
274
+ * in experimental testing tools.
275
+ */
276
+ setVarSpecs(varSpecs) {
277
+ if (varSpecs.length !== this.varIds.length) {
278
+ throw new Error("Length of output varSpecs must match that of varIds");
279
+ }
280
+ this.varSpecs = varSpecs;
281
+ }
282
+ /**
283
+ * Parse the given raw float buffer (produced by the model) and store the values
284
+ * into this `Outputs` instance.
285
+ *
286
+ * Note that the length of `outputsBuffer` must be greater than or equal to
287
+ * the capacity of this `Outputs` instance. The `Outputs` instance is allowed
288
+ * to be smaller to support the case where you want to extract a subset of
289
+ * the time range in the buffer produced by the model.
290
+ *
291
+ * @param outputsBuffer The raw outputs buffer produced by the model.
292
+ * @param rowLength The number of elements per row (one element per save point).
293
+ * @return An `ok` result if the buffer is valid, otherwise an `err` result.
294
+ */
142
295
  updateFromBuffer(outputsBuffer, rowLength) {
143
296
  const result = parseOutputsBuffer(outputsBuffer, rowLength, this);
144
297
  if (result.isOk()) {
@@ -147,6 +300,11 @@ var Outputs = class {
147
300
  return (0, import_neverthrow.err)(result.error);
148
301
  }
149
302
  }
303
+ /**
304
+ * Return the series for the given output variable.
305
+ *
306
+ * @param varId The ID of the output variable (as used by SDEverywhere).
307
+ */
150
308
  getSeriesForVar(varId) {
151
309
  const seriesIndex = this.varIds.indexOf(varId);
152
310
  if (seriesIndex >= 0) {
@@ -209,6 +367,8 @@ function createWasmModelRunner(wasmResult) {
209
367
  const inputsArray = inputsBuffer.getArrayView();
210
368
  const outputsBuffer = wasmResult.outputsBuffer;
211
369
  const outputsArray = outputsBuffer.getArrayView();
370
+ const outputIndicesBuffer = wasmResult.outputIndicesBuffer;
371
+ const outputIndicesArray = outputIndicesBuffer == null ? void 0 : outputIndicesBuffer.getArrayView();
212
372
  const rowLength = wasmModel.numSavePoints;
213
373
  let terminated = false;
214
374
  const runModelSync = (inputs, outputs) => {
@@ -216,8 +376,16 @@ function createWasmModelRunner(wasmResult) {
216
376
  for (const input of inputs) {
217
377
  inputsArray[i++] = input.get();
218
378
  }
379
+ const outputSpecs = outputs.varSpecs;
380
+ let useIndices;
381
+ if (outputIndicesArray && outputSpecs !== void 0 && outputSpecs.length > 0) {
382
+ updateOutputIndices(outputIndicesArray, outputSpecs);
383
+ useIndices = true;
384
+ } else {
385
+ useIndices = false;
386
+ }
219
387
  const t0 = perfNow();
220
- wasmModel.runModel(inputsBuffer, outputsBuffer);
388
+ wasmModel.runModel(inputsBuffer, outputsBuffer, useIndices ? outputIndicesBuffer : void 0);
221
389
  outputs.runTimeInMillis = perfElapsed(t0);
222
390
  outputs.updateFromBuffer(outputsArray, rowLength);
223
391
  return outputs;
@@ -247,13 +415,121 @@ function createWasmModelRunner(wasmResult) {
247
415
  };
248
416
  }
249
417
 
418
+ // src/model-runner/model-listing.ts
419
+ var ModelListing = class {
420
+ constructor(modelJsonString) {
421
+ this.varSpecs = /* @__PURE__ */ new Map();
422
+ const modelJson = JSON.parse(modelJsonString);
423
+ const dimensions = /* @__PURE__ */ new Map();
424
+ for (const dimInfo of modelJson.dimensions) {
425
+ const dimId = dimInfo.name;
426
+ const subscripts = [];
427
+ for (let i = 0; i < dimInfo.value.length; i++) {
428
+ subscripts.push({
429
+ id: dimInfo.value[i],
430
+ // name: dimInfo.modelValue[i]
431
+ index: i
432
+ });
433
+ }
434
+ dimensions.set(dimId, {
435
+ id: dimId,
436
+ // name: dimInfo.modelName,
437
+ subscripts
438
+ });
439
+ }
440
+ function dimensionForId(dimId) {
441
+ const dim = dimensions.get(dimId);
442
+ if (dim === void 0) {
443
+ throw new Error(`No dimension info found for id=${dimId}`);
444
+ }
445
+ return dim;
446
+ }
447
+ const baseVarIds = /* @__PURE__ */ new Set();
448
+ for (const v of modelJson.variables) {
449
+ const baseVarId = varIdWithoutSubscripts(v.varName);
450
+ if (!baseVarIds.has(baseVarId)) {
451
+ const dimIds = v.families || [];
452
+ const dimensions2 = dimIds.map(dimensionForId);
453
+ if (dimensions2.length > 0) {
454
+ if (dimensions2.length > 3) {
455
+ throw new Error("Variables with more than 3 dimensions not currently supported");
456
+ }
457
+ const dimSubs = [];
458
+ for (const dim of dimensions2) {
459
+ dimSubs.push(dim.subscripts);
460
+ }
461
+ const combos = cartesianProductOf(dimSubs);
462
+ for (const combo of combos) {
463
+ const subs = combo.map((sub) => sub.id).join(",");
464
+ const subIndices = combo.map((sub) => sub.index);
465
+ const fullVarId = `${baseVarId}[${subs}]`;
466
+ this.varSpecs.set(fullVarId, {
467
+ varIndex: v.varIndex,
468
+ subscriptIndices: subIndices
469
+ });
470
+ }
471
+ } else {
472
+ this.varSpecs.set(baseVarId, {
473
+ varIndex: v.varIndex
474
+ });
475
+ }
476
+ baseVarIds.add(baseVarId);
477
+ }
478
+ }
479
+ }
480
+ /**
481
+ * Create a new `Outputs` instance that uses the same start/end years as the given "normal"
482
+ * `Outputs` instance but is prepared for reading the specified internal variables from the model.
483
+ *
484
+ * @param normalOutputs The `Outputs` that is used to access normal output variables from the model.
485
+ * @param varIds The variable IDs to include with the new `Outputs` instance.
486
+ */
487
+ deriveOutputs(normalOutputs, varIds) {
488
+ const varSpecs = [];
489
+ for (const varId of varIds) {
490
+ const varSpec = this.varSpecs.get(varId);
491
+ if (varSpec !== void 0) {
492
+ varSpecs.push(varSpec);
493
+ } else {
494
+ console.warn(`WARNING: No output var spec found for id=${varId}`);
495
+ }
496
+ }
497
+ const newOutputs = new Outputs(varIds, normalOutputs.startTime, normalOutputs.endTime, normalOutputs.saveFreq);
498
+ newOutputs.varSpecs = varSpecs;
499
+ return newOutputs;
500
+ }
501
+ };
502
+ function varIdWithoutSubscripts(fullVarId) {
503
+ const bracketIndex = fullVarId.indexOf("[");
504
+ if (bracketIndex >= 0) {
505
+ return fullVarId.substring(0, bracketIndex);
506
+ } else {
507
+ return fullVarId;
508
+ }
509
+ }
510
+ function cartesianProductOf(arr) {
511
+ return arr.reduce(
512
+ (a, b) => {
513
+ return a.map((x) => b.map((y) => x.concat([y]))).reduce((v, w) => v.concat(w), []);
514
+ },
515
+ [[]]
516
+ );
517
+ }
518
+
250
519
  // src/model-scheduler/model-scheduler.ts
251
520
  var ModelScheduler = class {
521
+ /**
522
+ * @param runner The model runner.
523
+ * @param userInputs The input values, in the same order as in the spec file passed to `sde`.
524
+ * @param outputs The structure into which the model outputs will be stored.
525
+ */
252
526
  constructor(runner, userInputs, outputs) {
253
527
  this.runner = runner;
254
528
  this.userInputs = userInputs;
255
529
  this.outputs = outputs;
530
+ /** Whether a model run has been scheduled. */
256
531
  this.runNeeded = false;
532
+ /** Whether a model run is in progress. */
257
533
  this.runInProgress = false;
258
534
  const afterSet = () => {
259
535
  this.runWasmModelIfNeeded();
@@ -266,6 +542,10 @@ var ModelScheduler = class {
266
542
  this.currentInputs.push(createSimpleInputValue(userInput.varId));
267
543
  }
268
544
  }
545
+ /**
546
+ * Schedule a wasm model run (if not already pending). When the run is
547
+ * complete, save the outputs and call the `onOutputsChanged` callback.
548
+ */
269
549
  runWasmModelIfNeeded() {
270
550
  this.runNeeded = true;
271
551
  if (this.runInProgress) {
@@ -277,26 +557,31 @@ var ModelScheduler = class {
277
557
  }, 0);
278
558
  }
279
559
  }
280
- async runWasmModelNow() {
281
- var _a;
282
- for (let i = 0; i < this.userInputs.length; i++) {
283
- this.currentInputs[i].set(this.userInputs[i].get());
284
- }
285
- try {
286
- this.outputs = await this.runner.runModel(this.currentInputs, this.outputs);
287
- (_a = this.onOutputsChanged) == null ? void 0 : _a.call(this, this.outputs);
288
- } catch (e) {
289
- console.error(`ERROR: Failed to run model: ${e.message}`);
290
- }
291
- if (this.runNeeded) {
292
- this.runNeeded = false;
293
- setTimeout(() => {
294
- this.runWasmModelNow();
295
- }, 0);
296
- } else {
297
- this.runNeeded = false;
298
- this.runInProgress = false;
299
- }
560
+ /**
561
+ * Run the wasm model asynchronously using the current set of input values.
562
+ */
563
+ runWasmModelNow() {
564
+ return __async(this, null, function* () {
565
+ var _a;
566
+ for (let i = 0; i < this.userInputs.length; i++) {
567
+ this.currentInputs[i].set(this.userInputs[i].get());
568
+ }
569
+ try {
570
+ this.outputs = yield this.runner.runModel(this.currentInputs, this.outputs);
571
+ (_a = this.onOutputsChanged) == null ? void 0 : _a.call(this, this.outputs);
572
+ } catch (e) {
573
+ console.error(`ERROR: Failed to run model: ${e.message}`);
574
+ }
575
+ if (this.runNeeded) {
576
+ this.runNeeded = false;
577
+ setTimeout(() => {
578
+ this.runWasmModelNow();
579
+ }, 0);
580
+ } else {
581
+ this.runNeeded = false;
582
+ this.runInProgress = false;
583
+ }
584
+ });
300
585
  }
301
586
  };
302
587
  function createSimpleInputValue(varId) {
@@ -314,15 +599,19 @@ function createSimpleInputValue(varId) {
314
599
  }
315
600
  // Annotate the CommonJS export names for ESM import in node:
316
601
  0 && (module.exports = {
602
+ ModelListing,
317
603
  ModelScheduler,
318
604
  Outputs,
319
605
  Series,
320
606
  WasmBuffer,
321
607
  WasmModel,
608
+ createFloat64WasmBuffer,
322
609
  createInputValue,
610
+ createInt32WasmBuffer,
323
611
  createWasmModelRunner,
324
612
  initWasmModelAndBuffers,
325
613
  perfElapsed,
326
- perfNow
614
+ perfNow,
615
+ updateOutputIndices
327
616
  });
328
617
  //# sourceMappingURL=index.cjs.map