@torkbot/sledge 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.
@@ -0,0 +1,116 @@
1
+ class VirtualRuntimeClock {
2
+ #nowMs;
3
+ constructor(nowMs) {
4
+ this.#nowMs = nowMs;
5
+ }
6
+ nowMs() {
7
+ return this.#nowMs;
8
+ }
9
+ advanceByMs(ms) {
10
+ this.#nowMs += ms;
11
+ }
12
+ }
13
+ class VirtualRuntimeScheduler {
14
+ #clock;
15
+ #entries = new Map();
16
+ #nextId = 1;
17
+ constructor(clock) {
18
+ this.#clock = clock;
19
+ }
20
+ scheduleOnce(delayMs, task) {
21
+ return this.#schedule(delayMs, null, task);
22
+ }
23
+ scheduleRepeating(everyMs, task) {
24
+ return this.#schedule(everyMs, everyMs, task);
25
+ }
26
+ runDue() {
27
+ while (true) {
28
+ const dueEntry = this.#nextDueEntry();
29
+ if (dueEntry === null) {
30
+ return;
31
+ }
32
+ dueEntry.task();
33
+ if (dueEntry.cancelled) {
34
+ this.#entries.delete(dueEntry.id);
35
+ continue;
36
+ }
37
+ if (dueEntry.everyMs === null) {
38
+ this.#entries.delete(dueEntry.id);
39
+ continue;
40
+ }
41
+ dueEntry.dueAtMs += dueEntry.everyMs;
42
+ }
43
+ }
44
+ #schedule(delayMs, everyMs, task) {
45
+ const id = this.#nextId;
46
+ this.#nextId += 1;
47
+ const entry = {
48
+ id,
49
+ dueAtMs: this.#clock.nowMs() + delayMs,
50
+ everyMs,
51
+ task,
52
+ cancelled: false,
53
+ };
54
+ this.#entries.set(id, entry);
55
+ return {
56
+ cancel: () => {
57
+ entry.cancelled = true;
58
+ },
59
+ };
60
+ }
61
+ #nextDueEntry() {
62
+ let selected = null;
63
+ for (const entry of this.#entries.values()) {
64
+ if (entry.cancelled) {
65
+ continue;
66
+ }
67
+ if (entry.dueAtMs > this.#clock.nowMs()) {
68
+ continue;
69
+ }
70
+ if (selected === null) {
71
+ selected = entry;
72
+ continue;
73
+ }
74
+ if (entry.dueAtMs < selected.dueAtMs) {
75
+ selected = entry;
76
+ continue;
77
+ }
78
+ if (entry.dueAtMs === selected.dueAtMs && entry.id < selected.id) {
79
+ selected = entry;
80
+ }
81
+ }
82
+ return selected;
83
+ }
84
+ }
85
+ /**
86
+ * Deterministic runtime harness for contract and integration tests.
87
+ */
88
+ export class VirtualRuntimeHarness {
89
+ #clock;
90
+ #scheduler;
91
+ constructor(nowMs) {
92
+ this.#clock = new VirtualRuntimeClock(nowMs);
93
+ this.#scheduler = new VirtualRuntimeScheduler(this.#clock);
94
+ }
95
+ get clock() {
96
+ return this.#clock;
97
+ }
98
+ get scheduler() {
99
+ return this.#scheduler;
100
+ }
101
+ nowMs() {
102
+ return this.#clock.nowMs();
103
+ }
104
+ async advanceByMs(ms) {
105
+ this.#clock.advanceByMs(ms);
106
+ this.#scheduler.runDue();
107
+ await this.flush();
108
+ }
109
+ async flush() {
110
+ this.#scheduler.runDue();
111
+ for (let i = 0; i < 5; i += 1) {
112
+ await Promise.resolve();
113
+ }
114
+ }
115
+ }
116
+ //# sourceMappingURL=virtual-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-runtime.js","sourceRoot":"","sources":["../../src/runtime/virtual-runtime.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@torkbot/sledge",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "A SQLite-backed event and work engine that stays consistent across retries, restarts, and failures.",
7
+ "license": "MIT",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "exports": {
12
+ "./ledger": {
13
+ "types": "./dist/ledger/ledger.d.ts",
14
+ "default": "./dist/ledger/ledger.js"
15
+ },
16
+ "./database-ledger-engine": {
17
+ "types": "./dist/ledger/database-ledger-engine.d.ts",
18
+ "default": "./dist/ledger/database-ledger-engine.js"
19
+ },
20
+ "./better-sqlite3-ledger": {
21
+ "types": "./dist/ledger/better-sqlite3-ledger.d.ts",
22
+ "default": "./dist/ledger/better-sqlite3-ledger.js"
23
+ },
24
+ "./turso-ledger": {
25
+ "types": "./dist/ledger/turso-ledger.d.ts",
26
+ "default": "./dist/ledger/turso-ledger.js"
27
+ },
28
+ "./runtime/contracts": {
29
+ "types": "./dist/runtime/contracts.d.ts",
30
+ "default": "./dist/runtime/contracts.js"
31
+ },
32
+ "./runtime/node-runtime": {
33
+ "types": "./dist/runtime/node-runtime.d.ts",
34
+ "default": "./dist/runtime/node-runtime.js"
35
+ },
36
+ "./runtime/virtual-runtime": {
37
+ "types": "./dist/runtime/virtual-runtime.d.ts",
38
+ "default": "./dist/runtime/virtual-runtime.js"
39
+ }
40
+ },
41
+ "types": "./dist/ledger/ledger.d.ts",
42
+ "files": [
43
+ "dist",
44
+ "README.md",
45
+ "LICENSE"
46
+ ],
47
+ "scripts": {
48
+ "build": "rm -rf dist && tsc --project tsconfig.build.json --pretty",
49
+ "test": "node --test src/**/*.test.ts",
50
+ "typecheck": "tsc --noEmit --pretty",
51
+ "lint": "prettier -c README.md package.json tsconfig.json tsconfig.build.json src/**/*.ts",
52
+ "prepublishOnly": "node --run build"
53
+ },
54
+ "dependencies": {
55
+ "@sinclair/typebox": "^0.34.48",
56
+ "@tursodatabase/database": "^0.5.1",
57
+ "better-sqlite3": "^12.6.2"
58
+ },
59
+ "devDependencies": {
60
+ "@types/better-sqlite3": "^7.6.13",
61
+ "@types/node": "^24.12.0",
62
+ "prettier": "^3.8.1",
63
+ "typescript": "^5.9.3"
64
+ },
65
+ "engines": {
66
+ "node": ">=22.6.0"
67
+ }
68
+ }