@slithy/prim-interface 1.0.4 → 1.0.6

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.
Files changed (3) hide show
  1. package/README.md +9 -0
  2. package/dist/index.js +33 -11
  3. package/package.json +7 -7
package/README.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  Browser-facing API for `@slithy/prim-lib`. Consumed by `apps/prim-demo`.
4
4
 
5
+ ## License
6
+
7
+ This package is dual-licensed.
8
+
9
+ - Public use is licensed under `PolyForm-Noncommercial-1.0.0` in [LICENSE](./LICENSE).
10
+ - Separate commercial use rights, if any, are granted only by a separate written commercial license. The current repo-tracked commercial grant is in [LICENSE-COMMERCIAL.md](./LICENSE-COMMERCIAL.md).
11
+
12
+ This package also includes upstream MIT attributions for `primitive` and `primitive.js` in its `LICENSE` file.
13
+
5
14
  ## What it does
6
15
 
7
16
  Wraps `prim-lib` in a `run()` / `runWorker()` API and provides save/copy/share helpers for exporting results. `run()` runs the optimizer on the main thread; `runWorker()` moves computation into a Web Worker, keeping the main thread responsive during long jobs. Both share the same callback API.
package/dist/index.js CHANGED
@@ -87,11 +87,23 @@ function runWorker(source, cfg, callbacks = {}) {
87
87
  const url = source instanceof File ? URL.createObjectURL(source) : new URL(source, globalThis.location.href).href;
88
88
  const isBlob = source instanceof File;
89
89
  let stopped = false;
90
+ let settled = false;
90
91
  let result = null;
91
92
  let svgEl = null;
92
93
  const serializer = new XMLSerializer();
93
94
  const worker = new Worker(new URL("./worker-entry.js", import.meta.url), { type: "module" });
95
+ const finalize = (cb) => {
96
+ if (settled) return;
97
+ settled = true;
98
+ if (isBlob) URL.revokeObjectURL(url);
99
+ try {
100
+ cb();
101
+ } finally {
102
+ worker.terminate();
103
+ }
104
+ };
94
105
  worker.onmessage = (e) => {
106
+ if (settled) return;
95
107
  const msg = e.data;
96
108
  if (msg.type === "ready") {
97
109
  const { width, height, scale, fill, outputFill } = msg;
@@ -130,19 +142,23 @@ function runWorker(source, cfg, callbacks = {}) {
130
142
  progress
131
143
  });
132
144
  } else if (msg.type === "complete") {
133
- if (isBlob) URL.revokeObjectURL(url);
134
- callbacks.onComplete?.(msg.serialized);
145
+ finalize(() => {
146
+ callbacks.onComplete?.(msg.serialized);
147
+ });
135
148
  } else if (msg.type === "stopped") {
136
- if (isBlob) URL.revokeObjectURL(url);
137
- callbacks.onStop?.(msg.serialized);
149
+ finalize(() => {
150
+ callbacks.onStop?.(msg.serialized);
151
+ });
138
152
  } else if (msg.type === "error") {
139
- if (isBlob) URL.revokeObjectURL(url);
140
- callbacks.onError?.(msg.message);
153
+ finalize(() => {
154
+ callbacks.onError?.(msg.message);
155
+ });
141
156
  }
142
157
  };
143
158
  worker.onerror = (e) => {
144
- if (isBlob) URL.revokeObjectURL(url);
145
- callbacks.onError?.(e.message ?? "Unknown worker error");
159
+ finalize(() => {
160
+ callbacks.onError?.(e.message ?? "Unknown worker error");
161
+ });
146
162
  };
147
163
  const { shapeTypes, pixelRatio: _pr, width: _w, height: _h, scale: _s, ...rest } = cfg;
148
164
  const workerCfg = {
@@ -154,12 +170,18 @@ function runWorker(source, cfg, callbacks = {}) {
154
170
  worker.postMessage({ type: "start", url, cfg: workerCfg });
155
171
  return {
156
172
  stop: () => {
157
- if (stopped) return;
173
+ if (stopped || settled) return;
158
174
  stopped = true;
159
175
  worker.postMessage({ type: "stop" });
160
176
  },
161
- pause: () => worker.postMessage({ type: "pause" }),
162
- resume: () => worker.postMessage({ type: "resume" })
177
+ pause: () => {
178
+ if (settled) return;
179
+ worker.postMessage({ type: "pause" });
180
+ },
181
+ resume: () => {
182
+ if (settled) return;
183
+ worker.postMessage({ type: "resume" });
184
+ }
163
185
  };
164
186
  }
165
187
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slithy/prim-interface",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Browser-facing API for primitive-based image reconstruction.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,16 +18,16 @@
18
18
  ],
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
- "@slithy/prim-lib": "0.8.0"
21
+ "@slithy/prim-lib": "0.8.1"
22
22
  },
23
23
  "devDependencies": {
24
- "@vitest/coverage-v8": "^4.1.2",
25
- "jsdom": "^29.0.1",
24
+ "@vitest/coverage-v8": "^4.1.7",
25
+ "jsdom": "^29.1.1",
26
26
  "tsup": "^8",
27
27
  "typescript": "^5",
28
- "vitest": "^4.1.2",
29
- "@slithy/tsconfig": "0.0.0",
30
- "@slithy/eslint-config": "0.0.0"
28
+ "vitest": "^4.1.7",
29
+ "@slithy/eslint-config": "0.0.0",
30
+ "@slithy/tsconfig": "0.0.0"
31
31
  },
32
32
  "author": {
33
33
  "name": "Matthew Campagna",