@sdeverywhere/plugin-worker 0.1.4 → 0.2.1

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,12 +1,32 @@
1
1
  # @sdeverywhere/plugin-worker
2
2
 
3
- This package provides a plugin that generates a `worker.js` file that can run
4
- an SDEverywhere-generated system dynamics model asynchronously in a Web Worker
5
- or Node.js worker thread.
3
+ This package provides a plugin that generates a `worker.js` file that can run a System Dynamics model (as generated by [SDEverywhere](https://github.com/climateinteractive/SDEverywhere)) asynchronously in a Web Worker or Node.js worker thread.
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/plugin-worker` 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 --save-dev @sdeverywhere/plugin-worker
15
+
16
+ # pnpm
17
+ pnpm add -D @sdeverywhere/plugin-worker
18
+
19
+ # yarn
20
+ yarn add -D @sdeverywhere/plugin-worker
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ _TODO: This section needs to be fleshed out. In the meantime, you can refer to the API documentation below for the options used to configure this plugin._
6
26
 
7
27
  ## Documentation
8
28
 
9
- TODO
29
+ API documentation (for plugin configuration options) is available in the [`docs`](./docs/index.md) directory.
10
30
 
11
31
  ## License
12
32
 
package/dist/index.cjs CHANGED
@@ -23,6 +23,10 @@ __export(src_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(src_exports);
25
25
 
26
+ // ../../node_modules/.pnpm/tsup@7.2.0_typescript@5.2.2/node_modules/tsup/assets/cjs_shims.js
27
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL("file:" + __filename).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
28
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
29
+
26
30
  // src/plugin.ts
27
31
  var import_path2 = require("path");
28
32
  var import_vite = require("vite");
@@ -30,7 +34,6 @@ var import_vite = require("vite");
30
34
  // src/vite-config.ts
31
35
  var import_path = require("path");
32
36
  var import_url = require("url");
33
- var import_plugin_node_resolve = require("@rollup/plugin-node-resolve");
34
37
 
35
38
  // src/var-names.ts
36
39
  function sdeNameForVensimName(name) {
@@ -50,14 +53,11 @@ function sdeNameForVensimVarName(varName) {
50
53
  }
51
54
 
52
55
  // src/vite-config.ts
53
- var import_meta = {};
54
- var __filename = (0, import_url.fileURLToPath)(import_meta.url);
55
- var __dirname = (0, import_path.dirname)(__filename);
56
+ var __filename2 = (0, import_url.fileURLToPath)(importMetaUrl);
57
+ var __dirname = (0, import_path.dirname)(__filename2);
56
58
  function injectModelSpec(modelSpec) {
57
59
  const outputVarIds = modelSpec.outputs.map((o) => sdeNameForVensimVarName(o.varName));
58
60
  const moduleSrc = `
59
- export const startTime = ${modelSpec.startTime};
60
- export const endTime = ${modelSpec.endTime};
61
61
  export const numInputs = ${modelSpec.inputs.length};
62
62
  export const outputVarIds = ${JSON.stringify(outputVarIds)};
63
63
  `;
@@ -81,27 +81,42 @@ function createViteConfig(stagedModelDir, modelJsFile, modelSpec, outputFile) {
81
81
  const root = stagedModelDir;
82
82
  const entry = (0, import_path.resolve)(__dirname, "..", "template-worker", "worker.js");
83
83
  return {
84
+ // Don't use an external config file
84
85
  configFile: false,
86
+ // Use the root directory configured above
85
87
  root,
88
+ // Don't clear the screen in dev mode so that we can see builder output
86
89
  clearScreen: false,
90
+ // Disable vite output by default
91
+ // TODO: Re-enable logging if `--verbose` option is used?
87
92
  logLevel: "silent",
93
+ // Configure path aliases
88
94
  resolve: {
89
95
  alias: [
96
+ // In the template, we use `@_wasm_` as an alias for the JS-wrapped Wasm
97
+ // file generated by Emscripten
90
98
  {
91
99
  find: "@_wasm_",
92
100
  replacement: (0, import_path.resolve)(stagedModelDir, modelJsFile)
93
- },
94
- {
95
- find: "threads",
96
- replacement: "threads",
97
- customResolver: (0, import_plugin_node_resolve.nodeResolve)({ browser: false })
98
101
  }
99
- ]
102
+ ],
103
+ // XXX: Prevent Vite from using the `browser` section of `threads/package.json`
104
+ // since we want to force the use of the general module (under dist) that chooses
105
+ // the correct implementation (Web Worker vs worker_threads) at runtime. This
106
+ // gets the job done, but is fragile because it applies to all dependencies even
107
+ // though we really only need this workaround for the threads package. Fortunately
108
+ // the worker template is very simple (only depends on `@sdeverywhere/runtime-async`,
109
+ // which in turn only depends on `@sdeverywhere/runtime` and `threads`, so we should
110
+ // be safe to use this workaround for a while.
111
+ browserField: false
100
112
  },
101
113
  plugins: [
114
+ // Use a virtual module plugin to inject the model spec values
102
115
  injectModelSpec(modelSpec)
103
116
  ],
104
117
  build: {
118
+ // Write output file to the `staged/model` directory; note that this path is
119
+ // relative to the bundle `root` directory
105
120
  outDir: ".",
106
121
  emptyOutDir: false,
107
122
  lib: {
@@ -130,7 +145,6 @@ var WorkerPlugin = class {
130
145
  this.options = options;
131
146
  }
132
147
  async postGenerate(context, modelSpec) {
133
- var _a;
134
148
  const log = context.log;
135
149
  log("info", "Building worker");
136
150
  const prepDir = context.config.prepDir;
@@ -138,7 +152,7 @@ var WorkerPlugin = class {
138
152
  const stagedModelDir = (0, import_path2.join)(prepDir, "staged", srcDir);
139
153
  const inModelJsFile = "wasm-model.js";
140
154
  const outWorkerJsFile = "worker.js";
141
- const outputPaths = ((_a = this.options) == null ? void 0 : _a.outputPaths) || [(0, import_path2.join)(prepDir, outWorkerJsFile)];
155
+ const outputPaths = this.options?.outputPaths || [(0, import_path2.join)(prepDir, outWorkerJsFile)];
142
156
  for (const outputPath of outputPaths) {
143
157
  const dstDir = (0, import_path2.dirname)(outputPath);
144
158
  const dstFile = (0, import_path2.basename)(outputPath);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/vite-config.ts","../src/var-names.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nexport type { WorkerPluginOptions } from './options'\nexport { workerPlugin } from './plugin'\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { basename, dirname, join as joinPath } from 'path'\n\nimport { build } from 'vite'\n\nimport type { BuildContext, ModelSpec, Plugin } from '@sdeverywhere/build'\n\nimport type { WorkerPluginOptions } from './options'\nimport { createViteConfig } from './vite-config'\n\nexport function workerPlugin(options?: WorkerPluginOptions): Plugin {\n return new WorkerPlugin(options)\n}\n\nclass WorkerPlugin implements Plugin {\n constructor(private readonly options?: WorkerPluginOptions) {}\n\n async postGenerate(context: BuildContext, modelSpec: ModelSpec): Promise<boolean> {\n const log = context.log\n log('info', 'Building worker')\n\n // Locate the input (model JS/Wasm) file in the staged directory. Note\n // that this relies on the `plugin-wasm` package writing a file called\n // `wasm-model.js` to the `staged/model` directory.\n const prepDir = context.config.prepDir\n const srcDir = 'model'\n const stagedModelDir = joinPath(prepDir, 'staged', srcDir)\n const inModelJsFile = 'wasm-model.js'\n const outWorkerJsFile = 'worker.js'\n\n // If `outputPaths` is undefined, write the `worker.js` to the prep dir\n const outputPaths = this.options?.outputPaths || [joinPath(prepDir, outWorkerJsFile)]\n\n // Add staged file entries; this will cause the generated worker to be copied\n // to the configured output paths during the \"copy staged files\" step\n // TODO: This assumes that other plugins that use the generated worker files\n // will run after the \"copy staged files\" step. There might be use cases\n // where a plugin needs access to these in `postGenerate`, in which case the\n // files will not have been copied already. Need to reconsider the ordering\n // of plugins and the \"copy staged files\" step(s).\n for (const outputPath of outputPaths) {\n const dstDir = dirname(outputPath)\n const dstFile = basename(outputPath)\n context.prepareStagedFile(srcDir, outWorkerJsFile, dstDir, dstFile)\n }\n\n // Build the worker and write generated file to the `staged/model` directory\n const viteConfig = createViteConfig(stagedModelDir, inModelJsFile, modelSpec, outWorkerJsFile)\n await build(viteConfig)\n\n // log('info', 'Done!')\n\n return true\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { dirname, resolve as resolvePath } from 'path'\nimport { fileURLToPath } from 'url'\n\nimport type { InlineConfig, Plugin as VitePlugin, ResolverObject } from 'vite'\nimport { nodeResolve } from '@rollup/plugin-node-resolve'\n\nimport type { ModelSpec } from '@sdeverywhere/build'\n\nimport { sdeNameForVensimVarName } from './var-names'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\n/**\n * This is a virtual module plugin used to inject model-specific configuration\n * values into the generated worker bundle.\n *\n * This follows the \"Virtual Modules Convention\" described here:\n * https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention\n *\n * TODO: This could be simplified by using `vite-plugin-virtual` but that\n * doesn't seem to be working correctly in an ESM setting\n */\nfunction injectModelSpec(modelSpec: ModelSpec): VitePlugin {\n const outputVarIds = modelSpec.outputs.map(o => sdeNameForVensimVarName(o.varName))\n\n const moduleSrc = `\nexport const startTime = ${modelSpec.startTime};\nexport const endTime = ${modelSpec.endTime};\nexport const numInputs = ${modelSpec.inputs.length};\nexport const outputVarIds = ${JSON.stringify(outputVarIds)};\n`\n\n const virtualModuleId = 'virtual:model-spec'\n const resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n return {\n name: 'vite-plugin-virtual-custom',\n resolveId(id: string) {\n if (id === virtualModuleId) {\n return resolvedVirtualModuleId\n }\n },\n load(id: string) {\n if (id === resolvedVirtualModuleId) {\n return moduleSrc\n }\n }\n }\n}\n\n/**\n * Create a Vite `InlineConfig` that can be used to build a complete\n * worker bundle that can run the generated Wasm model in a separate\n * Web Worker or Node worker thread.\n *\n * @param stagedModelDir The `staged` directory under the `sde-prep` directory.\n * @param modelJsFile The name of the JS file containing the embedded Wasm.\n * @param modelSpec The model spec generated earlier in the build process.\n * @param outputFile The name of the generated worker JS file.\n * @return An `InlineConfig` instance that can be passed to Vite's `build` function.\n */\nexport function createViteConfig(\n stagedModelDir: string,\n modelJsFile: string,\n modelSpec: ModelSpec,\n outputFile: string\n): InlineConfig {\n // Use `staged/model` as the root directory for the worker build\n const root = stagedModelDir\n\n // Use `template-worker/worker.js` from this package as the entry file\n const entry = resolvePath(__dirname, '..', 'template-worker', 'worker.js')\n\n return {\n // Don't use an external config file\n configFile: false,\n\n // Use the root directory configured above\n root,\n\n // Don't clear the screen in dev mode so that we can see builder output\n clearScreen: false,\n\n // Disable vite output by default\n // TODO: Re-enable logging if `--verbose` option is used?\n logLevel: 'silent',\n\n // Configure path aliases\n resolve: {\n alias: [\n // In the template, we use `@_wasm_` as an alias for the JS-wrapped Wasm\n // file generated by Emscripten\n {\n find: '@_wasm_',\n replacement: resolvePath(stagedModelDir, modelJsFile)\n },\n\n // XXX: Prevent Vite from using the `browser` section of `threads/package.json`\n // since we want to force the use of the general module (under dist) that chooses\n // the correct implementation (Web Worker vs worker_threads) at runtime. Currently\n // Vite's library mode is browser focused, so using a `customResolver` seems to be\n // the easiest way to prevent Vite from picking up the `browser` exports.\n {\n find: 'threads',\n replacement: 'threads',\n customResolver: nodeResolve({ browser: false }) as ResolverObject\n }\n ]\n },\n\n plugins: [\n // Use a virtual module plugin to inject the model spec values\n injectModelSpec(modelSpec)\n ],\n\n build: {\n // Write output file to the `staged/model` directory; note that this path is\n // relative to the bundle `root` directory\n outDir: '.',\n emptyOutDir: false,\n\n lib: {\n entry,\n name: 'worker',\n formats: ['iife'],\n fileName: () => outputFile\n },\n\n rollupOptions: {\n onwarn: (warning, warn) => {\n // XXX: Suppress \"Use of eval is strongly discouraged\" warnings that are\n // triggered by use of the following pattern in threads.js:\n // eval(\"require\")(\"worker_threads\")\n // It would be nice to avoid use of `eval` there, but it's not critical for\n // our use case so we will suppress the warnings for now\n if (warning.code !== 'EVAL') {\n warn(warning)\n }\n }\n }\n }\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\n/**\n * Helper function that converts a Vensim variable or subscript name\n * into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeNameForVensimName(name: string): string {\n return (\n '_' +\n name\n .trim()\n .replace(/\"/g, '_')\n .replace(/\\s+!$/g, '!')\n .replace(/\\s/g, '_')\n .replace(/,/g, '_')\n .replace(/-/g, '_')\n .replace(/\\./g, '_')\n .replace(/\\$/g, '_')\n .replace(/'/g, '_')\n .replace(/&/g, '_')\n .replace(/%/g, '_')\n .replace(/\\//g, '_')\n .replace(/\\|/g, '_')\n .toLowerCase()\n )\n}\n\n/**\n * Helper function that converts a Vensim variable name (possibly containing\n * subscripts) into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nexport function sdeNameForVensimVarName(varName: string): string {\n const m = varName.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid Vensim name: ${varName}`)\n }\n let id = sdeNameForVensimName(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => sdeNameForVensimName(x))\n id += `[${subscripts.join('][')}]`\n }\n\n return id\n}\n"],"mappings":"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","names":["import_path","resolvePath","joinPath"]}
