@mindees/core 0.1.0
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/LICENSE +31 -0
- package/README.md +119 -0
- package/dist/component/component.d.ts +112 -0
- package/dist/component/component.d.ts.map +1 -0
- package/dist/component/component.js +107 -0
- package/dist/component/component.js.map +1 -0
- package/dist/errors.d.ts +23 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/not-implemented.d.ts +16 -0
- package/dist/not-implemented.d.ts.map +1 -0
- package/dist/not-implemented.js +18 -0
- package/dist/not-implemented.js.map +1 -0
- package/dist/reactive/reactive.d.ts +146 -0
- package/dist/reactive/reactive.d.ts.map +1 -0
- package/dist/reactive/reactive.js +393 -0
- package/dist/reactive/reactive.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +86 -0
- package/dist/scheduler/scheduler.d.ts.map +1 -0
- package/dist/scheduler/scheduler.js +118 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/threading/thread-pool.d.ts +88 -0
- package/dist/threading/thread-pool.d.ts.map +1 -0
- package/dist/threading/thread-pool.js +135 -0
- package/dist/threading/thread-pool.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//#region src/scheduler/scheduler.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* MindeesNative scheduler — a small, deterministic priority scheduler.
|
|
4
|
+
*
|
|
5
|
+
* Two lanes:
|
|
6
|
+
* - **`sync`** — high-priority work (interaction handlers, first frame). Drained
|
|
7
|
+
* synchronously at the next flush point and always before the normal lane.
|
|
8
|
+
* - **`normal`** — default work, drained on a microtask so multiple schedules in
|
|
9
|
+
* the same tick coalesce into one flush.
|
|
10
|
+
*
|
|
11
|
+
* Tasks are **cancellable** (via the returned handle) and **dedupable** (two
|
|
12
|
+
* tasks scheduled with the same `key` collapse to one — the latest callback
|
|
13
|
+
* wins, preserving the earlier queue position). The scheduler never throws from
|
|
14
|
+
* a task into the caller: task errors are collected and reported via an optional
|
|
15
|
+
* `onError` hook, so one bad task can't stop the rest of the flush.
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
/** Scheduling lanes, highest priority first. */
|
|
20
|
+
type Priority = 'sync' | 'normal';
|
|
21
|
+
/** A unit of scheduled work. */
|
|
22
|
+
type Task = () => void;
|
|
23
|
+
/** Options for {@link Scheduler.schedule}. */
|
|
24
|
+
interface ScheduleOptions {
|
|
25
|
+
/** Lane to run in. Defaults to `'normal'`. */
|
|
26
|
+
priority?: Priority;
|
|
27
|
+
/**
|
|
28
|
+
* Dedup key. Scheduling again with the same key replaces the pending task's
|
|
29
|
+
* callback (latest wins) instead of enqueuing a second one.
|
|
30
|
+
*/
|
|
31
|
+
key?: string;
|
|
32
|
+
}
|
|
33
|
+
/** A handle to a scheduled task. */
|
|
34
|
+
interface ScheduledTask {
|
|
35
|
+
/** Remove the task if it hasn't run yet. Idempotent. */
|
|
36
|
+
cancel(): void;
|
|
37
|
+
/** Whether the task is still pending (not yet run or cancelled). */
|
|
38
|
+
readonly pending: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Options for {@link Scheduler}. */
|
|
41
|
+
interface SchedulerOptions {
|
|
42
|
+
/**
|
|
43
|
+
* Called with any error thrown by a task. If omitted, errors are rethrown
|
|
44
|
+
* asynchronously (so they surface to the host without aborting the flush).
|
|
45
|
+
*/
|
|
46
|
+
onError?: (error: unknown) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Schedules a microtask. Injectable for testing; defaults to `queueMicrotask`.
|
|
49
|
+
*/
|
|
50
|
+
scheduleMicrotask?: (cb: () => void) => void;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A deterministic two-lane priority scheduler. Create one with {@link createScheduler}.
|
|
54
|
+
*/
|
|
55
|
+
declare class Scheduler {
|
|
56
|
+
private readonly sync;
|
|
57
|
+
private readonly normal;
|
|
58
|
+
private readonly keyed;
|
|
59
|
+
private microtaskQueued;
|
|
60
|
+
private flushing;
|
|
61
|
+
private readonly onError;
|
|
62
|
+
private readonly scheduleMicrotask;
|
|
63
|
+
constructor(options?: SchedulerOptions);
|
|
64
|
+
/** Schedule `task`. Returns a handle to cancel it or check its status. */
|
|
65
|
+
schedule(task: Task, options?: ScheduleOptions): ScheduledTask;
|
|
66
|
+
/** Run all pending tasks right now (sync lane first), draining both lanes. */
|
|
67
|
+
flushSync(): void;
|
|
68
|
+
/** Number of pending tasks across both lanes (cancelled tasks excluded). */
|
|
69
|
+
get size(): number;
|
|
70
|
+
private requestFlush;
|
|
71
|
+
private run;
|
|
72
|
+
/**
|
|
73
|
+
* Remove an entry's dedup-key mapping, but only if the map still points at THIS
|
|
74
|
+
* entry. Keys are reused over time (a 'render' key is scheduled, runs, then
|
|
75
|
+
* scheduled again), so a stale handle or an already-dequeued entry must never
|
|
76
|
+
* evict a newer live entry's mapping — doing so would break dedup and let two
|
|
77
|
+
* same-key tasks both run.
|
|
78
|
+
*/
|
|
79
|
+
private clearKey;
|
|
80
|
+
private makeHandle;
|
|
81
|
+
}
|
|
82
|
+
/** Create a new {@link Scheduler}. */
|
|
83
|
+
declare function createScheduler(options?: SchedulerOptions): Scheduler;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { Priority, ScheduleOptions, ScheduledTask, Scheduler, SchedulerOptions, Task, createScheduler };
|
|
86
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","names":[],"sources":["../../src/scheduler/scheduler.ts"],"mappings":";;AAmBA;;;;AAAoB;AAGpB;;;;AAAgB;AAGhB;;;;;;;KANY,QAAA;AAaP;AAAA,KAVO,IAAA;;UAGK,eAAA;EAaf;EAXA,QAAA,GAAW,QAAQ;EAsBJ;;;;EAjBf,GAAA;AAAA;;UAIe,aAAA;EAsBoB;EApBnC,MAAA;EAiCW;EAAA,SA/BF,OAAO;AAAA;;UASD,gBAAA;EAqCgB;;;;EAhC/B,OAAA,IAAW,KAAA;EAmBM;;;EAfjB,iBAAA,IAAqB,EAAA;AAAA;;;;cAaV,SAAA;EAAA,iBACM,IAAA;EAAA,iBACA,MAAA;EAAA,iBACA,KAAA;EAAA,QACT,eAAA;EAAA,QACA,QAAA;EAAA,iBACS,OAAA;EAAA,iBACA,iBAAA;cAEL,OAAA,GAAU,gBAAA;EAuDd;EAjDR,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,OAAA,GAAU,eAAA,GAAkB,aAAA;EAwFzC;EAnER,SAAA;EAyEkB;EAAA,IApDd,IAAA;EAAA,QAOI,YAAA;EAAA,QASA,GAAA;;;;;;;AAkD4D;UApB5D,QAAA;EAAA,QAMA,UAAA;AAAA;;iBAcM,eAAA,CAAgB,OAAA,GAAU,gBAAA,GAAmB,SAAS"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//#region src/scheduler/scheduler.ts
|
|
2
|
+
const defaultScheduleMicrotask = typeof queueMicrotask === "function" ? queueMicrotask : (cb) => {
|
|
3
|
+
Promise.resolve().then(cb);
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* A deterministic two-lane priority scheduler. Create one with {@link createScheduler}.
|
|
7
|
+
*/
|
|
8
|
+
var Scheduler = class {
|
|
9
|
+
sync = [];
|
|
10
|
+
normal = [];
|
|
11
|
+
keyed = /* @__PURE__ */ new Map();
|
|
12
|
+
microtaskQueued = false;
|
|
13
|
+
flushing = false;
|
|
14
|
+
onError;
|
|
15
|
+
scheduleMicrotask;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.onError = options?.onError;
|
|
18
|
+
this.scheduleMicrotask = options?.scheduleMicrotask ?? defaultScheduleMicrotask;
|
|
19
|
+
}
|
|
20
|
+
/** Schedule `task`. Returns a handle to cancel it or check its status. */
|
|
21
|
+
schedule(task, options) {
|
|
22
|
+
const priority = options?.priority ?? "normal";
|
|
23
|
+
const key = options?.key ?? null;
|
|
24
|
+
if (key !== null) {
|
|
25
|
+
const existing = this.keyed.get(key);
|
|
26
|
+
if (existing && existing.fn !== null) {
|
|
27
|
+
existing.fn = task;
|
|
28
|
+
return this.makeHandle(existing);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const entry = {
|
|
32
|
+
key,
|
|
33
|
+
fn: task
|
|
34
|
+
};
|
|
35
|
+
if (key !== null) this.keyed.set(key, entry);
|
|
36
|
+
(priority === "sync" ? this.sync : this.normal).push(entry);
|
|
37
|
+
this.requestFlush();
|
|
38
|
+
return this.makeHandle(entry);
|
|
39
|
+
}
|
|
40
|
+
/** Run all pending tasks right now (sync lane first), draining both lanes. */
|
|
41
|
+
flushSync() {
|
|
42
|
+
if (this.flushing) return;
|
|
43
|
+
this.flushing = true;
|
|
44
|
+
try {
|
|
45
|
+
while (this.sync.length > 0 || this.normal.length > 0) {
|
|
46
|
+
const entry = this.sync.length > 0 ? this.sync.shift() : this.normal.shift();
|
|
47
|
+
if (!entry) continue;
|
|
48
|
+
this.clearKey(entry);
|
|
49
|
+
const fn = entry.fn;
|
|
50
|
+
entry.fn = null;
|
|
51
|
+
if (fn) this.run(fn);
|
|
52
|
+
}
|
|
53
|
+
} finally {
|
|
54
|
+
this.flushing = false;
|
|
55
|
+
this.microtaskQueued = false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Number of pending tasks across both lanes (cancelled tasks excluded). */
|
|
59
|
+
get size() {
|
|
60
|
+
let n = 0;
|
|
61
|
+
for (const e of this.sync) if (e.fn !== null) n++;
|
|
62
|
+
for (const e of this.normal) if (e.fn !== null) n++;
|
|
63
|
+
return n;
|
|
64
|
+
}
|
|
65
|
+
requestFlush() {
|
|
66
|
+
if (this.microtaskQueued || this.flushing) return;
|
|
67
|
+
this.microtaskQueued = true;
|
|
68
|
+
this.scheduleMicrotask(() => {
|
|
69
|
+
this.microtaskQueued = false;
|
|
70
|
+
this.flushSync();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
run(fn) {
|
|
74
|
+
try {
|
|
75
|
+
fn();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (this.onError) try {
|
|
78
|
+
this.onError(error);
|
|
79
|
+
} catch (hookError) {
|
|
80
|
+
this.scheduleMicrotask(() => {
|
|
81
|
+
throw hookError;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
else this.scheduleMicrotask(() => {
|
|
85
|
+
throw error;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Remove an entry's dedup-key mapping, but only if the map still points at THIS
|
|
91
|
+
* entry. Keys are reused over time (a 'render' key is scheduled, runs, then
|
|
92
|
+
* scheduled again), so a stale handle or an already-dequeued entry must never
|
|
93
|
+
* evict a newer live entry's mapping — doing so would break dedup and let two
|
|
94
|
+
* same-key tasks both run.
|
|
95
|
+
*/
|
|
96
|
+
clearKey(entry) {
|
|
97
|
+
if (entry.key !== null && this.keyed.get(entry.key) === entry) this.keyed.delete(entry.key);
|
|
98
|
+
}
|
|
99
|
+
makeHandle(entry) {
|
|
100
|
+
return {
|
|
101
|
+
cancel: () => {
|
|
102
|
+
entry.fn = null;
|
|
103
|
+
this.clearKey(entry);
|
|
104
|
+
},
|
|
105
|
+
get pending() {
|
|
106
|
+
return entry.fn !== null;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
/** Create a new {@link Scheduler}. */
|
|
112
|
+
function createScheduler(options) {
|
|
113
|
+
return new Scheduler(options);
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { Scheduler, createScheduler };
|
|
117
|
+
|
|
118
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","names":[],"sources":["../../src/scheduler/scheduler.ts"],"sourcesContent":["/**\n * MindeesNative scheduler — a small, deterministic priority scheduler.\n *\n * Two lanes:\n * - **`sync`** — high-priority work (interaction handlers, first frame). Drained\n * synchronously at the next flush point and always before the normal lane.\n * - **`normal`** — default work, drained on a microtask so multiple schedules in\n * the same tick coalesce into one flush.\n *\n * Tasks are **cancellable** (via the returned handle) and **dedupable** (two\n * tasks scheduled with the same `key` collapse to one — the latest callback\n * wins, preserving the earlier queue position). The scheduler never throws from\n * a task into the caller: task errors are collected and reported via an optional\n * `onError` hook, so one bad task can't stop the rest of the flush.\n *\n * @module\n */\n\n/** Scheduling lanes, highest priority first. */\nexport type Priority = 'sync' | 'normal'\n\n/** A unit of scheduled work. */\nexport type Task = () => void\n\n/** Options for {@link Scheduler.schedule}. */\nexport interface ScheduleOptions {\n /** Lane to run in. Defaults to `'normal'`. */\n priority?: Priority\n /**\n * Dedup key. Scheduling again with the same key replaces the pending task's\n * callback (latest wins) instead of enqueuing a second one.\n */\n key?: string\n}\n\n/** A handle to a scheduled task. */\nexport interface ScheduledTask {\n /** Remove the task if it hasn't run yet. Idempotent. */\n cancel(): void\n /** Whether the task is still pending (not yet run or cancelled). */\n readonly pending: boolean\n}\n\ninterface Entry {\n key: string | null\n fn: Task | null // null once cancelled\n}\n\n/** Options for {@link Scheduler}. */\nexport interface SchedulerOptions {\n /**\n * Called with any error thrown by a task. If omitted, errors are rethrown\n * asynchronously (so they surface to the host without aborting the flush).\n */\n onError?: (error: unknown) => void\n /**\n * Schedules a microtask. Injectable for testing; defaults to `queueMicrotask`.\n */\n scheduleMicrotask?: (cb: () => void) => void\n}\n\nconst defaultScheduleMicrotask: (cb: () => void) => void =\n typeof queueMicrotask === 'function'\n ? queueMicrotask\n : (cb) => {\n void Promise.resolve().then(cb)\n }\n\n/**\n * A deterministic two-lane priority scheduler. Create one with {@link createScheduler}.\n */\nexport class Scheduler {\n private readonly sync: Entry[] = []\n private readonly normal: Entry[] = []\n private readonly keyed = new Map<string, Entry>()\n private microtaskQueued = false\n private flushing = false\n private readonly onError: ((error: unknown) => void) | undefined\n private readonly scheduleMicrotask: (cb: () => void) => void\n\n constructor(options?: SchedulerOptions) {\n this.onError = options?.onError\n this.scheduleMicrotask = options?.scheduleMicrotask ?? defaultScheduleMicrotask\n }\n\n /** Schedule `task`. Returns a handle to cancel it or check its status. */\n schedule(task: Task, options?: ScheduleOptions): ScheduledTask {\n const priority = options?.priority ?? 'normal'\n const key = options?.key ?? null\n\n if (key !== null) {\n const existing = this.keyed.get(key)\n if (existing && existing.fn !== null) {\n // Dedup: replace the callback, keep the existing queue position.\n existing.fn = task\n return this.makeHandle(existing)\n }\n }\n\n const entry: Entry = { key, fn: task }\n if (key !== null) this.keyed.set(key, entry)\n ;(priority === 'sync' ? this.sync : this.normal).push(entry)\n this.requestFlush()\n return this.makeHandle(entry)\n }\n\n /** Run all pending tasks right now (sync lane first), draining both lanes. */\n flushSync(): void {\n if (this.flushing) return\n this.flushing = true\n try {\n // Drain in priority order. Re-check each loop so tasks scheduled by tasks\n // (e.g. a sync task that queues normal work) are handled in this flush.\n while (this.sync.length > 0 || this.normal.length > 0) {\n const entry = this.sync.length > 0 ? this.sync.shift() : this.normal.shift()\n if (!entry) continue\n this.clearKey(entry)\n const fn = entry.fn\n entry.fn = null\n if (fn) this.run(fn)\n }\n } finally {\n this.flushing = false\n this.microtaskQueued = false\n }\n }\n\n /** Number of pending tasks across both lanes (cancelled tasks excluded). */\n get size(): number {\n let n = 0\n for (const e of this.sync) if (e.fn !== null) n++\n for (const e of this.normal) if (e.fn !== null) n++\n return n\n }\n\n private requestFlush(): void {\n if (this.microtaskQueued || this.flushing) return\n this.microtaskQueued = true\n this.scheduleMicrotask(() => {\n this.microtaskQueued = false\n this.flushSync()\n })\n }\n\n private run(fn: Task): void {\n try {\n fn()\n } catch (error) {\n if (this.onError) {\n try {\n this.onError(error)\n } catch (hookError) {\n // A throwing onError hook must not abort the flush or strand the tasks\n // queued after it; surface it asynchronously like an unhandled task error.\n this.scheduleMicrotask(() => {\n throw hookError\n })\n }\n } else {\n // Surface without aborting the flush.\n this.scheduleMicrotask(() => {\n throw error\n })\n }\n }\n }\n\n /**\n * Remove an entry's dedup-key mapping, but only if the map still points at THIS\n * entry. Keys are reused over time (a 'render' key is scheduled, runs, then\n * scheduled again), so a stale handle or an already-dequeued entry must never\n * evict a newer live entry's mapping — doing so would break dedup and let two\n * same-key tasks both run.\n */\n private clearKey(entry: Entry): void {\n if (entry.key !== null && this.keyed.get(entry.key) === entry) {\n this.keyed.delete(entry.key)\n }\n }\n\n private makeHandle(entry: Entry): ScheduledTask {\n return {\n cancel: () => {\n entry.fn = null\n this.clearKey(entry)\n },\n get pending() {\n return entry.fn !== null\n },\n }\n }\n}\n\n/** Create a new {@link Scheduler}. */\nexport function createScheduler(options?: SchedulerOptions): Scheduler {\n return new Scheduler(options)\n}\n"],"mappings":";AA6DA,MAAM,2BACJ,OAAO,mBAAmB,aACtB,kBACC,OAAO;CACN,QAAa,QAAQ,EAAE,KAAK,EAAE;AAChC;;;;AAKN,IAAa,YAAb,MAAuB;CACrB,OAAiC,CAAC;CAClC,SAAmC,CAAC;CACpC,wBAAyB,IAAI,IAAmB;CAChD,kBAA0B;CAC1B,WAAmB;CACnB;CACA;CAEA,YAAY,SAA4B;EACtC,KAAK,UAAU,SAAS;EACxB,KAAK,oBAAoB,SAAS,qBAAqB;CACzD;;CAGA,SAAS,MAAY,SAA0C;EAC7D,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,MAAM,SAAS,OAAO;EAE5B,IAAI,QAAQ,MAAM;GAChB,MAAM,WAAW,KAAK,MAAM,IAAI,GAAG;GACnC,IAAI,YAAY,SAAS,OAAO,MAAM;IAEpC,SAAS,KAAK;IACd,OAAO,KAAK,WAAW,QAAQ;GACjC;EACF;EAEA,MAAM,QAAe;GAAE;GAAK,IAAI;EAAK;EACrC,IAAI,QAAQ,MAAM,KAAK,MAAM,IAAI,KAAK,KAAK;EAC1C,CAAC,aAAa,SAAS,KAAK,OAAO,KAAK,QAAQ,KAAK,KAAK;EAC3D,KAAK,aAAa;EAClB,OAAO,KAAK,WAAW,KAAK;CAC9B;;CAGA,YAAkB;EAChB,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW;EAChB,IAAI;GAGF,OAAO,KAAK,KAAK,SAAS,KAAK,KAAK,OAAO,SAAS,GAAG;IACrD,MAAM,QAAQ,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,OAAO,MAAM;IAC3E,IAAI,CAAC,OAAO;IACZ,KAAK,SAAS,KAAK;IACnB,MAAM,KAAK,MAAM;IACjB,MAAM,KAAK;IACX,IAAI,IAAI,KAAK,IAAI,EAAE;GACrB;EACF,UAAU;GACR,KAAK,WAAW;GAChB,KAAK,kBAAkB;EACzB;CACF;;CAGA,IAAI,OAAe;EACjB,IAAI,IAAI;EACR,KAAK,MAAM,KAAK,KAAK,MAAM,IAAI,EAAE,OAAO,MAAM;EAC9C,KAAK,MAAM,KAAK,KAAK,QAAQ,IAAI,EAAE,OAAO,MAAM;EAChD,OAAO;CACT;CAEA,eAA6B;EAC3B,IAAI,KAAK,mBAAmB,KAAK,UAAU;EAC3C,KAAK,kBAAkB;EACvB,KAAK,wBAAwB;GAC3B,KAAK,kBAAkB;GACvB,KAAK,UAAU;EACjB,CAAC;CACH;CAEA,IAAY,IAAgB;EAC1B,IAAI;GACF,GAAG;EACL,SAAS,OAAO;GACd,IAAI,KAAK,SACP,IAAI;IACF,KAAK,QAAQ,KAAK;GACpB,SAAS,WAAW;IAGlB,KAAK,wBAAwB;KAC3B,MAAM;IACR,CAAC;GACH;QAGA,KAAK,wBAAwB;IAC3B,MAAM;GACR,CAAC;EAEL;CACF;;;;;;;;CASA,SAAiB,OAAoB;EACnC,IAAI,MAAM,QAAQ,QAAQ,KAAK,MAAM,IAAI,MAAM,GAAG,MAAM,OACtD,KAAK,MAAM,OAAO,MAAM,GAAG;CAE/B;CAEA,WAAmB,OAA6B;EAC9C,OAAO;GACL,cAAc;IACZ,MAAM,KAAK;IACX,KAAK,SAAS,KAAK;GACrB;GACA,IAAI,UAAU;IACZ,OAAO,MAAM,OAAO;GACtB;EACF;CACF;AACF;;AAGA,SAAgB,gBAAgB,SAAuC;CACrE,OAAO,IAAI,UAAU,OAAO;AAC9B"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
//#region src/threading/thread-pool.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* MindeesNative threading abstraction.
|
|
4
|
+
*
|
|
5
|
+
* Defines the **contract** for offloading CPU-bound work off the main thread, so
|
|
6
|
+
* the rest of the framework can parallelize without binding to a specific
|
|
7
|
+
* backend. Two backends are anticipated:
|
|
8
|
+
*
|
|
9
|
+
* - **Web Worker backend** (`createWorkerPool`) — works today on web; runs each
|
|
10
|
+
* job in a `Worker`.
|
|
11
|
+
* - **Native multi-thread backend** — 🔬 research track. The interface is
|
|
12
|
+
* defined here so the architecture is real; a native Rust-backed scheduler
|
|
13
|
+
* will implement {@link ThreadPool} in a later phase. Until then,
|
|
14
|
+
* {@link createInlineThreadPool} provides a correct, synchronous fallback so
|
|
15
|
+
* callers are never blocked (Working-Code Doctrine: a real fallback, not a
|
|
16
|
+
* lying stub).
|
|
17
|
+
*
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* A pool that runs a pure job function with a transferable argument and resolves
|
|
22
|
+
* its result. Implementations may run jobs on worker threads, native threads, or
|
|
23
|
+
* (as a fallback) inline on the calling thread.
|
|
24
|
+
*/
|
|
25
|
+
interface ThreadPool {
|
|
26
|
+
/**
|
|
27
|
+
* Run `job(input)` and resolve its result.
|
|
28
|
+
*
|
|
29
|
+
* `job` must be a **pure, self-contained function** (it may be serialized and
|
|
30
|
+
* re-created in another realm, so it cannot close over outer variables in
|
|
31
|
+
* worker/native backends). `input` must be structured-cloneable.
|
|
32
|
+
*/
|
|
33
|
+
run<In, Out>(job: (input: In) => Out, input: In): Promise<Out>;
|
|
34
|
+
/** Release all underlying resources (terminate workers, etc.). Idempotent. */
|
|
35
|
+
dispose(): void;
|
|
36
|
+
/** Number of live workers/threads (0 for the inline fallback). */
|
|
37
|
+
readonly size: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A synchronous, single-realm {@link ThreadPool}: runs each job inline on the
|
|
41
|
+
* calling thread. This is the universal fallback — correct everywhere, with no
|
|
42
|
+
* parallelism. Use it where workers aren't available (or in tests).
|
|
43
|
+
*/
|
|
44
|
+
declare function createInlineThreadPool(): ThreadPool;
|
|
45
|
+
/** Minimal structural subset of the DOM `Worker` we depend on. */
|
|
46
|
+
interface WorkerLike {
|
|
47
|
+
postMessage(message: unknown): void;
|
|
48
|
+
terminate(): void;
|
|
49
|
+
onmessage: ((event: {
|
|
50
|
+
data: unknown;
|
|
51
|
+
}) => void) | null;
|
|
52
|
+
onerror: ((event: {
|
|
53
|
+
message?: string;
|
|
54
|
+
}) => void) | null;
|
|
55
|
+
}
|
|
56
|
+
/** Options for {@link createWorkerPool}. */
|
|
57
|
+
interface WorkerPoolOptions {
|
|
58
|
+
/** Number of workers to spawn. Defaults to 1. */
|
|
59
|
+
size?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Factory that creates a worker which evaluates serialized jobs. Injectable so
|
|
62
|
+
* the pool can be unit-tested without a real `Worker` and so the host app
|
|
63
|
+
* controls how the worker module is bundled/loaded.
|
|
64
|
+
*/
|
|
65
|
+
createWorker: () => WorkerLike;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A {@link ThreadPool} backed by Web Workers. Round-robins jobs across `size`
|
|
69
|
+
* workers. The caller supplies `createWorker`; each worker is expected to accept
|
|
70
|
+
* `{ id, source, input }` messages and reply with `{ id, ok, result }` or
|
|
71
|
+
* `{ id, ok: false, error }` (see the reference worker protocol in this package).
|
|
72
|
+
*
|
|
73
|
+
* @remarks Web-only today. The native multi-threaded backend is a research
|
|
74
|
+
* track — see the module docs.
|
|
75
|
+
*/
|
|
76
|
+
declare function createWorkerPool(options: WorkerPoolOptions): ThreadPool;
|
|
77
|
+
/**
|
|
78
|
+
* 🔬 **Research track.** Placeholder for the native (Rust-backed) multi-threaded
|
|
79
|
+
* pool. Not implemented — throws {@link NotImplementedError}. Use
|
|
80
|
+
* {@link createWorkerPool} (web) or {@link createInlineThreadPool} (fallback)
|
|
81
|
+
* today. Tracked for a later phase.
|
|
82
|
+
*
|
|
83
|
+
* @experimental
|
|
84
|
+
*/
|
|
85
|
+
declare function createNativeThreadPool(): ThreadPool;
|
|
86
|
+
//#endregion
|
|
87
|
+
export { ThreadPool, WorkerLike, WorkerPoolOptions, createInlineThreadPool, createNativeThreadPool, createWorkerPool };
|
|
88
|
+
//# sourceMappingURL=thread-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-pool.d.ts","names":[],"sources":["../../src/threading/thread-pool.ts"],"mappings":";;AA0BA;;;;;;;;;;;;;;;;;;;;;;UAAiB,UAAA;EAYF;AAAA;AAQf;;;;AAAoD;EAZlD,GAAA,UAAa,GAAA,GAAM,KAAA,EAAO,EAAA,KAAO,GAAA,EAAK,KAAA,EAAO,EAAA,GAAK,OAAA,CAAQ,GAAA;EA+BjC;EA7BzB,OAAA;EA6ByB;EAAA,SA3BhB,IAAA;AAAA;;;;;;iBAQK,sBAAA,IAA0B,UAAU;;UAmBnC,UAAA;EACf,WAAA,CAAY,OAAA;EACZ,SAAA;EACA,SAAA,IAAa,KAAA;IAAS,IAAA;EAAA;EACtB,OAAA,IAAW,KAAA;IAAS,OAAA;EAAA;AAAA;AAYU;AAAA,UARf,iBAAA;EA2Be;EAzB9B,IAAA;EAyBsE;;;;;EAnBtE,YAAA,QAAoB,UAAU;AAAA;;;;AAqGoB;;;;;;iBAlFpC,gBAAA,CAAiB,OAAA,EAAS,iBAAA,GAAoB,UAAU;;;;;;;;;iBAkFxD,sBAAA,IAA0B,UAAU"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { NotImplementedError } from "../errors.js";
|
|
2
|
+
//#region src/threading/thread-pool.ts
|
|
3
|
+
/**
|
|
4
|
+
* MindeesNative threading abstraction.
|
|
5
|
+
*
|
|
6
|
+
* Defines the **contract** for offloading CPU-bound work off the main thread, so
|
|
7
|
+
* the rest of the framework can parallelize without binding to a specific
|
|
8
|
+
* backend. Two backends are anticipated:
|
|
9
|
+
*
|
|
10
|
+
* - **Web Worker backend** (`createWorkerPool`) — works today on web; runs each
|
|
11
|
+
* job in a `Worker`.
|
|
12
|
+
* - **Native multi-thread backend** — 🔬 research track. The interface is
|
|
13
|
+
* defined here so the architecture is real; a native Rust-backed scheduler
|
|
14
|
+
* will implement {@link ThreadPool} in a later phase. Until then,
|
|
15
|
+
* {@link createInlineThreadPool} provides a correct, synchronous fallback so
|
|
16
|
+
* callers are never blocked (Working-Code Doctrine: a real fallback, not a
|
|
17
|
+
* lying stub).
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* A synchronous, single-realm {@link ThreadPool}: runs each job inline on the
|
|
23
|
+
* calling thread. This is the universal fallback — correct everywhere, with no
|
|
24
|
+
* parallelism. Use it where workers aren't available (or in tests).
|
|
25
|
+
*/
|
|
26
|
+
function createInlineThreadPool() {
|
|
27
|
+
let disposed = false;
|
|
28
|
+
return {
|
|
29
|
+
run(job, input) {
|
|
30
|
+
if (disposed) return Promise.reject(/* @__PURE__ */ new Error("ThreadPool is disposed"));
|
|
31
|
+
try {
|
|
32
|
+
return Promise.resolve(job(input));
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return Promise.reject(error);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
dispose() {
|
|
38
|
+
disposed = true;
|
|
39
|
+
},
|
|
40
|
+
size: 0
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A {@link ThreadPool} backed by Web Workers. Round-robins jobs across `size`
|
|
45
|
+
* workers. The caller supplies `createWorker`; each worker is expected to accept
|
|
46
|
+
* `{ id, source, input }` messages and reply with `{ id, ok, result }` or
|
|
47
|
+
* `{ id, ok: false, error }` (see the reference worker protocol in this package).
|
|
48
|
+
*
|
|
49
|
+
* @remarks Web-only today. The native multi-threaded backend is a research
|
|
50
|
+
* track — see the module docs.
|
|
51
|
+
*/
|
|
52
|
+
function createWorkerPool(options) {
|
|
53
|
+
const count = Math.max(1, options.size ?? 1);
|
|
54
|
+
const workers = [];
|
|
55
|
+
const pending = /* @__PURE__ */ new Map();
|
|
56
|
+
let nextId = 0;
|
|
57
|
+
let rr = 0;
|
|
58
|
+
let disposed = false;
|
|
59
|
+
/** Reject and forget every in-flight job dispatched to a given worker. */
|
|
60
|
+
function rejectWorkerJobs(workerIndex, message) {
|
|
61
|
+
for (const [id, job] of pending) if (job.workerIndex === workerIndex) {
|
|
62
|
+
pending.delete(id);
|
|
63
|
+
job.reject(new Error(message));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Create a worker at `index`, wire its handlers, and store it in place. */
|
|
67
|
+
function spawn(index) {
|
|
68
|
+
const w = options.createWorker();
|
|
69
|
+
w.onmessage = (event) => {
|
|
70
|
+
const data = event.data;
|
|
71
|
+
const job = pending.get(data.id);
|
|
72
|
+
if (!job) return;
|
|
73
|
+
pending.delete(data.id);
|
|
74
|
+
if (data.ok) job.resolve(data.result);
|
|
75
|
+
else job.reject(new Error(data.error ?? "worker job failed"));
|
|
76
|
+
};
|
|
77
|
+
w.onerror = (event) => {
|
|
78
|
+
if (disposed) return;
|
|
79
|
+
rejectWorkerJobs(index, event.message ?? "worker error");
|
|
80
|
+
try {
|
|
81
|
+
w.terminate();
|
|
82
|
+
} catch {}
|
|
83
|
+
spawn(index);
|
|
84
|
+
};
|
|
85
|
+
workers[index] = w;
|
|
86
|
+
}
|
|
87
|
+
for (let i = 0; i < count; i++) spawn(i);
|
|
88
|
+
return {
|
|
89
|
+
run(job, input) {
|
|
90
|
+
if (disposed) return Promise.reject(/* @__PURE__ */ new Error("ThreadPool is disposed"));
|
|
91
|
+
const index = rr % workers.length;
|
|
92
|
+
rr++;
|
|
93
|
+
const worker = workers[index];
|
|
94
|
+
if (!worker) return Promise.reject(/* @__PURE__ */ new Error("no worker available"));
|
|
95
|
+
const id = nextId++;
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
pending.set(id, {
|
|
98
|
+
resolve,
|
|
99
|
+
reject,
|
|
100
|
+
workerIndex: index
|
|
101
|
+
});
|
|
102
|
+
worker.postMessage({
|
|
103
|
+
id,
|
|
104
|
+
source: job.toString(),
|
|
105
|
+
input
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
dispose() {
|
|
110
|
+
if (disposed) return;
|
|
111
|
+
disposed = true;
|
|
112
|
+
for (const w of workers) w.terminate();
|
|
113
|
+
for (const [, job] of pending) job.reject(/* @__PURE__ */ new Error("ThreadPool disposed"));
|
|
114
|
+
pending.clear();
|
|
115
|
+
},
|
|
116
|
+
get size() {
|
|
117
|
+
return disposed ? 0 : workers.length;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 🔬 **Research track.** Placeholder for the native (Rust-backed) multi-threaded
|
|
123
|
+
* pool. Not implemented — throws {@link NotImplementedError}. Use
|
|
124
|
+
* {@link createWorkerPool} (web) or {@link createInlineThreadPool} (fallback)
|
|
125
|
+
* today. Tracked for a later phase.
|
|
126
|
+
*
|
|
127
|
+
* @experimental
|
|
128
|
+
*/
|
|
129
|
+
function createNativeThreadPool() {
|
|
130
|
+
throw new NotImplementedError("Native multi-threaded ThreadPool");
|
|
131
|
+
}
|
|
132
|
+
//#endregion
|
|
133
|
+
export { createInlineThreadPool, createNativeThreadPool, createWorkerPool };
|
|
134
|
+
|
|
135
|
+
//# sourceMappingURL=thread-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-pool.js","names":[],"sources":["../../src/threading/thread-pool.ts"],"sourcesContent":["/**\n * MindeesNative threading abstraction.\n *\n * Defines the **contract** for offloading CPU-bound work off the main thread, so\n * the rest of the framework can parallelize without binding to a specific\n * backend. Two backends are anticipated:\n *\n * - **Web Worker backend** (`createWorkerPool`) — works today on web; runs each\n * job in a `Worker`.\n * - **Native multi-thread backend** — 🔬 research track. The interface is\n * defined here so the architecture is real; a native Rust-backed scheduler\n * will implement {@link ThreadPool} in a later phase. Until then,\n * {@link createInlineThreadPool} provides a correct, synchronous fallback so\n * callers are never blocked (Working-Code Doctrine: a real fallback, not a\n * lying stub).\n *\n * @module\n */\n\nimport { NotImplementedError } from '../errors'\n\n/**\n * A pool that runs a pure job function with a transferable argument and resolves\n * its result. Implementations may run jobs on worker threads, native threads, or\n * (as a fallback) inline on the calling thread.\n */\nexport interface ThreadPool {\n /**\n * Run `job(input)` and resolve its result.\n *\n * `job` must be a **pure, self-contained function** (it may be serialized and\n * re-created in another realm, so it cannot close over outer variables in\n * worker/native backends). `input` must be structured-cloneable.\n */\n run<In, Out>(job: (input: In) => Out, input: In): Promise<Out>\n /** Release all underlying resources (terminate workers, etc.). Idempotent. */\n dispose(): void\n /** Number of live workers/threads (0 for the inline fallback). */\n readonly size: number\n}\n\n/**\n * A synchronous, single-realm {@link ThreadPool}: runs each job inline on the\n * calling thread. This is the universal fallback — correct everywhere, with no\n * parallelism. Use it where workers aren't available (or in tests).\n */\nexport function createInlineThreadPool(): ThreadPool {\n let disposed = false\n return {\n run<In, Out>(job: (input: In) => Out, input: In): Promise<Out> {\n if (disposed) return Promise.reject(new Error('ThreadPool is disposed'))\n try {\n return Promise.resolve(job(input))\n } catch (error) {\n return Promise.reject(error as Error)\n }\n },\n dispose() {\n disposed = true\n },\n size: 0,\n }\n}\n\n/** Minimal structural subset of the DOM `Worker` we depend on. */\nexport interface WorkerLike {\n postMessage(message: unknown): void\n terminate(): void\n onmessage: ((event: { data: unknown }) => void) | null\n onerror: ((event: { message?: string }) => void) | null\n}\n\n/** Options for {@link createWorkerPool}. */\nexport interface WorkerPoolOptions {\n /** Number of workers to spawn. Defaults to 1. */\n size?: number\n /**\n * Factory that creates a worker which evaluates serialized jobs. Injectable so\n * the pool can be unit-tested without a real `Worker` and so the host app\n * controls how the worker module is bundled/loaded.\n */\n createWorker: () => WorkerLike\n}\n\ninterface PendingJob {\n resolve: (value: unknown) => void\n reject: (error: unknown) => void\n /** Index of the worker this job was dispatched to (for crash correlation). */\n workerIndex: number\n}\n\n/**\n * A {@link ThreadPool} backed by Web Workers. Round-robins jobs across `size`\n * workers. The caller supplies `createWorker`; each worker is expected to accept\n * `{ id, source, input }` messages and reply with `{ id, ok, result }` or\n * `{ id, ok: false, error }` (see the reference worker protocol in this package).\n *\n * @remarks Web-only today. The native multi-threaded backend is a research\n * track — see the module docs.\n */\nexport function createWorkerPool(options: WorkerPoolOptions): ThreadPool {\n const count = Math.max(1, options.size ?? 1)\n const workers: WorkerLike[] = []\n const pending = new Map<number, PendingJob>()\n let nextId = 0\n let rr = 0\n let disposed = false\n\n /** Reject and forget every in-flight job dispatched to a given worker. */\n function rejectWorkerJobs(workerIndex: number, message: string): void {\n for (const [id, job] of pending) {\n if (job.workerIndex === workerIndex) {\n pending.delete(id)\n job.reject(new Error(message))\n }\n }\n }\n\n /** Create a worker at `index`, wire its handlers, and store it in place. */\n function spawn(index: number): void {\n const w = options.createWorker()\n w.onmessage = (event) => {\n const data = event.data as { id: number; ok: boolean; result?: unknown; error?: string }\n const job = pending.get(data.id)\n if (!job) return\n pending.delete(data.id)\n if (data.ok) job.resolve(data.result)\n else job.reject(new Error(data.error ?? 'worker job failed'))\n }\n w.onerror = (event) => {\n if (disposed) return\n // A worker crash loses EVERY job in flight on it (a worker can carry many\n // concurrently). Reject all of them — correlated by worker index, so a\n // healthy worker's jobs are never touched — then replace the dead worker in\n // place so the pool stays live and `size` keeps reflecting reality.\n rejectWorkerJobs(index, event.message ?? 'worker error')\n try {\n w.terminate()\n } catch {\n // The worker is already dead; ignore terminate failures.\n }\n spawn(index)\n }\n workers[index] = w\n }\n\n for (let i = 0; i < count; i++) spawn(i)\n\n return {\n run<In, Out>(job: (input: In) => Out, input: In): Promise<Out> {\n if (disposed) return Promise.reject(new Error('ThreadPool is disposed'))\n const index = rr % workers.length\n rr++\n const worker = workers[index]\n if (!worker) return Promise.reject(new Error('no worker available'))\n const id = nextId++\n return new Promise<Out>((resolve, reject) => {\n pending.set(id, { resolve: resolve as (v: unknown) => void, reject, workerIndex: index })\n worker.postMessage({ id, source: job.toString(), input })\n })\n },\n dispose() {\n if (disposed) return\n disposed = true\n for (const w of workers) w.terminate()\n for (const [, job] of pending) job.reject(new Error('ThreadPool disposed'))\n pending.clear()\n },\n get size() {\n return disposed ? 0 : workers.length\n },\n }\n}\n\n/**\n * 🔬 **Research track.** Placeholder for the native (Rust-backed) multi-threaded\n * pool. Not implemented — throws {@link NotImplementedError}. Use\n * {@link createWorkerPool} (web) or {@link createInlineThreadPool} (fallback)\n * today. Tracked for a later phase.\n *\n * @experimental\n */\nexport function createNativeThreadPool(): ThreadPool {\n throw new NotImplementedError('Native multi-threaded ThreadPool')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,yBAAqC;CACnD,IAAI,WAAW;CACf,OAAO;EACL,IAAa,KAAyB,OAAyB;GAC7D,IAAI,UAAU,OAAO,QAAQ,uBAAO,IAAI,MAAM,wBAAwB,CAAC;GACvE,IAAI;IACF,OAAO,QAAQ,QAAQ,IAAI,KAAK,CAAC;GACnC,SAAS,OAAO;IACd,OAAO,QAAQ,OAAO,KAAc;GACtC;EACF;EACA,UAAU;GACR,WAAW;EACb;EACA,MAAM;CACR;AACF;;;;;;;;;;AAsCA,SAAgB,iBAAiB,SAAwC;CACvE,MAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,QAAQ,CAAC;CAC3C,MAAM,UAAwB,CAAC;CAC/B,MAAM,0BAAU,IAAI,IAAwB;CAC5C,IAAI,SAAS;CACb,IAAI,KAAK;CACT,IAAI,WAAW;;CAGf,SAAS,iBAAiB,aAAqB,SAAuB;EACpE,KAAK,MAAM,CAAC,IAAI,QAAQ,SACtB,IAAI,IAAI,gBAAgB,aAAa;GACnC,QAAQ,OAAO,EAAE;GACjB,IAAI,OAAO,IAAI,MAAM,OAAO,CAAC;EAC/B;CAEJ;;CAGA,SAAS,MAAM,OAAqB;EAClC,MAAM,IAAI,QAAQ,aAAa;EAC/B,EAAE,aAAa,UAAU;GACvB,MAAM,OAAO,MAAM;GACnB,MAAM,MAAM,QAAQ,IAAI,KAAK,EAAE;GAC/B,IAAI,CAAC,KAAK;GACV,QAAQ,OAAO,KAAK,EAAE;GACtB,IAAI,KAAK,IAAI,IAAI,QAAQ,KAAK,MAAM;QAC/B,IAAI,OAAO,IAAI,MAAM,KAAK,SAAS,mBAAmB,CAAC;EAC9D;EACA,EAAE,WAAW,UAAU;GACrB,IAAI,UAAU;GAKd,iBAAiB,OAAO,MAAM,WAAW,cAAc;GACvD,IAAI;IACF,EAAE,UAAU;GACd,QAAQ,CAER;GACA,MAAM,KAAK;EACb;EACA,QAAQ,SAAS;CACnB;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK,MAAM,CAAC;CAEvC,OAAO;EACL,IAAa,KAAyB,OAAyB;GAC7D,IAAI,UAAU,OAAO,QAAQ,uBAAO,IAAI,MAAM,wBAAwB,CAAC;GACvE,MAAM,QAAQ,KAAK,QAAQ;GAC3B;GACA,MAAM,SAAS,QAAQ;GACvB,IAAI,CAAC,QAAQ,OAAO,QAAQ,uBAAO,IAAI,MAAM,qBAAqB,CAAC;GACnE,MAAM,KAAK;GACX,OAAO,IAAI,SAAc,SAAS,WAAW;IAC3C,QAAQ,IAAI,IAAI;KAAW;KAAiC;KAAQ,aAAa;IAAM,CAAC;IACxF,OAAO,YAAY;KAAE;KAAI,QAAQ,IAAI,SAAS;KAAG;IAAM,CAAC;GAC1D,CAAC;EACH;EACA,UAAU;GACR,IAAI,UAAU;GACd,WAAW;GACX,KAAK,MAAM,KAAK,SAAS,EAAE,UAAU;GACrC,KAAK,MAAM,GAAG,QAAQ,SAAS,IAAI,uBAAO,IAAI,MAAM,qBAAqB,CAAC;GAC1E,QAAQ,MAAM;EAChB;EACA,IAAI,OAAO;GACT,OAAO,WAAW,IAAI,QAAQ;EAChC;CACF;AACF;;;;;;;;;AAUA,SAAgB,yBAAqC;CACnD,MAAM,IAAI,oBAAoB,kCAAkC;AAClE"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Maturity level of a MindeesNative package or capability.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the legend in the repository `STATUS.md`. Used so tooling and
|
|
6
|
+
* consumers can introspect, honestly, how finished a piece of the framework is.
|
|
7
|
+
*/
|
|
8
|
+
type Maturity = 'stable' | 'experimental' | 'research-track' | 'planned' | 'scaffold';
|
|
9
|
+
/**
|
|
10
|
+
* Static identity + maturity metadata exported by every `@mindees/*` package.
|
|
11
|
+
*/
|
|
12
|
+
interface PackageInfo {
|
|
13
|
+
/** The npm package name, e.g. `@mindees/core`. */
|
|
14
|
+
readonly name: string;
|
|
15
|
+
/** The package version. All `@mindees/*` packages share one locked version line. */
|
|
16
|
+
readonly version: string;
|
|
17
|
+
/** Current maturity of the package. */
|
|
18
|
+
readonly maturity: Maturity;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { Maturity, PackageInfo };
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;AAMA;;;;AAAoB;KAAR,QAAA;;;;UAKK,WAAA;EAIN;EAAA,SAFA,IAAA;EAIU;EAAA,SAFV,OAAA;EAEkB;EAAA,SAAlB,QAAA,EAAU,QAAQ;AAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mindees/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MindeesNative core — fine-grained reactivity (signals/computed/effect/batch), component model with selector-isolated context, priority scheduler, and a thread-pool abstraction (Web Worker + inline; native is a research track).",
|
|
5
|
+
"license": "MIT OR Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/mindees/mindees.git",
|
|
23
|
+
"directory": "packages/core"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsdown",
|
|
27
|
+
"typecheck": "tsc --noEmit"
|
|
28
|
+
}
|
|
29
|
+
}
|