@mantaq/traversal 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anders Can
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # @mantaq/traversal
2
+
3
+ Graph extraction, traversal algorithms, and runtime tracking for
4
+ [@mantaq/core](https://www.npmjs.com/package/@mantaq/core) actors.
5
+
6
+ Build the state-machine graph from an actor, walk it with traversal
7
+ algorithms, and instrument coverage as the actor runs — useful for
8
+ verifying that every declared transition is reachable and exercised.
@@ -0,0 +1,99 @@
1
+ import { AnyActor, Snapshot } from "@mantaq/core";
2
+ //#region src/types.d.ts
3
+ interface GraphNode {
4
+ id: string;
5
+ label: string;
6
+ isActive: boolean;
7
+ isFinal: boolean;
8
+ isInitial?: boolean;
9
+ }
10
+ interface GraphEdge {
11
+ id: string;
12
+ source: string;
13
+ target: string;
14
+ label: string;
15
+ isActive: boolean;
16
+ isInternal?: boolean;
17
+ isUndetermined?: boolean;
18
+ payload?: {
19
+ action?: string;
20
+ };
21
+ contexts?: string[];
22
+ }
23
+ interface ActorGraph {
24
+ nodes: GraphNode[];
25
+ edges: GraphEdge[];
26
+ }
27
+ interface StateVisit {
28
+ stateName: string;
29
+ timestamp: number;
30
+ }
31
+ interface TransitionRecord {
32
+ from: string;
33
+ event: string;
34
+ to: string | undefined;
35
+ timestamp: number;
36
+ }
37
+ interface EffectRecord {
38
+ stateName: string;
39
+ timestamp: number;
40
+ }
41
+ interface HistoryEntry {
42
+ type: "state_visit" | "transition" | "effect" | "send";
43
+ data: StateVisit | TransitionRecord | EffectRecord | {
44
+ event: string;
45
+ timestamp: number;
46
+ };
47
+ }
48
+ //#endregion
49
+ //#region src/graph.d.ts
50
+ declare const INITIAL_NODE_ID = "__initial__";
51
+ declare function collectActiveStates(snapshot: Snapshot, prefix: string, activeSet: Set<string>): void;
52
+ declare function buildGraph(actor: AnyActor, options?: {
53
+ internalIds?: Set<string>;
54
+ sampleContext?: Record<string, unknown>;
55
+ sampleContexts?: Record<string, Record<string, unknown>>;
56
+ }): ActorGraph;
57
+ //#endregion
58
+ //#region src/history.d.ts
59
+ declare class History {
60
+ constructor();
61
+ append(entry: HistoryEntry): void;
62
+ entries(): readonly HistoryEntry[];
63
+ stateVisits(): StateVisit[];
64
+ transitions(): TransitionRecord[];
65
+ effects(): EffectRecord[];
66
+ sends(): Array<{
67
+ event: string;
68
+ timestamp: number;
69
+ }>;
70
+ visitedStates(): Set<string>;
71
+ firedTransitions(): Set<string>;
72
+ reset(): void;
73
+ }
74
+ //#endregion
75
+ //#region src/instrument.d.ts
76
+ interface InstrumentedActor {
77
+ history: History;
78
+ send(event: unknown): void;
79
+ state: AnyActor["state"];
80
+ snapshot(): Snapshot;
81
+ regions: Record<string, AnyActor>;
82
+ context?: Record<string, unknown>;
83
+ clock: AnyActor["clock"];
84
+ on(event: "change", fn: (snapshot: Snapshot) => void): () => void;
85
+ on(event: "error", fn: (error: unknown) => void): () => void;
86
+ on(event: "done", fn: () => void): () => void;
87
+ settled(): Promise<void>;
88
+ options?: AnyActor["options"];
89
+ }
90
+ declare function instrument(actor: AnyActor): InstrumentedActor;
91
+ //#endregion
92
+ //#region src/algorithms.d.ts
93
+ declare function reachable(graph: ActorGraph, fromId: string, toId: string): boolean;
94
+ declare function allPaths(graph: ActorGraph, fromId: string, toId: string): string[][];
95
+ declare function findCycles(graph: ActorGraph): string[][];
96
+ declare function unreachableNodes(graph: ActorGraph, fromId: string): string[];
97
+ declare function shortestPath(graph: ActorGraph, fromId: string, toId: string): string[] | null;
98
+ //#endregion
99
+ export { type ActorGraph, type EffectRecord, type GraphEdge, type GraphNode, History, type HistoryEntry, INITIAL_NODE_ID, type InstrumentedActor, type StateVisit, type TransitionRecord, allPaths, buildGraph, collectActiveStates, findCycles, instrument, reachable, shortestPath, unreachableNodes };
package/dist/index.mjs ADDED
@@ -0,0 +1,479 @@
1
+ import { Either } from "@mantaq/utils";
2
+ //#region src/graph.ts
3
+ const INITIAL_NODE_ID = "__initial__";
4
+ function collectActiveStates(snapshot, prefix, activeSet) {
5
+ if (!snapshot || !snapshot.path) return;
6
+ const currentName = snapshot.path[snapshot.path.length - 1];
7
+ if (!currentName) return;
8
+ const fullId = nodeId(prefix, currentName);
9
+ activeSet.add(fullId);
10
+ if (snapshot.regions && !snapshot.done) for (const [regionName, regionSnap] of Object.entries(snapshot.regions)) collectActiveStates(regionSnap, regionName, activeSet);
11
+ }
12
+ function nodeId(prefix, name) {
13
+ return prefix ? `${prefix}.${name}` : name;
14
+ }
15
+ function buildNodesFromStates(states, activeSet, pathPrefix) {
16
+ return states.map((stateRef) => {
17
+ const nid = nodeId(pathPrefix, stateRef.name);
18
+ return {
19
+ id: nid,
20
+ label: stateRef.name,
21
+ isActive: activeSet.has(nid),
22
+ isFinal: stateRef.isFinal
23
+ };
24
+ });
25
+ }
26
+ function invokeHandler(handler, eventId, ctx, actor) {
27
+ return Either.from(() => {
28
+ const result = handler({ id: eventId }, {
29
+ context: ctx,
30
+ actor
31
+ });
32
+ return {
33
+ targetName: result?.state?.name,
34
+ emitNames: result?.emit?.map((e) => e.id).filter((id) => Boolean(id)) ?? []
35
+ };
36
+ });
37
+ }
38
+ function upsertEdge(sink, traversal, eventId, handled) {
39
+ const undetermined = !handled.targetName;
40
+ const targetId = handled.targetName ? nodeId(traversal.pathPrefix, handled.targetName) : `${sink.sourceId}-undetermined-${eventId}`;
41
+ const edgeId = `${sink.sourceId}-${eventId}-${targetId}`;
42
+ const existing = sink.edgeMap.get(edgeId);
43
+ if (existing) existing.contexts.push(sink.ctxName);
44
+ else sink.edgeMap.set(edgeId, {
45
+ id: edgeId,
46
+ source: sink.sourceId,
47
+ target: targetId,
48
+ label: eventId,
49
+ isActive: traversal.activeSet.has(sink.sourceId),
50
+ isInternal: traversal.internalIds?.has(eventId),
51
+ isUndetermined: undetermined,
52
+ contexts: [sink.ctxName],
53
+ ...handled.emitNames.length > 0 && { payload: { action: `emit(${handled.emitNames.join(", ")})` } }
54
+ });
55
+ }
56
+ function processStateTransitions(stateTransitions, pass) {
57
+ const stateTransitionedEvents = /* @__PURE__ */ new Set();
58
+ for (const [eventId, handler] of Object.entries(stateTransitions)) {
59
+ if (typeof handler !== "function") continue;
60
+ for (const ctxName of pass.traversal.contextNames) {
61
+ const ctx = pass.traversal.contexts[ctxName];
62
+ const handled = Either.getOrElse(invokeHandler(handler, eventId, ctx, pass.traversal.actor), () => ({
63
+ targetName: void 0,
64
+ emitNames: []
65
+ }));
66
+ if (handled.targetName) stateTransitionedEvents.add(eventId);
67
+ upsertEdge({
68
+ edgeMap: pass.edgeMap,
69
+ sourceId: pass.sourceId,
70
+ ctxName
71
+ }, pass.traversal, eventId, handled);
72
+ }
73
+ }
74
+ return stateTransitionedEvents;
75
+ }
76
+ function mergeAnyTransitions(anyTransitions, stateTransitionedEvents, pass) {
77
+ for (const [eventId, handler] of Object.entries(anyTransitions)) {
78
+ if (typeof handler !== "function") continue;
79
+ if (stateTransitionedEvents.has(eventId)) continue;
80
+ for (const ctxName of pass.traversal.contextNames) {
81
+ const ctx = pass.traversal.contexts[ctxName];
82
+ const handled = Either.getOrElse(invokeHandler(handler, eventId, ctx, pass.traversal.actor), () => ({
83
+ targetName: void 0,
84
+ emitNames: []
85
+ }));
86
+ upsertEdge({
87
+ edgeMap: pass.edgeMap,
88
+ sourceId: pass.sourceId,
89
+ ctxName
90
+ }, pass.traversal, eventId, handled);
91
+ }
92
+ }
93
+ }
94
+ function collectTransitionsForState(stateTransitions, anyTransitions, sourceId, traversal) {
95
+ const edgeMap = /* @__PURE__ */ new Map();
96
+ const pass = {
97
+ edgeMap,
98
+ sourceId,
99
+ traversal
100
+ };
101
+ const stateTransitionedEvents = stateTransitions ? processStateTransitions(stateTransitions, pass) : /* @__PURE__ */ new Set();
102
+ if (anyTransitions) mergeAnyTransitions(anyTransitions, stateTransitionedEvents, pass);
103
+ return edgeMap;
104
+ }
105
+ function buildEdgesFromTransitions(states, transitions, traversal) {
106
+ if (!transitions) return [];
107
+ const anyTransitions = transitions["Any"];
108
+ const edges = [];
109
+ for (const stateRef of states) {
110
+ const sourceId = nodeId(traversal.pathPrefix, stateRef.name);
111
+ const edgeMap = collectTransitionsForState(transitions[stateRef.name], anyTransitions, sourceId, traversal);
112
+ edges.push(...edgeMap.values());
113
+ }
114
+ return edges;
115
+ }
116
+ function addNodesForActor(actor, pathPrefix, activeSet) {
117
+ return buildNodesFromStates(actor.options?.states ?? [], activeSet, pathPrefix);
118
+ }
119
+ function addEdgesForActor(actor, traversal) {
120
+ return buildEdgesFromTransitions(actor.options?.states ?? [], actor.options?.transitions, traversal);
121
+ }
122
+ function recurseRegions(actor, traversal) {
123
+ const nodes = [];
124
+ const edges = [];
125
+ if (actor.regions) for (const [regionName, childActor] of Object.entries(actor.regions)) {
126
+ const child = buildForActor(childActor, {
127
+ ...traversal,
128
+ pathPrefix: nodeId(traversal.pathPrefix, regionName)
129
+ });
130
+ nodes.push(...child.nodes);
131
+ edges.push(...child.edges);
132
+ }
133
+ return {
134
+ nodes,
135
+ edges
136
+ };
137
+ }
138
+ function addEffectSelfLoops(actor, pathPrefix, activeSet) {
139
+ const edges = [];
140
+ const effects = actor.options?.effects;
141
+ if (effects) {
142
+ for (const [stateName, fns] of Object.entries(effects)) if (Array.isArray(fns) && fns.length > 0) {
143
+ const sid = nodeId(pathPrefix, stateName);
144
+ edges.push({
145
+ id: `${sid}-effect:${stateName}-${sid}`,
146
+ source: sid,
147
+ target: sid,
148
+ label: `effect:${stateName}`,
149
+ isActive: activeSet.has(sid),
150
+ isInternal: true
151
+ });
152
+ }
153
+ }
154
+ return edges;
155
+ }
156
+ function buildForActor(actor, traversal) {
157
+ if (!actor) return {
158
+ nodes: [],
159
+ edges: []
160
+ };
161
+ const nodes = addNodesForActor(actor, traversal.pathPrefix, traversal.activeSet);
162
+ const edges = addEdgesForActor(actor, traversal);
163
+ const region = recurseRegions(actor, traversal);
164
+ nodes.push(...region.nodes);
165
+ edges.push(...region.edges);
166
+ edges.push(...addEffectSelfLoops(actor, traversal.pathPrefix, traversal.activeSet));
167
+ return {
168
+ nodes,
169
+ edges
170
+ };
171
+ }
172
+ function addInitialNode(actor, nodes, edges) {
173
+ const initialName = actor.options?.initial?.name;
174
+ if (!initialName) return;
175
+ const initNodeId = nodeId("", INITIAL_NODE_ID);
176
+ const targetId = nodeId("", initialName);
177
+ nodes.push({
178
+ id: initNodeId,
179
+ label: "",
180
+ isActive: false,
181
+ isFinal: false,
182
+ isInitial: true
183
+ });
184
+ edges.push({
185
+ id: `${initNodeId}->${targetId}`,
186
+ source: initNodeId,
187
+ target: targetId,
188
+ label: "",
189
+ isActive: true
190
+ });
191
+ }
192
+ function collectActorsFromSnapshot(snapshot) {
193
+ const activeSet = /* @__PURE__ */ new Set();
194
+ collectActiveStates(snapshot, "", activeSet);
195
+ return activeSet;
196
+ }
197
+ function collectNamedContexts(options) {
198
+ return options?.sampleContexts ?? (options?.sampleContext ? { default: options.sampleContext } : void 0);
199
+ }
200
+ function buildGraph(actor, options) {
201
+ if (!actor) return {
202
+ nodes: [],
203
+ edges: []
204
+ };
205
+ return Either.match(Either.from(() => {
206
+ const activeSet = collectActorsFromSnapshot(actor.snapshot());
207
+ const contexts = collectNamedContexts(options) ?? { default: { ...actor.context } };
208
+ const { nodes, edges } = buildForActor(actor, {
209
+ actor,
210
+ pathPrefix: "",
211
+ activeSet,
212
+ internalIds: options?.internalIds,
213
+ contexts,
214
+ contextNames: Object.keys(contexts)
215
+ });
216
+ addInitialNode(actor, nodes, edges);
217
+ return {
218
+ nodes,
219
+ edges
220
+ };
221
+ }), (error) => {
222
+ console.error("[mantaq/traversal] buildGraph failed:", error);
223
+ return {
224
+ nodes: [],
225
+ edges: []
226
+ };
227
+ }, (result) => result);
228
+ }
229
+ //#endregion
230
+ //#region src/history.ts
231
+ const entriesMap = /* @__PURE__ */ new WeakMap();
232
+ function entriesOfType(entries, type) {
233
+ return entries.filter((e) => e.type === type).map((e) => e.data);
234
+ }
235
+ var History = class {
236
+ constructor() {
237
+ entriesMap.set(this, []);
238
+ }
239
+ append(entry) {
240
+ entriesMap.get(this).push(entry);
241
+ }
242
+ entries() {
243
+ return entriesMap.get(this);
244
+ }
245
+ stateVisits() {
246
+ return entriesOfType(entriesMap.get(this), "state_visit");
247
+ }
248
+ transitions() {
249
+ return entriesOfType(entriesMap.get(this), "transition");
250
+ }
251
+ effects() {
252
+ return entriesOfType(entriesMap.get(this), "effect");
253
+ }
254
+ sends() {
255
+ return entriesOfType(entriesMap.get(this), "send");
256
+ }
257
+ visitedStates() {
258
+ const result = /* @__PURE__ */ new Set();
259
+ for (const visit of this.stateVisits()) result.add(visit.stateName);
260
+ return result;
261
+ }
262
+ firedTransitions() {
263
+ const result = /* @__PURE__ */ new Set();
264
+ for (const t of this.transitions()) result.add(`${t.from}:${t.event}`);
265
+ return result;
266
+ }
267
+ reset() {
268
+ const arr = entriesMap.get(this);
269
+ arr.length = 0;
270
+ }
271
+ };
272
+ //#endregion
273
+ //#region src/instrument.ts
274
+ function wrapWithProxy(actor, hooks) {
275
+ const { history, origSend, pendingEventId } = hooks;
276
+ return {
277
+ get history() {
278
+ return history;
279
+ },
280
+ get state() {
281
+ return actor.state;
282
+ },
283
+ get regions() {
284
+ return actor.regions;
285
+ },
286
+ get context() {
287
+ return actor.context;
288
+ },
289
+ get clock() {
290
+ return actor.clock;
291
+ },
292
+ get options() {
293
+ return actor.options;
294
+ },
295
+ send(event) {
296
+ const { id: eventId } = trackSendEvent(history, event);
297
+ pendingEventId.value = eventId;
298
+ try {
299
+ origSend(event);
300
+ } finally {
301
+ pendingEventId.value = void 0;
302
+ }
303
+ },
304
+ snapshot() {
305
+ return actor.snapshot();
306
+ },
307
+ on: actor.on.bind(actor),
308
+ settled: actor.settled.bind(actor)
309
+ };
310
+ }
311
+ function recordTransition(history, from, to, eventId) {
312
+ history.append({
313
+ type: "transition",
314
+ data: {
315
+ from,
316
+ event: eventId,
317
+ to,
318
+ timestamp: Date.now()
319
+ }
320
+ });
321
+ history.append({
322
+ type: "state_visit",
323
+ data: {
324
+ stateName: to,
325
+ timestamp: Date.now()
326
+ }
327
+ });
328
+ history.append({
329
+ type: "effect",
330
+ data: {
331
+ stateName: to,
332
+ timestamp: Date.now()
333
+ }
334
+ });
335
+ }
336
+ function trackSendEvent(history, event) {
337
+ const eventId = event?.id ?? "unknown";
338
+ history.append({
339
+ type: "send",
340
+ data: {
341
+ event: eventId,
342
+ timestamp: Date.now()
343
+ }
344
+ });
345
+ return { id: eventId };
346
+ }
347
+ function instrument(actor) {
348
+ const history = new History();
349
+ const origSend = actor.send.bind(actor);
350
+ let prevStateName = actor.state.name;
351
+ const pendingEventId = { value: void 0 };
352
+ history.append({
353
+ type: "state_visit",
354
+ data: {
355
+ stateName: actor.state.name,
356
+ timestamp: Date.now()
357
+ }
358
+ });
359
+ const wrapped = wrapWithProxy(actor, {
360
+ history,
361
+ origSend,
362
+ pendingEventId
363
+ });
364
+ actor.on("change", () => {
365
+ const currentName = actor.state.name;
366
+ if (currentName !== prevStateName) {
367
+ recordTransition(history, prevStateName, currentName, pendingEventId.value ?? "unknown");
368
+ prevStateName = currentName;
369
+ }
370
+ });
371
+ return wrapped;
372
+ }
373
+ //#endregion
374
+ //#region src/algorithms.ts
375
+ function buildAdjacency(graph) {
376
+ const adj = {};
377
+ for (const node of graph.nodes) adj[node.id] = [];
378
+ for (const edge of graph.edges) if (adj[edge.source]) adj[edge.source].push({
379
+ target: edge.target,
380
+ label: edge.label
381
+ });
382
+ return adj;
383
+ }
384
+ function bfsWalk(adj, start, visit) {
385
+ const visited = {};
386
+ const queue = [start];
387
+ while (queue.length > 0) {
388
+ const current = queue.shift();
389
+ if (visited[current]) continue;
390
+ visited[current] = true;
391
+ if (visit(current)) break;
392
+ const neighbors = adj[current] || [];
393
+ for (let i = 0; i < neighbors.length; i++) {
394
+ const target = neighbors[i].target;
395
+ if (!visited[target]) queue.push(target);
396
+ }
397
+ }
398
+ return visited;
399
+ }
400
+ function reachable(graph, fromId, toId) {
401
+ return bfsWalk(buildAdjacency(graph), fromId, (node) => node === toId)[toId] === true;
402
+ }
403
+ function allPaths(graph, fromId, toId) {
404
+ const adj = buildAdjacency(graph);
405
+ const results = [];
406
+ const visited = {};
407
+ function dfs(current, path) {
408
+ if (current === toId) {
409
+ results.push(path.slice());
410
+ return;
411
+ }
412
+ if (visited[current]) return;
413
+ visited[current] = true;
414
+ const neighbors = adj[current] || [];
415
+ for (let i = 0; i < neighbors.length; i++) {
416
+ path.push(neighbors[i].target);
417
+ dfs(neighbors[i].target, path);
418
+ path.pop();
419
+ }
420
+ delete visited[current];
421
+ }
422
+ dfs(fromId, [fromId]);
423
+ return results;
424
+ }
425
+ function findCycles(graph) {
426
+ const adj = buildAdjacency(graph);
427
+ const cycles = [];
428
+ const visited = {};
429
+ const inStack = {};
430
+ const path = [];
431
+ function dfs(node) {
432
+ if (inStack[node]) {
433
+ const cycleStart = path.indexOf(node);
434
+ if (cycleStart !== -1) cycles.push(path.slice(cycleStart).concat(node));
435
+ return;
436
+ }
437
+ if (visited[node]) return;
438
+ visited[node] = true;
439
+ inStack[node] = true;
440
+ path.push(node);
441
+ const neighbors = adj[node] || [];
442
+ for (let i = 0; i < neighbors.length; i++) dfs(neighbors[i].target);
443
+ path.pop();
444
+ delete inStack[node];
445
+ }
446
+ for (const node of graph.nodes) dfs(node.id);
447
+ return cycles;
448
+ }
449
+ function unreachableNodes(graph, fromId) {
450
+ const visited = bfsWalk(buildAdjacency(graph), fromId, () => false);
451
+ const result = [];
452
+ for (const node of graph.nodes) if (!visited[node.id]) result.push(node.id);
453
+ return result;
454
+ }
455
+ function shortestPath(graph, fromId, toId) {
456
+ const adj = buildAdjacency(graph);
457
+ const visited = {};
458
+ const queue = [{
459
+ node: fromId,
460
+ path: [fromId]
461
+ }];
462
+ while (queue.length > 0) {
463
+ const { node: current, path } = queue.shift();
464
+ if (current === toId) return path;
465
+ if (visited[current]) continue;
466
+ visited[current] = true;
467
+ const neighbors = adj[current] || [];
468
+ for (let i = 0; i < neighbors.length; i++) {
469
+ const target = neighbors[i].target;
470
+ if (!visited[target]) queue.push({
471
+ node: target,
472
+ path: path.concat(target)
473
+ });
474
+ }
475
+ }
476
+ return null;
477
+ }
478
+ //#endregion
479
+ export { History, INITIAL_NODE_ID, allPaths, buildGraph, collectActiveStates, findCycles, instrument, reachable, shortestPath, unreachableNodes };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@mantaq/traversal",
3
+ "version": "0.0.1",
4
+ "description": "Graph extraction, traversal algorithms, and runtime tracking for mantaq actors.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/AndersCan/mantaq",
9
+ "directory": "packages/traversal"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "type": "module",
15
+ "exports": {
16
+ ".": "./dist/index.mjs",
17
+ "./package.json": "./package.json"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "dependencies": {
23
+ "@mantaq/core": "0.0.1",
24
+ "@mantaq/utils": "0.0.1"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^26.2.0",
28
+ "@typescript/native-preview": "7.0.0-dev.20260707.2",
29
+ "@vitest/coverage-v8": "4.1.10",
30
+ "typescript": "^7.0.2",
31
+ "vite": "npm:@voidzero-dev/vite-plus-core@0.2.8",
32
+ "vite-plus": "0.2.8"
33
+ },
34
+ "scripts": {
35
+ "build": "vp pack",
36
+ "dev": "vp pack --watch",
37
+ "test": "vp test",
38
+ "check": "vp check",
39
+ "coverage": "vp test run --coverage"
40
+ }
41
+ }