1
+ {"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/tsup@7.2.0_typescript@5.2.2/node_modules/tsup/assets/cjs_shims.js","../src/plugin.ts","../src/vite-config.ts","../src/var-names.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nexport type { WorkerPluginOptions } from './options'\nexport { workerPlugin } from './plugin'\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL('file:' + __filename).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { basename, dirname, join as joinPath } from 'path'\n\nimport { build } from 'vite'\n\nimport type { BuildContext, ModelSpec, Plugin } from '@sdeverywhere/build'\n\nimport type { WorkerPluginOptions } from './options'\nimport { createViteConfig } from './vite-config'\n\nexport function workerPlugin(options?: WorkerPluginOptions): Plugin {\n return new WorkerPlugin(options)\n}\n\nclass WorkerPlugin implements Plugin {\n constructor(private readonly options?: WorkerPluginOptions) {}\n\n async postGenerate(context: BuildContext, modelSpec: ModelSpec): Promise<boolean> {\n const log = context.log\n log('info', 'Building worker')\n\n // Locate the input (model JS/Wasm) file in the staged directory. Note\n // that this relies on the `plugin-wasm` package writing a file called\n // `wasm-model.js` to the `staged/model` directory.\n const prepDir = context.config.prepDir\n const srcDir = 'model'\n const stagedModelDir = joinPath(prepDir, 'staged', srcDir)\n const inModelJsFile = 'wasm-model.js'\n const outWorkerJsFile = 'worker.js'\n\n // If `outputPaths` is undefined, write the `worker.js` to the prep dir\n const outputPaths = this.options?.outputPaths || [joinPath(prepDir, outWorkerJsFile)]\n\n // Add staged file entries; this will cause the generated worker to be copied\n // to the configured output paths during the \"copy staged files\" step\n // TODO: This assumes that other plugins that use the generated worker files\n // will run after the \"copy staged files\" step. There might be use cases\n // where a plugin needs access to these in `postGenerate`, in which case the\n // files will not have been copied already. Need to reconsider the ordering\n // of plugins and the \"copy staged files\" step(s).\n for (const outputPath of outputPaths) {\n const dstDir = dirname(outputPath)\n const dstFile = basename(outputPath)\n context.prepareStagedFile(srcDir, outWorkerJsFile, dstDir, dstFile)\n }\n\n // Build the worker and write generated file to the `staged/model` directory\n const viteConfig = createViteConfig(stagedModelDir, inModelJsFile, modelSpec, outWorkerJsFile)\n await build(viteConfig)\n\n // log('info', 'Done!')\n\n return true\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { dirname, resolve as resolvePath } from 'path'\nimport { fileURLToPath } from 'url'\n\nimport type { InlineConfig, Plugin as VitePlugin } from 'vite'\n\nimport type { ModelSpec } from '@sdeverywhere/build'\n\nimport { sdeNameForVensimVarName } from './var-names'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\n/**\n * This is a virtual module plugin used to inject model-specific configuration\n * values into the generated worker bundle.\n *\n * This follows the \"Virtual Modules Convention\" described here:\n * https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention\n *\n * TODO: This could be simplified by using `vite-plugin-virtual` but that\n * doesn't seem to be working correctly in an ESM setting\n */\nfunction injectModelSpec(modelSpec: ModelSpec): VitePlugin {\n const outputVarIds = modelSpec.outputs.map(o => sdeNameForVensimVarName(o.varName))\n\n const moduleSrc = `\nexport const numInputs = ${modelSpec.inputs.length};\nexport const outputVarIds = ${JSON.stringify(outputVarIds)};\n`\n\n const virtualModuleId = 'virtual:model-spec'\n const resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n return {\n name: 'vite-plugin-virtual-custom',\n resolveId(id: string) {\n if (id === virtualModuleId) {\n return resolvedVirtualModuleId\n }\n },\n load(id: string) {\n if (id === resolvedVirtualModuleId) {\n return moduleSrc\n }\n }\n }\n}\n\n/**\n * Create a Vite `InlineConfig` that can be used to build a complete\n * worker bundle that can run the generated Wasm model in a separate\n * Web Worker or Node worker thread.\n *\n * @param stagedModelDir The `staged` directory under the `sde-prep` directory.\n * @param modelJsFile The name of the JS file containing the embedded Wasm.\n * @param modelSpec The model spec generated earlier in the build process.\n * @param outputFile The name of the generated worker JS file.\n * @return An `InlineConfig` instance that can be passed to Vite's `build` function.\n */\nexport function createViteConfig(\n stagedModelDir: string,\n modelJsFile: string,\n modelSpec: ModelSpec,\n outputFile: string\n): InlineConfig {\n // Use `staged/model` as the root directory for the worker build\n const root = stagedModelDir\n\n // Use `template-worker/worker.js` from this package as the entry file\n const entry = resolvePath(__dirname, '..', 'template-worker', 'worker.js')\n\n return {\n // Don't use an external config file\n configFile: false,\n\n // Use the root directory configured above\n root,\n\n // Don't clear the screen in dev mode so that we can see builder output\n clearScreen: false,\n\n // Disable vite output by default\n // TODO: Re-enable logging if `--verbose` option is used?\n logLevel: 'silent',\n\n // Configure path aliases\n resolve: {\n alias: [\n // In the template, we use `@_wasm_` as an alias for the JS-wrapped Wasm\n // file generated by Emscripten\n {\n find: '@_wasm_',\n replacement: resolvePath(stagedModelDir, modelJsFile)\n }\n ],\n\n // XXX: Prevent Vite from using the `browser` section of `threads/package.json`\n // since we want to force the use of the general module (under dist) that chooses\n // the correct implementation (Web Worker vs worker_threads) at runtime. This\n // gets the job done, but is fragile because it applies to all dependencies even\n // though we really only need this workaround for the threads package. Fortunately\n // the worker template is very simple (only depends on `@sdeverywhere/runtime-async`,\n // which in turn only depends on `@sdeverywhere/runtime` and `threads`, so we should\n // be safe to use this workaround for a while.\n browserField: false\n },\n\n plugins: [\n // Use a virtual module plugin to inject the model spec values\n injectModelSpec(modelSpec)\n ],\n\n build: {\n // Write output file to the `staged/model` directory; note that this path is\n // relative to the bundle `root` directory\n outDir: '.',\n emptyOutDir: false,\n\n lib: {\n entry,\n name: 'worker',\n formats: ['iife'],\n fileName: () => outputFile\n },\n\n rollupOptions: {\n onwarn: (warning, warn) => {\n // XXX: Suppress \"Use of eval is strongly discouraged\" warnings that are\n // triggered by use of the following pattern in threads.js:\n // eval(\"require\")(\"worker_threads\")\n // It would be nice to avoid use of `eval` there, but it's not critical for\n // our use case so we will suppress the warnings for now\n if (warning.code !== 'EVAL') {\n warn(warning)\n }\n }\n }\n }\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\n/**\n * Helper function that converts a Vensim variable or subscript name\n * into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeNameForVensimName(name: string): string {\n return (\n '_' +\n name\n .trim()\n .replace(/\"/g, '_')\n .replace(/\\s+!$/g, '!')\n .replace(/\\s/g, '_')\n .replace(/,/g, '_')\n .replace(/-/g, '_')\n .replace(/\\./g, '_')\n .replace(/\\$/g, '_')\n .replace(/'/g, '_')\n .replace(/&/g, '_')\n .replace(/%/g, '_')\n .replace(/\\//g, '_')\n .replace(/\\|/g, '_')\n .toLowerCase()\n )\n}\n\n/**\n * Helper function that converts a Vensim variable name (possibly containing\n * subscripts) into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nexport function sdeNameForVensimVarName(varName: string): string {\n const m = varName.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid Vensim name: ${varName}`)\n }\n let id = sdeNameForVensimName(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => sdeNameForVensimName(x))\n id += `[${subscripts.join('][')}]`\n }\n\n return id\n}\n"],"mappings":"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","names":["import_path","__filename","resolvePath","joinPath"]}
@@ -0,0 +1,13 @@
1
+ import { Plugin } from '@sdeverywhere/build';
2
+
3
+ interface WorkerPluginOptions {
4
+ /**
5
+ * The destination paths for the generated worker JS files. If undefined,
6
+ * a `worker.js` file will be written to the configured `prepDir`.
7
+ */
8
+ outputPaths?: string[];
9
+ }
10
+
11
+ declare function workerPlugin(options?: WorkerPluginOptions): Plugin;
12
+
13
+ export { WorkerPluginOptions, workerPlugin };
package/dist/index.js CHANGED
@@ -5,7 +5,6 @@ import { build } from "vite";
5
5
  // src/vite-config.ts
