@sdeverywhere/plugin-worker 0.2.14 → 0.2.16
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 +90 -1
- package/dist/index.d.ts +13 -11
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -88
- package/dist/index.js.map +1 -1
- package/package.json +6 -9
- package/dist/index.cjs +0 -127
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -13
package/README.md
CHANGED
|
@@ -22,7 +22,96 @@ yarn add -D @sdeverywhere/plugin-worker
|
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
_Note:_ If you followed the "Quick Start" instructions above and/or are using one of the standard project templates provided by SDEverywhere, the `sde.config.js` file should already be set up to use `plugin-worker`.
|
|
26
|
+
Reading these instructions can still be helpful if you are setting up a project manually or want to understand how `plugin-worker` can be integrated into your project.
|
|
27
|
+
|
|
28
|
+
### Why use this plugin?
|
|
29
|
+
|
|
30
|
+
Running an SDEverywhere-generated model can take long enough to make an application feel unresponsive if the model runs on the main (UI) thread.
|
|
31
|
+
This plugin bundles your generated model together with the `@sdeverywhere/runtime-async` glue code into a single, self-contained `worker.js` file.
|
|
32
|
+
When your application spawns that worker, model runs happen on a separate thread, which keeps sliders and other controls responsive.
|
|
33
|
+
|
|
34
|
+
The generated worker works in both web browser and Node.js environments without any changes on your part: it uses a Web Worker in a browser, and a worker thread in Node.js.
|
|
35
|
+
|
|
36
|
+
### Steps
|
|
37
|
+
|
|
38
|
+
1. Add `@sdeverywhere/plugin-worker` as a project "dev" dependency:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
cd your-model-project
|
|
42
|
+
npm install --save-dev @sdeverywhere/plugin-worker
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
2. Update your `sde.config.js` file to use `workerPlugin`. Make sure that `workerPlugin` runs after any plugin that produces the generated model (for example, `plugin-wasm`):
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
import { dirname, join as joinPath } from 'path'
|
|
49
|
+
import { fileURLToPath } from 'url'
|
|
50
|
+
|
|
51
|
+
import { workerPlugin } from '@sdeverywhere/plugin-worker'
|
|
52
|
+
|
|
53
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
54
|
+
const corePath = (...parts) => joinPath(__dirname, 'packages', 'core', ...parts)
|
|
55
|
+
|
|
56
|
+
export async function config() {
|
|
57
|
+
return {
|
|
58
|
+
modelFiles: ['model/example.mdl'],
|
|
59
|
+
|
|
60
|
+
// ...
|
|
61
|
+
|
|
62
|
+
plugins: [
|
|
63
|
+
// Generate a `worker.js` file that runs the model asynchronously on a
|
|
64
|
+
// worker thread for improved responsiveness
|
|
65
|
+
workerPlugin({
|
|
66
|
+
// If `outputPaths` is undefined, `worker.js` is written to the `sde-prep`
|
|
67
|
+
// directory. More commonly, you will write it into your app or library
|
|
68
|
+
// source tree so that it can be imported directly.
|
|
69
|
+
outputPaths: [corePath('src', 'model', 'generated', 'worker.js')]
|
|
70
|
+
})
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
3. Run `sde bundle` (or `sde dev`); the plugin writes a `worker.js` file to each configured output path.
|
|
77
|
+
|
|
78
|
+
_Note:_ If you set `genFormat` to `'c'` in your `sde.config.js` file, add `wasmPlugin()` before `workerPlugin()` so that the C code is compiled to a WebAssembly module first.
|
|
79
|
+
If `genFormat` is `'js'` (the default), `workerPlugin` can pick up the generated JavaScript model directly and no additional plugin is needed.
|
|
80
|
+
|
|
81
|
+
### Using the generated worker
|
|
82
|
+
|
|
83
|
+
The generated `worker.js` is a self-contained bundle, so the recommended approach is to import its source and pass it to `spawnAsyncModelRunner` from `@sdeverywhere/runtime-async`.
|
|
84
|
+
This avoids having to serve or resolve a separate worker file at runtime.
|
|
85
|
+
In a Vite-based project, you can use the `?raw` suffix to import the file as a string:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
import { spawnAsyncModelRunner } from '@sdeverywhere/runtime-async'
|
|
89
|
+
|
|
90
|
+
import workerJs from './generated/worker.js?raw'
|
|
91
|
+
|
|
92
|
+
export async function createModelRunner() {
|
|
93
|
+
return spawnAsyncModelRunner({ source: workerJs })
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Alternatively, if you serve `worker.js` as a static asset, you can spawn it by path instead:
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
const runner = await spawnAsyncModelRunner({ path: './worker.js' })
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The resulting `ModelRunner` can be used directly, or can be passed to a higher-level scheduler such as `ModelScheduler`.
|
|
104
|
+
See the [`@sdeverywhere/runtime`](https://github.com/climateinteractive/SDEverywhere/tree/main/packages/runtime) and [`@sdeverywhere/runtime-async`](https://github.com/climateinteractive/SDEverywhere/tree/main/packages/runtime-async) packages for more details.
|
|
105
|
+
|
|
106
|
+
### Writing to multiple locations
|
|
107
|
+
|
|
108
|
+
The `outputPaths` option accepts more than one path, which is useful if the same worker is needed by more than one package in a monorepo:
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
workerPlugin({
|
|
112
|
+
outputPaths: [corePath('src', 'model', 'generated', 'worker.js'), appPath('src', 'model', 'generated', 'worker.js')]
|
|
113
|
+
})
|
|
114
|
+
```
|
|
26
115
|
|
|
27
116
|
## Documentation
|
|
28
117
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { Plugin } from
|
|
2
|
-
|
|
1
|
+
import { Plugin } from "@sdeverywhere/build";
|
|
2
|
+
//#region src/options.d.ts
|
|
3
3
|
interface WorkerPluginOptions {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
9
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/plugin.d.ts
|
|
12
|
+
export declare function workerPlugin(options?: WorkerPluginOptions): Plugin;
|
|
13
|
+
//#endregion
|
|
14
|
+
export type { WorkerPluginOptions };
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/options.d.ts","../src/plugin.d.ts"],"mappings":";;UAAiB;;;;;EAKb;;;;wBCHoB,aAAa,UAAU,sBAAsB"}
|
package/dist/index.js
CHANGED
|
@@ -1,97 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
import { basename, dirname as dirname2, join as joinPath } from "path";
|
|
1
|
+
import { basename, dirname, join, resolve } from "path";
|
|
3
2
|
import { build } from "vite";
|
|
4
|
-
|
|
5
|
-
// src/vite-config.ts
|
|
6
|
-
import { dirname, resolve as resolvePath } from "path";
|
|
7
3
|
import { fileURLToPath } from "url";
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
//#region src/vite-config.ts
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
/**
|
|
8
|
+
* Create a Vite `InlineConfig` that can be used to build a complete
|
|
9
|
+
* worker bundle that can run the generated Wasm model in a separate
|
|
10
|
+
* Web Worker or Node worker thread.
|
|
11
|
+
*
|
|
12
|
+
* @param stagedModelDir The `staged` directory under the `sde-prep` directory.
|
|
13
|
+
* @param modelJsFile The name of the JS file containing the generated JS or Wasm model.
|
|
14
|
+
* @param outputFile The name of the generated worker JS file.
|
|
15
|
+
* @return An `InlineConfig` instance that can be passed to Vite's `build` function.
|
|
16
|
+
*/
|
|
10
17
|
function createViteConfig(stagedModelDir, modelJsFile, outputFile) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// XXX: Prevent Vite from using the `browser` section of `threads/package.json`
|
|
34
|
-
// since we want to force the use of the general module (under dist) that chooses
|
|
35
|
-
// the correct implementation (Web Worker vs worker_threads) at runtime. This
|
|
36
|
-
// gets the job done, but is fragile because it applies to all dependencies even
|
|
37
|
-
// though we really only need this workaround for the threads package. Fortunately
|
|
38
|
-
// the worker template is very simple (only depends on `@sdeverywhere/runtime-async`,
|
|
39
|
-
// which in turn only depends on `@sdeverywhere/runtime` and `threads`, so we should
|
|
40
|
-
// be safe to use this workaround for a while. Note that the default value of this
|
|
41
|
-
// property is `['browser', 'module', 'jsnext:main', 'jsnext']`, so we override it
|
|
42
|
-
// to omit the 'browser' item.
|
|
43
|
-
mainFields: ["module", "jsnext:main", "jsnext"]
|
|
44
|
-
},
|
|
45
|
-
build: {
|
|
46
|
-
// Write output file to the `staged/model` directory; note that this path is
|
|
47
|
-
// relative to the bundle `root` directory
|
|
48
|
-
outDir: ".",
|
|
49
|
-
emptyOutDir: false,
|
|
50
|
-
lib: {
|
|
51
|
-
entry,
|
|
52
|
-
name: "worker",
|
|
53
|
-
formats: ["iife"],
|
|
54
|
-
fileName: () => outputFile
|
|
55
|
-
},
|
|
56
|
-
rollupOptions: {
|
|
57
|
-
onwarn: (warning, warn) => {
|
|
58
|
-
if (warning.code !== "EVAL") {
|
|
59
|
-
warn(warning);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
};
|
|
18
|
+
const root = stagedModelDir;
|
|
19
|
+
const entry = resolve(__dirname, "..", "template-worker", "worker.js");
|
|
20
|
+
return {
|
|
21
|
+
configFile: false,
|
|
22
|
+
root,
|
|
23
|
+
clearScreen: false,
|
|
24
|
+
logLevel: "silent",
|
|
25
|
+
resolve: { alias: [{
|
|
26
|
+
find: "@_generatedModelFile_",
|
|
27
|
+
replacement: resolve(stagedModelDir, modelJsFile)
|
|
28
|
+
}] },
|
|
29
|
+
build: {
|
|
30
|
+
outDir: ".",
|
|
31
|
+
emptyOutDir: false,
|
|
32
|
+
lib: {
|
|
33
|
+
entry,
|
|
34
|
+
name: "worker",
|
|
35
|
+
formats: ["iife"],
|
|
36
|
+
fileName: () => outputFile
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
65
40
|
}
|
|
66
|
-
|
|
67
|
-
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/plugin.ts
|
|
68
43
|
function workerPlugin(options) {
|
|
69
|
-
|
|
44
|
+
return new WorkerPlugin(options);
|
|
70
45
|
}
|
|
71
46
|
var WorkerPlugin = class {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
};
|
|
94
|
-
export {
|
|
95
|
-
workerPlugin
|
|
47
|
+
constructor(options) {
|
|
48
|
+
this.options = options;
|
|
49
|
+
}
|
|
50
|
+
async postGenerate(context) {
|
|
51
|
+
const log = context.log;
|
|
52
|
+
log("info", "Building worker");
|
|
53
|
+
const prepDir = context.config.prepDir;
|
|
54
|
+
const srcDir = "model";
|
|
55
|
+
const stagedModelDir = join(prepDir, "staged", srcDir);
|
|
56
|
+
const inModelJsFile = "generated-model.js";
|
|
57
|
+
const outWorkerJsFile = "worker.js";
|
|
58
|
+
const outputPaths = this.options?.outputPaths || [join(prepDir, outWorkerJsFile)];
|
|
59
|
+
for (const outputPath of outputPaths) {
|
|
60
|
+
const dstDir = dirname(outputPath);
|
|
61
|
+
const dstFile = basename(outputPath);
|
|
62
|
+
context.prepareStagedFile(srcDir, outWorkerJsFile, dstDir, dstFile);
|
|
63
|
+
}
|
|
64
|
+
const viteConfig = createViteConfig(stagedModelDir, inModelJsFile, outWorkerJsFile);
|
|
65
|
+
await build(viteConfig);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
96
68
|
};
|
|
69
|
+
//#endregion
|
|
70
|
+
export { workerPlugin };
|
|
71
|
+
|
|
97
72
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"index.js","names":["resolvePath","joinPath"],"sources":["../src/vite-config.ts","../src/plugin.ts"],"sourcesContent":["// Copyright (c) 2022 Climate Interactive / New Venture Fund\n\nimport { dirname, resolve as resolvePath } from 'path'\nimport { fileURLToPath } from 'url'\n\nimport type { InlineConfig } from 'vite'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\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 generated JS or Wasm model.\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(stagedModelDir: string, modelJsFile: string, outputFile: string): 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 `@_generatedModelFile_` as an alias for the model\n // file containing the generated JS or Wasm model\n {\n find: '@_generatedModelFile_',\n replacement: resolvePath(stagedModelDir, modelJsFile)\n }\n ]\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 }\n}\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, 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): Promise<boolean> {\n const log = context.log\n log('info', 'Building worker')\n\n // Locate the generated model file in the staged directory. Note that this\n // relies on the `build` package writing the JS model (or the `plugin-wasm`\n // package writing the Wasm model) to a file called `generated-model.js`\n // in the `staged/model` directory.\n // TODO: Allow for customizing the file name/path\n const prepDir = context.config.prepDir\n const srcDir = 'model'\n const stagedModelDir = joinPath(prepDir, 'staged', srcDir)\n const inModelJsFile = 'generated-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, outWorkerJsFile)\n await build(viteConfig)\n\n // log('info', 'Done!')\n\n return true\n }\n}\n"],"mappings":";;;;AAOA,MAAM,aAAa,cAAc,YAAY,GAAG;AAChD,MAAM,YAAY,QAAQ,UAAU;;;;;;;;;;;AAYpC,SAAgB,iBAAiB,gBAAwB,aAAqB,YAAkC;CAE9G,MAAM,OAAO;CAGb,MAAM,QAAQA,QAAY,WAAW,MAAM,mBAAmB,WAAW;CAEzE,OAAO;EAEL,YAAY;EAGZ;EAGA,aAAa;EAIb,UAAU;EAGV,SAAS,EACP,OAAO,CAGL;GACE,MAAM;GACN,aAAaA,QAAY,gBAAgB,WAAW;EACtD,CACF,EACF;EAEA,OAAO;GAGL,QAAQ;GACR,aAAa;GAEb,KAAK;IACH;IACA,MAAM;IACN,SAAS,CAAC,MAAM;IAChB,gBAAgB;GAClB;EACF;CACF;AACF;;;ACxDA,SAAgB,aAAa,SAAuC;CAClE,OAAO,IAAI,aAAa,OAAO;AACjC;AAEA,IAAM,eAAN,MAAqC;CACnC,YAAY,SAAgD;EAA/B,KAAA,UAAA;CAAgC;CAE7D,MAAM,aAAa,SAAyC;EAC1D,MAAM,MAAM,QAAQ;EACpB,IAAI,QAAQ,iBAAiB;EAO7B,MAAM,UAAU,QAAQ,OAAO;EAC/B,MAAM,SAAS;EACf,MAAM,iBAAiBC,KAAS,SAAS,UAAU,MAAM;EACzD,MAAM,gBAAgB;EACtB,MAAM,kBAAkB;EAGxB,MAAM,cAAc,KAAK,SAAS,eAAe,CAACA,KAAS,SAAS,eAAe,CAAC;EASpF,KAAK,MAAM,cAAc,aAAa;GACpC,MAAM,SAAS,QAAQ,UAAU;GACjC,MAAM,UAAU,SAAS,UAAU;GACnC,QAAQ,kBAAkB,QAAQ,iBAAiB,QAAQ,OAAO;EACpE;EAGA,MAAM,aAAa,iBAAiB,gBAAgB,eAAe,eAAe;EAClF,MAAM,MAAM,UAAU;EAItB,OAAO;CACT;AACF"}
|
package/package.json
CHANGED
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdeverywhere/plugin-worker",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist/**",
|
|
6
6
|
"template-worker/**"
|
|
7
7
|
],
|
|
8
8
|
"type": "module",
|
|
9
|
-
"main": "dist/index.cjs",
|
|
10
9
|
"module": "dist/index.js",
|
|
11
10
|
"types": "dist/index.d.ts",
|
|
12
11
|
"exports": {
|
|
13
12
|
".": {
|
|
14
13
|
"types": "./dist/index.d.ts",
|
|
15
|
-
"import": "./dist/index.js"
|
|
16
|
-
"require": "./dist/index.cjs"
|
|
14
|
+
"import": "./dist/index.js"
|
|
17
15
|
}
|
|
18
16
|
},
|
|
19
17
|
"dependencies": {
|
|
20
|
-
"@sdeverywhere/runtime": "^0.2.
|
|
21
|
-
"@sdeverywhere/runtime-async": "^0.2.
|
|
22
|
-
"vite": "^
|
|
18
|
+
"@sdeverywhere/runtime": "^0.2.11",
|
|
19
|
+
"@sdeverywhere/runtime-async": "^0.2.11",
|
|
20
|
+
"vite": "^8.3.0"
|
|
23
21
|
},
|
|
24
22
|
"peerDependencies": {
|
|
25
23
|
"@sdeverywhere/build": "^0.3.10"
|
|
26
24
|
},
|
|
27
25
|
"devDependencies": {
|
|
28
|
-
"@sdeverywhere/build": "*",
|
|
29
26
|
"@types/node": "^20.14.8"
|
|
30
27
|
},
|
|
31
28
|
"author": "Climate Interactive",
|
|
@@ -49,7 +46,7 @@
|
|
|
49
46
|
"test:watch": "echo No tests yet",
|
|
50
47
|
"test:ci": "echo No tests yet",
|
|
51
48
|
"type-check": "tsc --noEmit -p tsconfig-test.json",
|
|
52
|
-
"build": "
|
|
49
|
+
"build": "tsdown",
|
|
53
50
|
"docs": "../../scripts/gen-docs.js",
|
|
54
51
|
"ci:build": "run-s clean lint prettier:check test:ci type-check build docs"
|
|
55
52
|
}
|
package/dist/index.cjs
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __export = (target, all) => {
|
|
6
|
-
for (var name in all)
|
|
7
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
-
|
|
19
|
-
// src/index.ts
|
|
20
|
-
var index_exports = {};
|
|
21
|
-
__export(index_exports, {
|
|
22
|
-
workerPlugin: () => workerPlugin
|
|
23
|
-
});
|
|
24
|
-
module.exports = __toCommonJS(index_exports);
|
|
25
|
-
|
|
26
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_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.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
28
|
-
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
29
|
-
|
|
30
|
-
// src/plugin.ts
|
|
31
|
-
var import_path2 = require("path");
|
|
32
|
-
var import_vite = require("vite");
|
|
33
|
-
|
|
34
|
-
// src/vite-config.ts
|
|
35
|
-
var import_path = require("path");
|
|
36
|
-
var import_url = require("url");
|
|
37
|
-
var __filename2 = (0, import_url.fileURLToPath)(importMetaUrl);
|
|
38
|
-
var __dirname = (0, import_path.dirname)(__filename2);
|
|
39
|
-
function createViteConfig(stagedModelDir, modelJsFile, outputFile) {
|
|
40
|
-
const root = stagedModelDir;
|
|
41
|
-
const entry = (0, import_path.resolve)(__dirname, "..", "template-worker", "worker.js");
|
|
42
|
-
return {
|
|
43
|
-
// Don't use an external config file
|
|
44
|
-
configFile: false,
|
|
45
|
-
// Use the root directory configured above
|
|
46
|
-
root,
|
|
47
|
-
// Don't clear the screen in dev mode so that we can see builder output
|
|
48
|
-
clearScreen: false,
|
|
49
|
-
// Disable vite output by default
|
|
50
|
-
// TODO: Re-enable logging if `--verbose` option is used?
|
|
51
|
-
logLevel: "silent",
|
|
52
|
-
// Configure path aliases
|
|
53
|
-
resolve: {
|
|
54
|
-
alias: [
|
|
55
|
-
// In the template, we use `@_generatedModelFile_` as an alias for the model
|
|
56
|
-
// file containing the generated JS or Wasm model
|
|
57
|
-
{
|
|
58
|
-
find: "@_generatedModelFile_",
|
|
59
|
-
replacement: (0, import_path.resolve)(stagedModelDir, modelJsFile)
|
|
60
|
-
}
|
|
61
|
-
],
|
|
62
|
-
// XXX: Prevent Vite from using the `browser` section of `threads/package.json`
|
|
63
|
-
// since we want to force the use of the general module (under dist) that chooses
|
|
64
|
-
// the correct implementation (Web Worker vs worker_threads) at runtime. This
|
|
65
|
-
// gets the job done, but is fragile because it applies to all dependencies even
|
|
66
|
-
// though we really only need this workaround for the threads package. Fortunately
|
|
67
|
-
// the worker template is very simple (only depends on `@sdeverywhere/runtime-async`,
|
|
68
|
-
// which in turn only depends on `@sdeverywhere/runtime` and `threads`, so we should
|
|
69
|
-
// be safe to use this workaround for a while. Note that the default value of this
|
|
70
|
-
// property is `['browser', 'module', 'jsnext:main', 'jsnext']`, so we override it
|
|
71
|
-
// to omit the 'browser' item.
|
|
72
|
-
mainFields: ["module", "jsnext:main", "jsnext"]
|
|
73
|
-
},
|
|
74
|
-
build: {
|
|
75
|
-
// Write output file to the `staged/model` directory; note that this path is
|
|
76
|
-
// relative to the bundle `root` directory
|
|
77
|
-
outDir: ".",
|
|
78
|
-
emptyOutDir: false,
|
|
79
|
-
lib: {
|
|
80
|
-
entry,
|
|
81
|
-
name: "worker",
|
|
82
|
-
formats: ["iife"],
|
|
83
|
-
fileName: () => outputFile
|
|
84
|
-
},
|
|
85
|
-
rollupOptions: {
|
|
86
|
-
onwarn: (warning, warn) => {
|
|
87
|
-
if (warning.code !== "EVAL") {
|
|
88
|
-
warn(warning);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// src/plugin.ts
|
|
97
|
-
function workerPlugin(options) {
|
|
98
|
-
return new WorkerPlugin(options);
|
|
99
|
-
}
|
|
100
|
-
var WorkerPlugin = class {
|
|
101
|
-
constructor(options) {
|
|
102
|
-
this.options = options;
|
|
103
|
-
}
|
|
104
|
-
async postGenerate(context) {
|
|
105
|
-
const log = context.log;
|
|
106
|
-
log("info", "Building worker");
|
|
107
|
-
const prepDir = context.config.prepDir;
|
|
108
|
-
const srcDir = "model";
|
|
109
|
-
const stagedModelDir = (0, import_path2.join)(prepDir, "staged", srcDir);
|
|
110
|
-
const inModelJsFile = "generated-model.js";
|
|
111
|
-
const outWorkerJsFile = "worker.js";
|
|
112
|
-
const outputPaths = this.options?.outputPaths || [(0, import_path2.join)(prepDir, outWorkerJsFile)];
|
|
113
|
-
for (const outputPath of outputPaths) {
|
|
114
|
-
const dstDir = (0, import_path2.dirname)(outputPath);
|
|
115
|
-
const dstFile = (0, import_path2.basename)(outputPath);
|
|
116
|
-
context.prepareStagedFile(srcDir, outWorkerJsFile, dstDir, dstFile);
|
|
117
|
-
}
|
|
118
|
-
const viteConfig = createViteConfig(stagedModelDir, inModelJsFile, outWorkerJsFile);
|
|
119
|
-
await (0, import_vite.build)(viteConfig);
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
124
|
-
0 && (module.exports = {
|
|
125
|
-
workerPlugin
|
|
126
|
-
});
|
|
127
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_typescript@5.2.2/node_modules/tsup/assets/cjs_shims.js","../src/plugin.ts","../src/vite-config.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.tagName.toUpperCase() === 'SCRIPT') \n ? 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, 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): Promise<boolean> {\n const log = context.log\n log('info', 'Building worker')\n\n // Locate the generated model file in the staged directory. Note that this\n // relies on the `build` package writing the JS model (or the `plugin-wasm`\n // package writing the Wasm model) to a file called `generated-model.js`\n // in the `staged/model` directory.\n // TODO: Allow for customizing the file name/path\n const prepDir = context.config.prepDir\n const srcDir = 'model'\n const stagedModelDir = joinPath(prepDir, 'staged', srcDir)\n const inModelJsFile = 'generated-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, 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 } from 'vite'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\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 generated JS or Wasm model.\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(stagedModelDir: string, modelJsFile: string, outputFile: string): 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 `@_generatedModelFile_` as an alias for the model\n // file containing the generated JS or Wasm model\n {\n find: '@_generatedModelFile_',\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. Note that the default value of this\n // property is `['browser', 'module', 'jsnext:main', 'jsnext']`, so we override it\n // to omit the 'browser' item.\n mainFields: ['module', 'jsnext:main', 'jsnext']\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"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,IAAM,mBAAmB,MACvB,OAAO,aAAa,cAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,OAC7B,SAAS,iBAAiB,SAAS,cAAc,QAAQ,YAAY,MAAM,WAC1E,SAAS,cAAc,MACvB,IAAI,IAAI,WAAW,SAAS,OAAO,EAAE;AAEtC,IAAM,gBAAgC,iCAAiB;;;ACV9D,IAAAA,eAAoD;AAEpD,kBAAsB;;;ACFtB,kBAAgD;AAChD,iBAA8B;AAI9B,IAAMC,kBAAa,0BAAc,aAAe;AAChD,IAAM,gBAAY,qBAAQA,WAAU;AAY7B,SAAS,iBAAiB,gBAAwB,aAAqB,YAAkC;AAE9G,QAAM,OAAO;AAGb,QAAM,YAAQ,YAAAC,SAAY,WAAW,MAAM,mBAAmB,WAAW;AAEzE,SAAO;AAAA;AAAA,IAEL,YAAY;AAAA;AAAA,IAGZ;AAAA;AAAA,IAGA,aAAa;AAAA;AAAA;AAAA,IAIb,UAAU;AAAA;AAAA,IAGV,SAAS;AAAA,MACP,OAAO;AAAA;AAAA;AAAA,QAGL;AAAA,UACE,MAAM;AAAA,UACN,iBAAa,YAAAA,SAAY,gBAAgB,WAAW;AAAA,QACtD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,YAAY,CAAC,UAAU,eAAe,QAAQ;AAAA,IAChD;AAAA,IAEA,OAAO;AAAA;AAAA;AAAA,MAGL,QAAQ;AAAA,MACR,aAAa;AAAA,MAEb,KAAK;AAAA,QACH;AAAA,QACA,MAAM;AAAA,QACN,SAAS,CAAC,MAAM;AAAA,QAChB,UAAU,MAAM;AAAA,MAClB;AAAA,MAEA,eAAe;AAAA,QACb,QAAQ,CAAC,SAAS,SAAS;AAMzB,cAAI,QAAQ,SAAS,QAAQ;AAC3B,iBAAK,OAAO;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ADjFO,SAAS,aAAa,SAAuC;AAClE,SAAO,IAAI,aAAa,OAAO;AACjC;AAEA,IAAM,eAAN,MAAqC;AAAA,EACnC,YAA6B,SAA+B;AAA/B;AAAA,EAAgC;AAAA,EAE7D,MAAM,aAAa,SAAyC;AAC1D,UAAM,MAAM,QAAQ;AACpB,QAAI,QAAQ,iBAAiB;AAO7B,UAAM,UAAU,QAAQ,OAAO;AAC/B,UAAM,SAAS;AACf,UAAM,qBAAiB,aAAAC,MAAS,SAAS,UAAU,MAAM;AACzD,UAAM,gBAAgB;AACtB,UAAM,kBAAkB;AAGxB,UAAM,cAAc,KAAK,SAAS,eAAe,KAAC,aAAAA,MAAS,SAAS,eAAe,CAAC;AASpF,eAAW,cAAc,aAAa;AACpC,YAAM,aAAS,sBAAQ,UAAU;AACjC,YAAM,cAAU,uBAAS,UAAU;AACnC,cAAQ,kBAAkB,QAAQ,iBAAiB,QAAQ,OAAO;AAAA,IACpE;AAGA,UAAM,aAAa,iBAAiB,gBAAgB,eAAe,eAAe;AAClF,cAAM,mBAAM,UAAU;AAItB,WAAO;AAAA,EACT;AACF;","names":["import_path","__filename","resolvePath","joinPath"]}
|
package/dist/index.d.cts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
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 { type WorkerPluginOptions, workerPlugin };
|