automatick 0.0.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.
Files changed (65) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +106 -0
  3. package/dist/chunk-66FUVAAG.js +7 -0
  4. package/dist/chunk-AIKB2FNR.js +17 -0
  5. package/dist/chunk-HTH6FQ7C.js +192 -0
  6. package/dist/chunk-OA6FGXTP.js +9 -0
  7. package/dist/chunk-SK5SHIWY.js +13 -0
  8. package/dist/chunk-YNLOTPDY.js +206 -0
  9. package/dist/engine.cjs +231 -0
  10. package/dist/engine.d.cts +72 -0
  11. package/dist/engine.d.ts +72 -0
  12. package/dist/engine.js +8 -0
  13. package/dist/react/EngineContext.cjs +43 -0
  14. package/dist/react/EngineContext.d.cts +18 -0
  15. package/dist/react/EngineContext.d.ts +18 -0
  16. package/dist/react/EngineContext.js +6 -0
  17. package/dist/react/PerformanceOverlay.cjs +341 -0
  18. package/dist/react/PerformanceOverlay.d.cts +9 -0
  19. package/dist/react/PerformanceOverlay.d.ts +9 -0
  20. package/dist/react/PerformanceOverlay.js +290 -0
  21. package/dist/react/Simulation.cjs +481 -0
  22. package/dist/react/Simulation.d.cts +31 -0
  23. package/dist/react/Simulation.d.ts +31 -0
  24. package/dist/react/Simulation.js +235 -0
  25. package/dist/react/SimulationContext.cjs +41 -0
  26. package/dist/react/SimulationContext.d.cts +25 -0
  27. package/dist/react/SimulationContext.d.ts +25 -0
  28. package/dist/react/SimulationContext.js +6 -0
  29. package/dist/react/SimulationControls.cjs +298 -0
  30. package/dist/react/SimulationControls.d.cts +33 -0
  31. package/dist/react/SimulationControls.d.ts +33 -0
  32. package/dist/react/SimulationControls.js +80 -0
  33. package/dist/react/controlPrimitives.cjs +247 -0
  34. package/dist/react/controlPrimitives.d.cts +45 -0
  35. package/dist/react/controlPrimitives.d.ts +45 -0
  36. package/dist/react/controlPrimitives.js +22 -0
  37. package/dist/react/hooks.cjs +53 -0
  38. package/dist/react/hooks.d.cts +26 -0
  39. package/dist/react/hooks.d.ts +26 -0
  40. package/dist/react/hooks.js +7 -0
  41. package/dist/react/stableCallback.cjs +47 -0
  42. package/dist/react/stableCallback.d.cts +3 -0
  43. package/dist/react/stableCallback.d.ts +3 -0
  44. package/dist/react/stableCallback.js +6 -0
  45. package/dist/react/useSimulationCanvas.cjs +92 -0
  46. package/dist/react/useSimulationCanvas.d.cts +38 -0
  47. package/dist/react/useSimulationCanvas.d.ts +38 -0
  48. package/dist/react/useSimulationCanvas.js +53 -0
  49. package/dist/sim.cjs +32 -0
  50. package/dist/sim.d.cts +40 -0
  51. package/dist/sim.d.ts +40 -0
  52. package/dist/sim.js +7 -0
  53. package/dist/worker/createSimWorker.cjs +147 -0
  54. package/dist/worker/createSimWorker.d.cts +19 -0
  55. package/dist/worker/createSimWorker.d.ts +19 -0
  56. package/dist/worker/createSimWorker.js +122 -0
  57. package/dist/worker/protocol.cjs +18 -0
  58. package/dist/worker/protocol.d.cts +59 -0
  59. package/dist/worker/protocol.d.ts +59 -0
  60. package/dist/worker/protocol.js +0 -0
  61. package/dist/worker/workerRunner.cjs +100 -0
  62. package/dist/worker/workerRunner.d.cts +30 -0
  63. package/dist/worker/workerRunner.d.ts +30 -0
  64. package/dist/worker/workerRunner.js +73 -0
  65. package/package.json +102 -0
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/react/useSimulationCanvas.ts
31
+ var useSimulationCanvas_exports = {};
32
+ __export(useSimulationCanvas_exports, {
33
+ useSimulationCanvas: () => useSimulationCanvas
34
+ });
35
+ module.exports = __toCommonJS(useSimulationCanvas_exports);
36
+ var import_react2 = __toESM(require("react"), 1);
37
+
38
+ // src/react/EngineContext.tsx
39
+ var import_react = __toESM(require("react"), 1);
40
+ var EngineContext = import_react.default.createContext(
41
+ null
42
+ );
43
+
44
+ // src/react/useSimulationCanvas.ts
45
+ function useSimulationCanvas(draw) {
46
+ const engineCtx = import_react2.default.useContext(EngineContext);
47
+ if (!engineCtx) {
48
+ throw new Error(
49
+ "useSimulationCanvas must be used within a <Simulation>"
50
+ );
51
+ }
52
+ const canvasRef = import_react2.default.useRef(null);
53
+ const drawRef = import_react2.default.useRef(draw);
54
+ drawRef.current = draw;
55
+ import_react2.default.useEffect(() => {
56
+ const canvas = canvasRef.current;
57
+ if (canvas) {
58
+ const ctx = canvas.getContext("2d");
59
+ if (ctx) {
60
+ const snap = engineCtx.getSnapshot();
61
+ const t0 = performance.now();
62
+ drawRef.current(ctx, {
63
+ data: snap.data,
64
+ params: snap.params,
65
+ tick: snap.tick
66
+ });
67
+ engineCtx.recordDrawTime(snap.tick, performance.now() - t0);
68
+ }
69
+ }
70
+ const unsubscribe = engineCtx.subscribe(
71
+ (snap) => {
72
+ const canvas2 = canvasRef.current;
73
+ if (!canvas2) return;
74
+ const ctx = canvas2.getContext("2d");
75
+ if (!ctx) return;
76
+ const t0 = performance.now();
77
+ drawRef.current(ctx, {
78
+ data: snap.data,
79
+ params: snap.params,
80
+ tick: snap.tick
81
+ });
82
+ engineCtx.recordDrawTime(snap.tick, performance.now() - t0);
83
+ }
84
+ );
85
+ return unsubscribe;
86
+ }, [engineCtx]);
87
+ return canvasRef;
88
+ }
89
+ // Annotate the CommonJS export names for ESM import in node:
90
+ 0 && (module.exports = {
91
+ useSimulationCanvas
92
+ });
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { SimModule } from '../sim.cjs';
3
+
4
+ /**
5
+ * Draw callback signature for useSimulationCanvas.
6
+ * Called imperatively on every engine snapshot — no React re-render involved.
7
+ */
8
+ type CanvasDrawFn<Data, Params> = (ctx: CanvasRenderingContext2D, snapshot: {
9
+ data: Data;
10
+ params: Params;
11
+ tick: number;
12
+ }) => void;
13
+ type InferDraw<T, FallbackParams> = T extends SimModule<infer D, infer P> ? CanvasDrawFn<D, P> : CanvasDrawFn<T, FallbackParams>;
14
+ /**
15
+ * Subscribe to simulation snapshots and draw to a canvas without React re-renders.
16
+ *
17
+ * Returns a ref to attach to a `<canvas>` element. The `draw` callback is called
18
+ * directly from the engine's subscription — it bypasses React's state/reconciliation
19
+ * entirely. Draw timing is recorded automatically to the engine's performance buffer.
20
+ *
21
+ * For DOM/React rendering, use `useSimulation()` instead.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * function BoidsCanvas() {
26
+ * const canvasRef = useSimulationCanvas<typeof boidsSim>((ctx, { data, params }) => {
27
+ * ctx.clearRect(0, 0, params.width, params.height);
28
+ * data.forEach(boid => {
29
+ * ctx.fillRect(boid.x, boid.y, 3, 3);
30
+ * });
31
+ * });
32
+ * return <canvas ref={canvasRef} width={400} height={400} />;
33
+ * }
34
+ * ```
35
+ */
36
+ declare function useSimulationCanvas<T = unknown, FallbackParams = unknown>(draw: InferDraw<T, FallbackParams>): React.RefObject<HTMLCanvasElement>;
37
+
38
+ export { type CanvasDrawFn, useSimulationCanvas };
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { SimModule } from '../sim.js';
3
+
4
+ /**
5
+ * Draw callback signature for useSimulationCanvas.
6
+ * Called imperatively on every engine snapshot — no React re-render involved.
7
+ */
8
+ type CanvasDrawFn<Data, Params> = (ctx: CanvasRenderingContext2D, snapshot: {
9
+ data: Data;
10
+ params: Params;
11
+ tick: number;
12
+ }) => void;
13
+ type InferDraw<T, FallbackParams> = T extends SimModule<infer D, infer P> ? CanvasDrawFn<D, P> : CanvasDrawFn<T, FallbackParams>;
14
+ /**
15
+ * Subscribe to simulation snapshots and draw to a canvas without React re-renders.
16
+ *
17
+ * Returns a ref to attach to a `<canvas>` element. The `draw` callback is called
18
+ * directly from the engine's subscription — it bypasses React's state/reconciliation
19
+ * entirely. Draw timing is recorded automatically to the engine's performance buffer.
20
+ *
21
+ * For DOM/React rendering, use `useSimulation()` instead.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * function BoidsCanvas() {
26
+ * const canvasRef = useSimulationCanvas<typeof boidsSim>((ctx, { data, params }) => {
27
+ * ctx.clearRect(0, 0, params.width, params.height);
28
+ * data.forEach(boid => {
29
+ * ctx.fillRect(boid.x, boid.y, 3, 3);
30
+ * });
31
+ * });
32
+ * return <canvas ref={canvasRef} width={400} height={400} />;
33
+ * }
34
+ * ```
35
+ */
36
+ declare function useSimulationCanvas<T = unknown, FallbackParams = unknown>(draw: InferDraw<T, FallbackParams>): React.RefObject<HTMLCanvasElement>;
37
+
38
+ export { type CanvasDrawFn, useSimulationCanvas };
@@ -0,0 +1,53 @@
1
+ import {
2
+ EngineContext
3
+ } from "../chunk-OA6FGXTP.js";
4
+
5
+ // src/react/useSimulationCanvas.ts
6
+ import React from "react";
7
+ function useSimulationCanvas(draw) {
8
+ const engineCtx = React.useContext(EngineContext);
9
+ if (!engineCtx) {
10
+ throw new Error(
11
+ "useSimulationCanvas must be used within a <Simulation>"
12
+ );
13
+ }
14
+ const canvasRef = React.useRef(null);
15
+ const drawRef = React.useRef(draw);
16
+ drawRef.current = draw;
17
+ React.useEffect(() => {
18
+ const canvas = canvasRef.current;
19
+ if (canvas) {
20
+ const ctx = canvas.getContext("2d");
21
+ if (ctx) {
22
+ const snap = engineCtx.getSnapshot();
23
+ const t0 = performance.now();
24
+ drawRef.current(ctx, {
25
+ data: snap.data,
26
+ params: snap.params,
27
+ tick: snap.tick
28
+ });
29
+ engineCtx.recordDrawTime(snap.tick, performance.now() - t0);
30
+ }
31
+ }
32
+ const unsubscribe = engineCtx.subscribe(
33
+ (snap) => {
34
+ const canvas2 = canvasRef.current;
35
+ if (!canvas2) return;
36
+ const ctx = canvas2.getContext("2d");
37
+ if (!ctx) return;
38
+ const t0 = performance.now();
39
+ drawRef.current(ctx, {
40
+ data: snap.data,
41
+ params: snap.params,
42
+ tick: snap.tick
43
+ });
44
+ engineCtx.recordDrawTime(snap.tick, performance.now() - t0);
45
+ }
46
+ );
47
+ return unsubscribe;
48
+ }, [engineCtx]);
49
+ return canvasRef;
50
+ }
51
+ export {
52
+ useSimulationCanvas
53
+ };
package/dist/sim.cjs ADDED
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/sim.ts
21
+ var sim_exports = {};
22
+ __export(sim_exports, {
23
+ defineSim: () => defineSim
24
+ });
25
+ module.exports = __toCommonJS(sim_exports);
26
+ function defineSim(sim) {
27
+ return sim;
28
+ }
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ defineSim
32
+ });
package/dist/sim.d.cts ADDED
@@ -0,0 +1,40 @@
1
+ /** Arguments passed to the `step` function on each tick. */
2
+ type StepArgs<Data, Params> = {
3
+ data: Data;
4
+ params: Params;
5
+ tick: number;
6
+ };
7
+ /** A simulation module: the pure business logic that automatick drives. */
8
+ type SimModule<Data, Params> = {
9
+ /** Create initial simulation state from params. Called on engine creation and on resetWith(). */
10
+ init: (params: Params) => Data;
11
+ /** Advance the simulation by one tick. Must be pure and synchronous. */
12
+ step: (args: StepArgs<Data, Params>) => Data;
13
+ /** Optional termination predicate. Checked after each step. If it returns true, the simulation stops. */
14
+ shouldStop?: (data: Data, params: Params) => boolean;
15
+ /** Default parameter values. Used at engine creation if no params override is provided. */
16
+ defaultParams: Params;
17
+ };
18
+ /**
19
+ * Define a simulation module with full type inference.
20
+ *
21
+ * This is an identity function — it returns its argument unchanged. Its purpose is to
22
+ * enable TypeScript to infer `Data` and `Params` from the `init` and `step` implementations,
23
+ * so the developer never needs to annotate types inside those functions.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * export default defineSim<{ count: number }, { increment: number }>({
28
+ * defaultParams: { increment: 1 },
29
+ * init: (params) => ({ count: 0 }),
30
+ * step: ({ data, params }) => ({ count: data.count + params.increment }),
31
+ * });
32
+ * ```
33
+ */
34
+ declare function defineSim<Data, Params>(sim: SimModule<Data, Params>): SimModule<Data, Params>;
35
+ /** Extract the Data type from a SimModule. */
36
+ type SimData<M> = M extends SimModule<infer D, infer _P> ? D : never;
37
+ /** Extract the Params type from a SimModule. */
38
+ type SimParams<M> = M extends SimModule<infer _D, infer P> ? P : never;
39
+
40
+ export { type SimData, type SimModule, type SimParams, type StepArgs, defineSim };
package/dist/sim.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ /** Arguments passed to the `step` function on each tick. */
2
+ type StepArgs<Data, Params> = {
3
+ data: Data;
4
+ params: Params;
5
+ tick: number;
6
+ };
7
+ /** A simulation module: the pure business logic that automatick drives. */
8
+ type SimModule<Data, Params> = {
9
+ /** Create initial simulation state from params. Called on engine creation and on resetWith(). */
10
+ init: (params: Params) => Data;
11
+ /** Advance the simulation by one tick. Must be pure and synchronous. */
12
+ step: (args: StepArgs<Data, Params>) => Data;
13
+ /** Optional termination predicate. Checked after each step. If it returns true, the simulation stops. */
14
+ shouldStop?: (data: Data, params: Params) => boolean;
15
+ /** Default parameter values. Used at engine creation if no params override is provided. */
16
+ defaultParams: Params;
17
+ };
18
+ /**
19
+ * Define a simulation module with full type inference.
20
+ *
21
+ * This is an identity function — it returns its argument unchanged. Its purpose is to
22
+ * enable TypeScript to infer `Data` and `Params` from the `init` and `step` implementations,
23
+ * so the developer never needs to annotate types inside those functions.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * export default defineSim<{ count: number }, { increment: number }>({
28
+ * defaultParams: { increment: 1 },
29
+ * init: (params) => ({ count: 0 }),
30
+ * step: ({ data, params }) => ({ count: data.count + params.increment }),
31
+ * });
32
+ * ```
33
+ */
34
+ declare function defineSim<Data, Params>(sim: SimModule<Data, Params>): SimModule<Data, Params>;
35
+ /** Extract the Data type from a SimModule. */
36
+ type SimData<M> = M extends SimModule<infer D, infer _P> ? D : never;
37
+ /** Extract the Params type from a SimModule. */
38
+ type SimParams<M> = M extends SimModule<infer _D, infer P> ? P : never;
39
+
40
+ export { type SimData, type SimModule, type SimParams, type StepArgs, defineSim };
package/dist/sim.js ADDED
@@ -0,0 +1,7 @@
1
+ // src/sim.ts
2
+ function defineSim(sim) {
3
+ return sim;
4
+ }
5
+ export {
6
+ defineSim
7
+ };
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/worker/createSimWorker.ts
21
+ var createSimWorker_exports = {};
22
+ __export(createSimWorker_exports, {
23
+ createSimWorker: () => createSimWorker
24
+ });
25
+ module.exports = __toCommonJS(createSimWorker_exports);
26
+ var WORKER_SCRIPT = `
27
+ let engine = null;
28
+ let loopTimer = null;
29
+ let snapshotIntervalMs = 16;
30
+ let lastSnapshotMs = 0;
31
+ let ticksPerFrame = 1;
32
+ let delayMs = 0;
33
+
34
+ function emitSnapshot() {
35
+ if (!engine) return;
36
+ postMessage({ kind: 'snapshot', snapshot: engine.getSnapshot() });
37
+ lastSnapshotMs = performance.now();
38
+ }
39
+
40
+ function tickLoop() {
41
+ if (!engine || engine.getStatus() !== 'playing') return;
42
+
43
+ for (let i = 0; i < ticksPerFrame; i++) {
44
+ engine.advance(1);
45
+ const s = engine.getStatus();
46
+ if (s === 'stopped') { emitSnapshot(); return; }
47
+ if (s !== 'paused') break;
48
+ }
49
+
50
+ // advance() transitions to paused; resume playing for the next batch
51
+ if (engine.getStatus() === 'paused') engine.play();
52
+
53
+ if (performance.now() - lastSnapshotMs >= snapshotIntervalMs) emitSnapshot();
54
+ loopTimer = setTimeout(tickLoop, delayMs);
55
+ }
56
+
57
+ function stopLoop() {
58
+ if (loopTimer !== null) { clearTimeout(loopTimer); loopTimer = null; }
59
+ }
60
+
61
+ self.onmessage = async (event) => {
62
+ const msg = event.data;
63
+ try {
64
+ switch (msg.kind) {
65
+ case 'init': {
66
+ delayMs = msg.config.delayMs || 0;
67
+ ticksPerFrame = msg.config.ticksPerFrame || 1;
68
+ snapshotIntervalMs = msg.config.snapshotIntervalMs || 16;
69
+
70
+ const [simMod, engineMod] = await Promise.all([
71
+ import(msg.moduleUrl),
72
+ import(msg.engineUrl),
73
+ ]);
74
+ const sim = simMod.default;
75
+ engine = engineMod.createEngine({
76
+ init: sim.init,
77
+ step: sim.step,
78
+ shouldStop: sim.shouldStop,
79
+ initialParams: msg.params,
80
+ maxTime: msg.config.maxTime,
81
+ });
82
+ postMessage({ kind: 'ready' });
83
+ emitSnapshot();
84
+ break;
85
+ }
86
+ case 'play':
87
+ if (!engine) return;
88
+ engine.play(); emitSnapshot(); stopLoop(); loopTimer = setTimeout(tickLoop, 0);
89
+ break;
90
+ case 'pause':
91
+ if (!engine) return;
92
+ stopLoop(); engine.pause(); emitSnapshot();
93
+ break;
94
+ case 'stop':
95
+ if (!engine) return;
96
+ stopLoop(); engine.stop(); emitSnapshot();
97
+ break;
98
+ case 'seek':
99
+ if (!engine) return;
100
+ stopLoop(); engine.seek(msg.tick); emitSnapshot();
101
+ break;
102
+ case 'advance':
103
+ if (!engine) return;
104
+ engine.advance(msg.count); emitSnapshot();
105
+ break;
106
+ case 'setParams':
107
+ if (!engine) return;
108
+ engine.setParams(msg.patch); emitSnapshot();
109
+ break;
110
+ case 'resetWith':
111
+ if (!engine) return;
112
+ stopLoop(); engine.resetWith(msg.patch); emitSnapshot();
113
+ break;
114
+ case 'destroy':
115
+ stopLoop();
116
+ if (engine) { engine.destroy(); engine = null; }
117
+ self.close();
118
+ break;
119
+ }
120
+ } catch (err) {
121
+ postMessage({ kind: 'error', error: { message: err.message, stack: err.stack } });
122
+ }
123
+ };
124
+ `;
125
+ function createSimWorker(options) {
126
+ const blob = new Blob([WORKER_SCRIPT], { type: "text/javascript" });
127
+ const blobUrl = URL.createObjectURL(blob);
128
+ const worker = new Worker(blobUrl, { type: "module" });
129
+ worker.addEventListener("message", function cleanup(event) {
130
+ if (event.data?.kind === "ready" || event.data?.kind === "error") {
131
+ URL.revokeObjectURL(blobUrl);
132
+ worker.removeEventListener("message", cleanup);
133
+ }
134
+ });
135
+ worker.postMessage({
136
+ kind: "init",
137
+ moduleUrl: options.moduleUrl,
138
+ engineUrl: options.engineUrl,
139
+ params: options.initialParams,
140
+ config: options.config
141
+ });
142
+ return worker;
143
+ }
144
+ // Annotate the CommonJS export names for ESM import in node:
145
+ 0 && (module.exports = {
146
+ createSimWorker
147
+ });
@@ -0,0 +1,19 @@
1
+ import { WorkerConfig } from './protocol.cjs';
2
+ import '../engine.cjs';
3
+ import '../sim.cjs';
4
+
5
+ /**
6
+ * Creates a Web Worker that loads a sim module and runs the engine.
7
+ *
8
+ * Uses a blob URL with dynamic import() — works in Vite dev (modules served
9
+ * over HTTP) and in production builds (bundled chunks).
10
+ */
11
+
12
+ declare function createSimWorker<Params>(options: {
13
+ moduleUrl: string;
14
+ engineUrl: string;
15
+ initialParams: Params;
16
+ config: WorkerConfig;
17
+ }): Worker;
18
+
19
+ export { createSimWorker };
@@ -0,0 +1,19 @@
1
+ import { WorkerConfig } from './protocol.js';
2
+ import '../engine.js';
3
+ import '../sim.js';
4
+
5
+ /**
6
+ * Creates a Web Worker that loads a sim module and runs the engine.
7
+ *
8
+ * Uses a blob URL with dynamic import() — works in Vite dev (modules served
9
+ * over HTTP) and in production builds (bundled chunks).
10
+ */
11
+
12
+ declare function createSimWorker<Params>(options: {
13
+ moduleUrl: string;
14
+ engineUrl: string;
15
+ initialParams: Params;
16
+ config: WorkerConfig;
17
+ }): Worker;
18
+
19
+ export { createSimWorker };
@@ -0,0 +1,122 @@
1
+ // src/worker/createSimWorker.ts
2
+ var WORKER_SCRIPT = `
3
+ let engine = null;
4
+ let loopTimer = null;
5
+ let snapshotIntervalMs = 16;
6
+ let lastSnapshotMs = 0;
7
+ let ticksPerFrame = 1;
8
+ let delayMs = 0;
9
+
10
+ function emitSnapshot() {
11
+ if (!engine) return;
12
+ postMessage({ kind: 'snapshot', snapshot: engine.getSnapshot() });
13
+ lastSnapshotMs = performance.now();
14
+ }
15
+
16
+ function tickLoop() {
17
+ if (!engine || engine.getStatus() !== 'playing') return;
18
+
19
+ for (let i = 0; i < ticksPerFrame; i++) {
20
+ engine.advance(1);
21
+ const s = engine.getStatus();
22
+ if (s === 'stopped') { emitSnapshot(); return; }
23
+ if (s !== 'paused') break;
24
+ }
25
+
26
+ // advance() transitions to paused; resume playing for the next batch
27
+ if (engine.getStatus() === 'paused') engine.play();
28
+
29
+ if (performance.now() - lastSnapshotMs >= snapshotIntervalMs) emitSnapshot();
30
+ loopTimer = setTimeout(tickLoop, delayMs);
31
+ }
32
+
33
+ function stopLoop() {
34
+ if (loopTimer !== null) { clearTimeout(loopTimer); loopTimer = null; }
35
+ }
36
+
37
+ self.onmessage = async (event) => {
38
+ const msg = event.data;
39
+ try {
40
+ switch (msg.kind) {
41
+ case 'init': {
42
+ delayMs = msg.config.delayMs || 0;
43
+ ticksPerFrame = msg.config.ticksPerFrame || 1;
44
+ snapshotIntervalMs = msg.config.snapshotIntervalMs || 16;
45
+
46
+ const [simMod, engineMod] = await Promise.all([
47
+ import(msg.moduleUrl),
48
+ import(msg.engineUrl),
49
+ ]);
50
+ const sim = simMod.default;
51
+ engine = engineMod.createEngine({
52
+ init: sim.init,
53
+ step: sim.step,
54
+ shouldStop: sim.shouldStop,
55
+ initialParams: msg.params,
56
+ maxTime: msg.config.maxTime,
57
+ });
58
+ postMessage({ kind: 'ready' });
59
+ emitSnapshot();
60
+ break;
61
+ }
62
+ case 'play':
63
+ if (!engine) return;
64
+ engine.play(); emitSnapshot(); stopLoop(); loopTimer = setTimeout(tickLoop, 0);
65
+ break;
66
+ case 'pause':
67
+ if (!engine) return;
68
+ stopLoop(); engine.pause(); emitSnapshot();
69
+ break;
70
+ case 'stop':
71
+ if (!engine) return;
72
+ stopLoop(); engine.stop(); emitSnapshot();
73
+ break;
74
+ case 'seek':
75
+ if (!engine) return;
76
+ stopLoop(); engine.seek(msg.tick); emitSnapshot();
77
+ break;
78
+ case 'advance':
79
+ if (!engine) return;
80
+ engine.advance(msg.count); emitSnapshot();
81
+ break;
82
+ case 'setParams':
83
+ if (!engine) return;
84
+ engine.setParams(msg.patch); emitSnapshot();
85
+ break;
86
+ case 'resetWith':
87
+ if (!engine) return;
88
+ stopLoop(); engine.resetWith(msg.patch); emitSnapshot();
89
+ break;
90
+ case 'destroy':
91
+ stopLoop();
92
+ if (engine) { engine.destroy(); engine = null; }
93
+ self.close();
94
+ break;
95
+ }
96
+ } catch (err) {
97
+ postMessage({ kind: 'error', error: { message: err.message, stack: err.stack } });
98
+ }
99
+ };
100
+ `;
101
+ function createSimWorker(options) {
102
+ const blob = new Blob([WORKER_SCRIPT], { type: "text/javascript" });
103
+ const blobUrl = URL.createObjectURL(blob);
104
+ const worker = new Worker(blobUrl, { type: "module" });
105
+ worker.addEventListener("message", function cleanup(event) {
106
+ if (event.data?.kind === "ready" || event.data?.kind === "error") {
107
+ URL.revokeObjectURL(blobUrl);
108
+ worker.removeEventListener("message", cleanup);
109
+ }
110
+ });
111
+ worker.postMessage({
112
+ kind: "init",
113
+ moduleUrl: options.moduleUrl,
114
+ engineUrl: options.engineUrl,
115
+ params: options.initialParams,
116
+ config: options.config
117
+ });
118
+ return worker;
119
+ }
120
+ export {
121
+ createSimWorker
122
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+
16
+ // src/worker/protocol.ts
17
+ var protocol_exports = {};
18
+ module.exports = __toCommonJS(protocol_exports);