6
6
  import { dirname, resolve as resolvePath } from "path";
7
7
  import { fileURLToPath } from "url";
8
- import { nodeResolve } from "@rollup/plugin-node-resolve";
9
8
 
10
9
  // src/var-names.ts
11
10
  function sdeNameForVensimName(name) {
@@ -25,13 +24,11 @@ function sdeNameForVensimVarName(varName) {
25
24
  }
26
25
 
27
26
  // src/vite-config.ts
28
- var __filename = fileURLToPath(import.meta.url);
29
- var __dirname = dirname(__filename);
27
+ var __filename2 = fileURLToPath(import.meta.url);
28
+ var __dirname2 = dirname(__filename2);
30
29
  function injectModelSpec(modelSpec) {
31
30
  const outputVarIds = modelSpec.outputs.map((o) => sdeNameForVensimVarName(o.varName));
32
31
  const moduleSrc = `
33
- export const startTime = ${modelSpec.startTime};
34
- export const endTime = ${modelSpec.endTime};
35
32
  export const numInputs = ${modelSpec.inputs.length};
36
33
  export const outputVarIds = ${JSON.stringify(outputVarIds)};
37
34
  `;
@@ -53,29 +50,44 @@ export const outputVarIds = ${JSON.stringify(outputVarIds)};
53
50
  }
54
51
  function createViteConfig(stagedModelDir, modelJsFile, modelSpec, outputFile) {
55
52
  const root = stagedModelDir;
56
- const entry = resolvePath(__dirname, "..", "template-worker", "worker.js");
53
+ const entry = resolvePath(__dirname2, "..", "template-worker", "worker.js");
57
54
  return {
55
+ // Don't use an external config file
58
56
  configFile: false,
57
+ // Use the root directory configured above
59
58
  root,
59
+ // Don't clear the screen in dev mode so that we can see builder output
60
60
  clearScreen: false,
61
+ // Disable vite output by default
62
+ // TODO: Re-enable logging if `--verbose` option is used?
61
63
  logLevel: "silent",
64
+ // Configure path aliases
62
65
  resolve: {
63
66
  alias: [
67
+ // In the template, we use `@_wasm_` as an alias for the JS-wrapped Wasm
68
+ // file generated by Emscripten
64
69
  {
65
70
  find: "@_wasm_",
66
71
  replacement: resolvePath(stagedModelDir, modelJsFile)
67
- },
68
- {
69
- find: "threads",
70
- replacement: "threads",
71
- customResolver: nodeResolve({ browser: false })
72
72
  }
73
- ]
73
+ ],
74
+ // XXX: Prevent Vite from using the `browser` section of `threads/package.json`
75
+ // since we want to force the use of the general module (under dist) that chooses
76
+ // the correct implementation (Web Worker vs worker_threads) at runtime. This
77
+ // gets the job done, but is fragile because it applies to all dependencies even
78
+ // though we really only need this workaround for the threads package. Fortunately
79
+ // the worker template is very simple (only depends on `@sdeverywhere/runtime-async`,
80
+ // which in turn only depends on `@sdeverywhere/runtime` and `threads`, so we should
81
+ // be safe to use this workaround for a while.
82
+ browserField: false
74
83
  },
75
84
  plugins: [
85
+ // Use a virtual module plugin to inject the model spec values
76
86
  injectModelSpec(modelSpec)
77
87
  ],
78
88
  build: {
89
+ // Write output file to the `staged/model` directory; note that this path is
90
+ // relative to the bundle `root` directory
79
91
  outDir: ".",
80
92
  emptyOutDir: false,
81
93
  lib: {
@@ -104,7 +116,6 @@ var WorkerPlugin = class {
104
116
  this.options = options;
105
117
  }
106
118
  async postGenerate(context, modelSpec) {
107
- var _a;
108
119
  const log = context.log;
109
120
  log("info", "Building worker");
110
121
  const prepDir = context.config.prepDir;
@@ -112,7 +123,7 @@ var WorkerPlugin = class {
112
123
  const stagedModelDir = joinPath(prepDir, "staged", srcDir);
113
124
  const inModelJsFile = "wasm-model.js";
114
125
  const outWorkerJsFile = "worker.js";
115
- const outputPaths = ((_a = this.options) == null ? void 0 : _a.outputPaths) || [joinPath(prepDir, outWorkerJsFile)];
126
+ const outputPaths = this.options?.outputPaths || [joinPath(prepDir, outWorkerJsFile)];
116
127
  for (const outputPath of outputPaths) {
117
128
  const dstDir = dirname2(outputPath);
118
129
  const dstFile = basename(outputPath);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts","../src/vite-config.ts","../src/var-names.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { basename, dirname, join as joinPath } from 'path'\n\nimport { build } from 'vite'\n\nimport type { BuildContext, ModelSpec, Plugin } from '@sdeverywhere/build'\n\nimport type { WorkerPluginOptions } from './options'\nimport { createViteConfig } from './vite-config'\n\nexport function workerPlugin(options?: WorkerPluginOptions): Plugin {\n return new WorkerPlugin(options)\n}\n\nclass WorkerPlugin implements Plugin {\n constructor(private readonly options?: WorkerPluginOptions) {}\n\n async postGenerate(context: BuildContext, modelSpec: ModelSpec): Promise<boolean> {\n const log = context.log\n log('info', 'Building worker')\n\n // Locate the input (model JS/Wasm) file in the staged directory. Note\n // that this relies on the `plugin-wasm` package writing a file called\n // `wasm-model.js` to the `staged/model` directory.\n const prepDir = context.config.prepDir\n const srcDir = 'model'\n const stagedModelDir = joinPath(prepDir, 'staged', srcDir)\n const inModelJsFile = 'wasm-model.js'\n const outWorkerJsFile = 'worker.js'\n\n // If `outputPaths` is undefined, write the `worker.js` to the prep dir\n const outputPaths = this.options?.outputPaths || [joinPath(prepDir, outWorkerJsFile)]\n\n // Add staged file entries; this will cause the generated worker to be copied\n // to the configured output paths during the \"copy staged files\" step\n // TODO: This assumes that other plugins that use the generated worker files\n // will run after the \"copy staged files\" step. There might be use cases\n // where a plugin needs access to these in `postGenerate`, in which case the\n // files will not have been copied already. Need to reconsider the ordering\n // of plugins and the \"copy staged files\" step(s).\n for (const outputPath of outputPaths) {\n const dstDir = dirname(outputPath)\n const dstFile = basename(outputPath)\n context.prepareStagedFile(srcDir, outWorkerJsFile, dstDir, dstFile)\n }\n\n // Build the worker and write generated file to the `staged/model` directory\n const viteConfig = createViteConfig(stagedModelDir, inModelJsFile, modelSpec, outWorkerJsFile)\n await build(viteConfig)\n\n // log('info', 'Done!')\n\n return true\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { dirname, resolve as resolvePath } from 'path'\nimport { fileURLToPath } from 'url'\n\nimport type { InlineConfig, Plugin as VitePlugin, ResolverObject } from 'vite'\nimport { nodeResolve } from '@rollup/plugin-node-resolve'\n\nimport type { ModelSpec } from '@sdeverywhere/build'\n\nimport { sdeNameForVensimVarName } from './var-names'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\n/**\n * This is a virtual module plugin used to inject model-specific configuration\n * values into the generated worker bundle.\n *\n * This follows the \"Virtual Modules Convention\" described here:\n * https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention\n *\n * TODO: This could be simplified by using `vite-plugin-virtual` but that\n * doesn't seem to be working correctly in an ESM setting\n */\nfunction injectModelSpec(modelSpec: ModelSpec): VitePlugin {\n const outputVarIds = modelSpec.outputs.map(o => sdeNameForVensimVarName(o.varName))\n\n const moduleSrc = `\nexport const startTime = ${modelSpec.startTime};\nexport const endTime = ${modelSpec.endTime};\nexport const numInputs = ${modelSpec.inputs.length};\nexport const outputVarIds = ${JSON.stringify(outputVarIds)};\n`\n\n const virtualModuleId = 'virtual:model-spec'\n const resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n return {\n name: 'vite-plugin-virtual-custom',\n resolveId(id: string) {\n if (id === virtualModuleId) {\n return resolvedVirtualModuleId\n }\n },\n load(id: string) {\n if (id === resolvedVirtualModuleId) {\n return moduleSrc\n }\n }\n }\n}\n\n/**\n * Create a Vite `InlineConfig` that can be used to build a complete\n * worker bundle that can run the generated Wasm model in a separate\n * Web Worker or Node worker thread.\n *\n * @param stagedModelDir The `staged` directory under the `sde-prep` directory.\n * @param modelJsFile The name of the JS file containing the embedded Wasm.\n * @param modelSpec The model spec generated earlier in the build process.\n * @param outputFile The name of the generated worker JS file.\n * @return An `InlineConfig` instance that can be passed to Vite's `build` function.\n */\nexport function createViteConfig(\n stagedModelDir: string,\n modelJsFile: string,\n modelSpec: ModelSpec,\n outputFile: string\n): InlineConfig {\n // Use `staged/model` as the root directory for the worker build\n const root = stagedModelDir\n\n // Use `template-worker/worker.js` from this package as the entry file\n const entry = resolvePath(__dirname, '..', 'template-worker', 'worker.js')\n\n return {\n // Don't use an external config file\n configFile: false,\n\n // Use the root directory configured above\n root,\n\n // Don't clear the screen in dev mode so that we can see builder output\n clearScreen: false,\n\n // Disable vite output by default\n // TODO: Re-enable logging if `--verbose` option is used?\n logLevel: 'silent',\n\n // Configure path aliases\n resolve: {\n alias: [\n // In the template, we use `@_wasm_` as an alias for the JS-wrapped Wasm\n // file generated by Emscripten\n {\n find: '@_wasm_',\n replacement: resolvePath(stagedModelDir, modelJsFile)\n },\n\n // XXX: Prevent Vite from using the `browser` section of `threads/package.json`\n // since we want to force the use of the general module (under dist) that chooses\n // the correct implementation (Web Worker vs worker_threads) at runtime. Currently\n // Vite's library mode is browser focused, so using a `customResolver` seems to be\n // the easiest way to prevent Vite from picking up the `browser` exports.\n {\n find: 'threads',\n replacement: 'threads',\n customResolver: nodeResolve({ browser: false }) as ResolverObject\n }\n ]\n },\n\n plugins: [\n // Use a virtual module plugin to inject the model spec values\n injectModelSpec(modelSpec)\n ],\n\n build: {\n // Write output file to the `staged/model` directory; note that this path is\n // relative to the bundle `root` directory\n outDir: '.',\n emptyOutDir: false,\n\n lib: {\n entry,\n name: 'worker',\n formats: ['iife'],\n fileName: () => outputFile\n },\n\n rollupOptions: {\n onwarn: (warning, warn) => {\n // XXX: Suppress \"Use of eval is strongly discouraged\" warnings that are\n // triggered by use of the following pattern in threads.js:\n // eval(\"require\")(\"worker_threads\")\n // It would be nice to avoid use of `eval` there, but it's not critical for\n // our use case so we will suppress the warnings for now\n if (warning.code !== 'EVAL') {\n warn(warning)\n }\n }\n }\n }\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\n/**\n * Helper function that converts a Vensim variable or subscript name\n * into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeNameForVensimName(name: string): string {\n return (\n '_' +\n name\n .trim()\n .replace(/\"/g, '_')\n .replace(/\\s+!$/g, '!')\n .replace(/\\s/g, '_')\n .replace(/,/g, '_')\n .replace(/-/g, '_')\n .replace(/\\./g, '_')\n .replace(/\\$/g, '_')\n .replace(/'/g, '_')\n .replace(/&/g, '_')\n .replace(/%/g, '_')\n .replace(/\\//g, '_')\n .replace(/\\|/g, '_')\n .toLowerCase()\n )\n}\n\n/**\n * Helper function that converts a Vensim variable name (possibly containing\n * subscripts) into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nexport function sdeNameForVensimVarName(varName: string): string {\n const m = varName.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid Vensim name: ${varName}`)\n }\n let id = sdeNameForVensimName(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => sdeNameForVensimName(x))\n id += `[${subscripts.join('][')}]`\n }\n\n return id\n}\n"],"mappings":"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","names":["dirname","dirname"]}
1
+ {"version":3,"sources":["../src/plugin.ts","../src/vite-config.ts","../src/var-names.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { basename, dirname, join as joinPath } from 'path'\n\nimport { build } from 'vite'\n\nimport type { BuildContext, ModelSpec, Plugin } from '@sdeverywhere/build'\n\nimport type { WorkerPluginOptions } from './options'\nimport { createViteConfig } from './vite-config'\n\nexport function workerPlugin(options?: WorkerPluginOptions): Plugin {\n return new WorkerPlugin(options)\n}\n\nclass WorkerPlugin implements Plugin {\n constructor(private readonly options?: WorkerPluginOptions) {}\n\n async postGenerate(context: BuildContext, modelSpec: ModelSpec): Promise<boolean> {\n const log = context.log\n log('info', 'Building worker')\n\n // Locate the input (model JS/Wasm) file in the staged directory. Note\n // that this relies on the `plugin-wasm` package writing a file called\n // `wasm-model.js` to the `staged/model` directory.\n const prepDir = context.config.prepDir\n const srcDir = 'model'\n const stagedModelDir = joinPath(prepDir, 'staged', srcDir)\n const inModelJsFile = 'wasm-model.js'\n const outWorkerJsFile = 'worker.js'\n\n // If `outputPaths` is undefined, write the `worker.js` to the prep dir\n const outputPaths = this.options?.outputPaths || [joinPath(prepDir, outWorkerJsFile)]\n\n // Add staged file entries; this will cause the generated worker to be copied\n // to the configured output paths during the \"copy staged files\" step\n // TODO: This assumes that other plugins that use the generated worker files\n // will run after the \"copy staged files\" step. There might be use cases\n // where a plugin needs access to these in `postGenerate`, in which case the\n // files will not have been copied already. Need to reconsider the ordering\n // of plugins and the \"copy staged files\" step(s).\n for (const outputPath of outputPaths) {\n const dstDir = dirname(outputPath)\n const dstFile = basename(outputPath)\n context.prepareStagedFile(srcDir, outWorkerJsFile, dstDir, dstFile)\n }\n\n // Build the worker and write generated file to the `staged/model` directory\n const viteConfig = createViteConfig(stagedModelDir, inModelJsFile, modelSpec, outWorkerJsFile)\n await build(viteConfig)\n\n // log('info', 'Done!')\n\n return true\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { dirname, resolve as resolvePath } from 'path'\nimport { fileURLToPath } from 'url'\n\nimport type { InlineConfig, Plugin as VitePlugin } from 'vite'\n\nimport type { ModelSpec } from '@sdeverywhere/build'\n\nimport { sdeNameForVensimVarName } from './var-names'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\n/**\n * This is a virtual module plugin used to inject model-specific configuration\n * values into the generated worker bundle.\n *\n * This follows the \"Virtual Modules Convention\" described here:\n * https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention\n *\n * TODO: This could be simplified by using `vite-plugin-virtual` but that\n * doesn't seem to be working correctly in an ESM setting\n */\nfunction injectModelSpec(modelSpec: ModelSpec): VitePlugin {\n const outputVarIds = modelSpec.outputs.map(o => sdeNameForVensimVarName(o.varName))\n\n const moduleSrc = `\nexport const numInputs = ${modelSpec.inputs.length};\nexport const outputVarIds = ${JSON.stringify(outputVarIds)};\n`\n\n const virtualModuleId = 'virtual:model-spec'\n const resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n return {\n name: 'vite-plugin-virtual-custom',\n resolveId(id: string) {\n if (id === virtualModuleId) {\n return resolvedVirtualModuleId\n }\n },\n load(id: string) {\n if (id === resolvedVirtualModuleId) {\n return moduleSrc\n }\n }\n }\n}\n\n/**\n * Create a Vite `InlineConfig` that can be used to build a complete\n * worker bundle that can run the generated Wasm model in a separate\n * Web Worker or Node worker thread.\n *\n * @param stagedModelDir The `staged` directory under the `sde-prep` directory.\n * @param modelJsFile The name of the JS file containing the embedded Wasm.\n * @param modelSpec The model spec generated earlier in the build process.\n * @param outputFile The name of the generated worker JS file.\n * @return An `InlineConfig` instance that can be passed to Vite's `build` function.\n */\nexport function createViteConfig(\n stagedModelDir: string,\n modelJsFile: string,\n modelSpec: ModelSpec,\n outputFile: string\n): InlineConfig {\n // Use `staged/model` as the root directory for the worker build\n const root = stagedModelDir\n\n // Use `template-worker/worker.js` from this package as the entry file\n const entry = resolvePath(__dirname, '..', 'template-worker', 'worker.js')\n\n return {\n // Don't use an external config file\n configFile: false,\n\n // Use the root directory configured above\n root,\n\n // Don't clear the screen in dev mode so that we can see builder output\n clearScreen: false,\n\n // Disable vite output by default\n // TODO: Re-enable logging if `--verbose` option is used?\n logLevel: 'silent',\n\n // Configure path aliases\n resolve: {\n alias: [\n // In the template, we use `@_wasm_` as an alias for the JS-wrapped Wasm\n // file generated by Emscripten\n {\n find: '@_wasm_',\n replacement: resolvePath(stagedModelDir, modelJsFile)\n }\n ],\n\n // XXX: Prevent Vite from using the `browser` section of `threads/package.json`\n // since we want to force the use of the general module (under dist) that chooses\n // the correct implementation (Web Worker vs worker_threads) at runtime. This\n // gets the job done, but is fragile because it applies to all dependencies even\n // though we really only need this workaround for the threads package. Fortunately\n // the worker template is very simple (only depends on `@sdeverywhere/runtime-async`,\n // which in turn only depends on `@sdeverywhere/runtime` and `threads`, so we should\n // be safe to use this workaround for a while.\n browserField: false\n },\n\n plugins: [\n // Use a virtual module plugin to inject the model spec values\n injectModelSpec(modelSpec)\n ],\n\n build: {\n // Write output file to the `staged/model` directory; note that this path is\n // relative to the bundle `root` directory\n outDir: '.',\n emptyOutDir: false,\n\n lib: {\n entry,\n name: 'worker',\n formats: ['iife'],\n fileName: () => outputFile\n },\n\n rollupOptions: {\n onwarn: (warning, warn) => {\n // XXX: Suppress \"Use of eval is strongly discouraged\" warnings that are\n // triggered by use of the following pattern in threads.js:\n // eval(\"require\")(\"worker_threads\")\n // It would be nice to avoid use of `eval` there, but it's not critical for\n // our use case so we will suppress the warnings for now\n if (warning.code !== 'EVAL') {\n warn(warning)\n }\n }\n }\n }\n }\n}\n","// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\n/**\n * Helper function that converts a Vensim variable or subscript name\n * into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nfunction sdeNameForVensimName(name: string): string {\n return (\n '_' +\n name\n .trim()\n .replace(/\"/g, '_')\n .replace(/\\s+!$/g, '!')\n .replace(/\\s/g, '_')\n .replace(/,/g, '_')\n .replace(/-/g, '_')\n .replace(/\\./g, '_')\n .replace(/\\$/g, '_')\n .replace(/'/g, '_')\n .replace(/&/g, '_')\n .replace(/%/g, '_')\n .replace(/\\//g, '_')\n .replace(/\\|/g, '_')\n .toLowerCase()\n )\n}\n\n/**\n * Helper function that converts a Vensim variable name (possibly containing\n * subscripts) into a valid C identifier as used by SDE.\n * TODO: Import helper function from `compile` package instead\n */\nexport function sdeNameForVensimVarName(varName: string): string {\n const m = varName.match(/([^[]+)(?:\\[([^\\]]+)\\])?/)\n if (!m) {\n throw new Error(`Invalid Vensim name: ${varName}`)\n }\n let id = sdeNameForVensimName(m[1])\n if (m[2]) {\n const subscripts = m[2].split(',').map(x => sdeNameForVensimName(x))\n id += `[${subscripts.join('][')}]`\n }\n\n return id\n}\n"],"mappings":"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","names":["dirname","__filename","__dirname","dirname"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdeverywhere/plugin-worker",
3
- "version": "0.1.4",
3
+ "version": "0.2.1",
4
4
  "files": [
5
5
  "dist/**",
6
6
  "template-worker/**"
@@ -17,27 +17,16 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@rollup/plugin-node-resolve": "^13.3.0",
21
- "@sdeverywhere/runtime": "^0.1.0",
22
- "@sdeverywhere/runtime-async": "^0.1.0",
23
- "rollup": "^2.76.0",
24
- "vite": "^3.1.3"
25
- },
26
- "dependenciesComments": {
27
- "rollup": [
28
- "XXX: For now, rollup is listed as a dependency even though it is not actually",
29
- "needed since we only use the @rollup plugins with vite. Those @rollup plugins",
30
- "don't technically need rollup to function properly, but they list rollup as a",
31
- "required peer dependency. To avoid making consumers worry about this, we list",
32
- "it as a dependency here."
33
- ]
20
+ "@sdeverywhere/runtime": "^0.2.0",
21
+ "@sdeverywhere/runtime-async": "^0.2.0",
22
+ "vite": "4.4.9"
34
23
  },
35
24
  "peerDependencies": {
36
- "@sdeverywhere/build": "^0.2.0"
25
+ "@sdeverywhere/build": "^0.3.0"
37
26
  },
38
27
  "devDependencies": {
39
28
  "@sdeverywhere/build": "*",
40
- "@types/node": "^16.11.7"
29
+ "@types/node": "^20.5.7"
41
30
  },
42
31
  "author": "Climate Interactive",
43
32
  "license": "MIT",
@@ -61,6 +50,7 @@
61
50
  "test:ci": "echo No tests yet",
62
51
  "type-check": "tsc --noEmit -p tsconfig-build.json",
63
52
  "build": "tsup",
64
- "ci:build": "run-s clean lint prettier:check test:ci type-check build"
53
+ "docs": "../../scripts/gen-docs.js",
54
+ "ci:build": "run-s clean lint prettier:check test:ci type-check build docs"
65
55
  }
66
56
  }
@@ -7,7 +7,7 @@ import { initWasmModelAndBuffers } from '@sdeverywhere/runtime'
7
7
  // generate a worker that won't run correctly in Node or the browser.
8
8
  import { exposeModelWorker } from '@sdeverywhere/runtime-async/worker'
9
9
 
10
- import { startTime, endTime, numInputs, outputVarIds } from 'virtual:model-spec'
10
+ import { numInputs, outputVarIds } from 'virtual:model-spec'
11
11
  import loadWasmModule from '@_wasm_'
12
12
 
13
13
  async function initWasmModel() {
@@ -15,7 +15,7 @@ async function initWasmModel() {
15
15
  const wasmModule = await loadWasmModule()
16
16
 
17
17
  // Initialize the wasm model and its associated buffers
18
- return initWasmModelAndBuffers(wasmModule, numInputs, outputVarIds, startTime, endTime)
18
+ return initWasmModelAndBuffers(wasmModule, numInputs, outputVarIds)
19
19
  }
20
20
 
21
21
  exposeModelWorker(initWasmModel)