@absurd-sqlite/bun-worker 0.1.0-alpha.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/README.md +22 -0
- package/bun.lock +134 -0
- package/package.json +51 -0
- package/src/index.ts +63 -0
- package/src/sqlite.ts +169 -0
- package/test/basic.test.ts +505 -0
- package/test/events.test.ts +207 -0
- package/test/hooks.test.ts +350 -0
- package/test/idempotent.test.ts +195 -0
- package/test/index.test.ts +63 -0
- package/test/retry.test.ts +389 -0
- package/test/run.test.ts +101 -0
- package/test/setup.ts +650 -0
- package/test/sqlite.test.ts +89 -0
- package/test/step.test.ts +259 -0
- package/test/wait-for.ts +21 -0
- package/test/worker.test.ts +194 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Absurd Sqlite Bun Worker
|
|
2
|
+
|
|
3
|
+
Utilities for running Absurd-Sqlite workers in Bun.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Set the database path and extension path via environment variables:
|
|
8
|
+
|
|
9
|
+
- `ABSURD_DATABASE_PATH` (required): path to the SQLite database file.
|
|
10
|
+
- `ABSURD_DATABASE_EXTENSION_PATH` (required): path to the Absurd-SQLite extension (`libabsurd.*`).
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import run from "@absurd-sqlite/bun-worker";
|
|
16
|
+
|
|
17
|
+
await run((absurd) => {
|
|
18
|
+
absurd.registerTask({ name: "hello" }, async (params) => {
|
|
19
|
+
return { ok: true };
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
```
|
package/bun.lock
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 1,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "@absurd-sqlite/bun-worker",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@absurd-sqlite/sdk": "^0.2.0-alpha.3",
|
|
9
|
+
"absurd-sdk": "~0.0.7",
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"bun-types": "^1.3.5",
|
|
13
|
+
"typescript": "^5.9.3",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
"packages": {
|
|
18
|
+
"@absurd-sqlite/sdk": ["@absurd-sqlite/sdk@0.2.0-alpha.3", "", { "dependencies": { "absurd-sdk": "~0.0.7" }, "peerDependencies": { "better-sqlite3": "^12.5.0" } }, "sha512-+4VYpigwRng2O+lkNPTzNgMOXl/vEBWZcnD1NNRbNuaKYz9xO4/psssT2aCfKJ4yMffvdatV8bz2g3NbQC7OPQ=="],
|
|
19
|
+
|
|
20
|
+
"@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
|
21
|
+
|
|
22
|
+
"absurd-sdk": ["absurd-sdk@0.0.7", "", { "peerDependencies": { "pg": "^8.0.0" } }, "sha512-8e+LUdtzLHFMMF5vaVCKfp0aZ21t3aazgVkYUFzhb9kL+/bQkD8Vw68tgEAUz53pT2xfIrScTA9QZXYfC1KDtA=="],
|
|
23
|
+
|
|
24
|
+
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
|
25
|
+
|
|
26
|
+
"better-sqlite3": ["better-sqlite3@12.5.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-WwCZ/5Diz7rsF29o27o0Gcc1Du+l7Zsv7SYtVPG0X3G/uUI1LqdxrQI7c9Hs2FWpqXXERjW9hp6g3/tH7DlVKg=="],
|
|
27
|
+
|
|
28
|
+
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
|
29
|
+
|
|
30
|
+
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
|
|
31
|
+
|
|
32
|
+
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
|
33
|
+
|
|
34
|
+
"bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
|
|
35
|
+
|
|
36
|
+
"chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
|
|
37
|
+
|
|
38
|
+
"decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
|
|
39
|
+
|
|
40
|
+
"deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
|
|
41
|
+
|
|
42
|
+
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
43
|
+
|
|
44
|
+
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
|
45
|
+
|
|
46
|
+
"expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
|
|
47
|
+
|
|
48
|
+
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
|
|
49
|
+
|
|
50
|
+
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
|
|
51
|
+
|
|
52
|
+
"github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
|
|
53
|
+
|
|
54
|
+
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
|
55
|
+
|
|
56
|
+
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
|
57
|
+
|
|
58
|
+
"ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
|
|
59
|
+
|
|
60
|
+
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
|
61
|
+
|
|
62
|
+
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
|
63
|
+
|
|
64
|
+
"mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
|
|
65
|
+
|
|
66
|
+
"napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
|
|
67
|
+
|
|
68
|
+
"node-abi": ["node-abi@3.85.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg=="],
|
|
69
|
+
|
|
70
|
+
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
|
71
|
+
|
|
72
|
+
"pg": ["pg@8.16.3", "", { "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", "pg-protocol": "^1.10.3", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.2.7" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw=="],
|
|
73
|
+
|
|
74
|
+
"pg-cloudflare": ["pg-cloudflare@1.2.7", "", {}, "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg=="],
|
|
75
|
+
|
|
76
|
+
"pg-connection-string": ["pg-connection-string@2.9.1", "", {}, "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w=="],
|
|
77
|
+
|
|
78
|
+
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
|
79
|
+
|
|
80
|
+
"pg-pool": ["pg-pool@3.10.1", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg=="],
|
|
81
|
+
|
|
82
|
+
"pg-protocol": ["pg-protocol@1.10.3", "", {}, "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ=="],
|
|
83
|
+
|
|
84
|
+
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
|
85
|
+
|
|
86
|
+
"pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="],
|
|
87
|
+
|
|
88
|
+
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
|
89
|
+
|
|
90
|
+
"postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
|
91
|
+
|
|
92
|
+
"postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
|
93
|
+
|
|
94
|
+
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
|
95
|
+
|
|
96
|
+
"prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
|
|
97
|
+
|
|
98
|
+
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
|
|
99
|
+
|
|
100
|
+
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
|
|
101
|
+
|
|
102
|
+
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
|
103
|
+
|
|
104
|
+
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
|
105
|
+
|
|
106
|
+
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
|
107
|
+
|
|
108
|
+
"simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
|
|
109
|
+
|
|
110
|
+
"simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
|
|
111
|
+
|
|
112
|
+
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
|
113
|
+
|
|
114
|
+
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
|
115
|
+
|
|
116
|
+
"strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
|
|
117
|
+
|
|
118
|
+
"tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
|
|
119
|
+
|
|
120
|
+
"tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
|
121
|
+
|
|
122
|
+
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
|
|
123
|
+
|
|
124
|
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
125
|
+
|
|
126
|
+
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
127
|
+
|
|
128
|
+
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
|
129
|
+
|
|
130
|
+
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
|
131
|
+
|
|
132
|
+
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
|
|
133
|
+
}
|
|
134
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@absurd-sqlite/bun-worker",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Bun worker utilities for Absurd-Sqlite",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"prebuild": "cd ../typescript && npm run build",
|
|
16
|
+
"build": "bun run prebuild && bun build ./src/index.ts --outdir ./dist --target bun && bun x tsc -p tsconfig.build.json",
|
|
17
|
+
"type-check": "bun run prebuild && bun x tsc -p tsconfig.json --noEmit",
|
|
18
|
+
"test:prepare": "cd ../../ && cargo build -p absurd-sqlite-extension --release",
|
|
19
|
+
"test": "bun run test:prepare && bun test"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/b4fun/absurd-sqlite.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"absurd",
|
|
27
|
+
"sqlite",
|
|
28
|
+
"queue",
|
|
29
|
+
"task",
|
|
30
|
+
"durable",
|
|
31
|
+
"workflow",
|
|
32
|
+
"bun"
|
|
33
|
+
],
|
|
34
|
+
"author": "",
|
|
35
|
+
"license": "Apache-2.0",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/b4fun/absurd-sqlite/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/b4fun/absurd-sqlite#readme",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@absurd-sqlite/sdk": "~0.2.0-alpha.3",
|
|
42
|
+
"absurd-sdk": "~0.0.7"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"bun-types": "^1.3.5",
|
|
46
|
+
"typescript": "^5.9.3"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"bun": ">=1.1.0"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Absurd } from "absurd-sdk";
|
|
2
|
+
import { Database } from "bun:sqlite";
|
|
3
|
+
|
|
4
|
+
import { BunSqliteConnection } from "./sqlite";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Register tasks and perform any one-time setup before the worker starts.
|
|
8
|
+
*/
|
|
9
|
+
export type SetupFunction = (absurd: Absurd) => void | Promise<void>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Boots a worker using Bun's SQLite driver and Absurd's task engine.
|
|
13
|
+
*
|
|
14
|
+
* Requires:
|
|
15
|
+
* - ABSURD_DATABASE_PATH: SQLite database file path.
|
|
16
|
+
* - ABSURD_DATABASE_EXTENSION_PATH: Absurd-SQLite extension path (libabsurd.*).
|
|
17
|
+
*/
|
|
18
|
+
export default async function run(
|
|
19
|
+
setupFunction: SetupFunction
|
|
20
|
+
): Promise<void> {
|
|
21
|
+
const dbPath = process.env.ABSURD_DATABASE_PATH;
|
|
22
|
+
const extensionPath = process.env.ABSURD_DATABASE_EXTENSION_PATH;
|
|
23
|
+
|
|
24
|
+
if (!dbPath) {
|
|
25
|
+
throw new Error("ABSURD_DATABASE_PATH is required");
|
|
26
|
+
}
|
|
27
|
+
if (!extensionPath) {
|
|
28
|
+
throw new Error("ABSURD_DATABASE_EXTENSION_PATH is required");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const db = new Database(dbPath);
|
|
32
|
+
(db as unknown as { loadExtension(path: string): void }).loadExtension(
|
|
33
|
+
extensionPath
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const conn = new BunSqliteConnection(db);
|
|
37
|
+
const absurd = new Absurd({ db: conn });
|
|
38
|
+
|
|
39
|
+
await setupFunction(absurd);
|
|
40
|
+
const worker = await absurd.startWorker();
|
|
41
|
+
|
|
42
|
+
let shuttingDown = false;
|
|
43
|
+
const shutdown = async (signal: string) => {
|
|
44
|
+
if (shuttingDown) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
shuttingDown = true;
|
|
48
|
+
try {
|
|
49
|
+
await worker.close();
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error(`Failed to close worker on ${signal}`, err);
|
|
52
|
+
} finally {
|
|
53
|
+
db.close();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
process.once("SIGINT", () => {
|
|
58
|
+
void shutdown("SIGINT");
|
|
59
|
+
});
|
|
60
|
+
process.once("SIGTERM", () => {
|
|
61
|
+
void shutdown("SIGTERM");
|
|
62
|
+
});
|
|
63
|
+
}
|
package/src/sqlite.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
|
|
3
|
+
import type { Queryable } from "@absurd-sqlite/sdk";
|
|
4
|
+
import type {
|
|
5
|
+
SQLiteBindParams,
|
|
6
|
+
SQLiteBindValue,
|
|
7
|
+
SQLiteRestBindParams,
|
|
8
|
+
} from "@absurd-sqlite/sdk";
|
|
9
|
+
|
|
10
|
+
export class BunSqliteConnection implements Queryable {
|
|
11
|
+
private readonly db: Database;
|
|
12
|
+
|
|
13
|
+
constructor(db: Database) {
|
|
14
|
+
this.db = db;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async query<R extends object = Record<string, any>>(
|
|
18
|
+
sql: string,
|
|
19
|
+
params?: SQLiteRestBindParams
|
|
20
|
+
): Promise<{ rows: R[] }> {
|
|
21
|
+
const { sql: sqliteQuery, paramOrder } = rewritePostgresQuery(sql);
|
|
22
|
+
const sqliteParams = rewritePostgresParams(
|
|
23
|
+
normalizeParams(params),
|
|
24
|
+
paramOrder
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const statement = this.db.query(sqliteQuery);
|
|
28
|
+
const rows = statement.all(...sqliteParams).map((row) =>
|
|
29
|
+
decodeRowValues(row as Record<string, unknown>)
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return { rows: rows as R[] };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async exec(sql: string, params?: SQLiteRestBindParams): Promise<void> {
|
|
36
|
+
const { sql: sqliteQuery, paramOrder } = rewritePostgresQuery(sql);
|
|
37
|
+
const sqliteParams = rewritePostgresParams(
|
|
38
|
+
normalizeParams(params),
|
|
39
|
+
paramOrder
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
this.db.query(sqliteQuery).run(...sqliteParams);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function rewritePostgresQuery(text: string): {
|
|
47
|
+
sql: string;
|
|
48
|
+
paramOrder: number[];
|
|
49
|
+
} {
|
|
50
|
+
const paramOrder: number[] = [];
|
|
51
|
+
const sql = text
|
|
52
|
+
.replace(/\$(\d+)/g, (_, index) => {
|
|
53
|
+
paramOrder.push(Number(index));
|
|
54
|
+
return "?";
|
|
55
|
+
})
|
|
56
|
+
.replace(/absurd\.(\w+)/g, "absurd_$1");
|
|
57
|
+
|
|
58
|
+
return { sql, paramOrder };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function rewritePostgresParams<I = any>(
|
|
62
|
+
params: SQLiteBindValue[],
|
|
63
|
+
paramOrder: number[]
|
|
64
|
+
): I[] {
|
|
65
|
+
if (paramOrder.length === 0) {
|
|
66
|
+
return params.map((value) => encodeColumnValue(value)) as I[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return paramOrder.map((index) => {
|
|
70
|
+
const value = params[index - 1];
|
|
71
|
+
return encodeColumnValue(value) as I;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function decodeRowValues<R extends object = any>(
|
|
76
|
+
row: Record<string, unknown>
|
|
77
|
+
): R {
|
|
78
|
+
const decodedRow: any = {};
|
|
79
|
+
for (const [columnName, rawValue] of Object.entries(row)) {
|
|
80
|
+
decodedRow[columnName] = decodeColumnValue(rawValue, columnName);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return decodedRow as R;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function decodeColumnValue<V = any>(
|
|
87
|
+
value: unknown | V,
|
|
88
|
+
columnName: string
|
|
89
|
+
): V | null {
|
|
90
|
+
if (value === null || value === undefined) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (isTimestampColumn(columnName)) {
|
|
95
|
+
if (typeof value === "number") {
|
|
96
|
+
return new Date(value) as V;
|
|
97
|
+
}
|
|
98
|
+
if (typeof value === "string") {
|
|
99
|
+
const parsed = Date.parse(value);
|
|
100
|
+
if (!Number.isNaN(parsed)) {
|
|
101
|
+
return new Date(parsed) as V;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (typeof value === "string") {
|
|
107
|
+
return tryDecodeJson(value) ?? (value as V);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
|
|
111
|
+
const bytes =
|
|
112
|
+
value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
113
|
+
const decoded = new TextDecoder().decode(bytes);
|
|
114
|
+
return tryDecodeJson(decoded) ?? (value as V);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return value as V;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function tryDecodeJson<V = any>(value: string): V | null {
|
|
121
|
+
try {
|
|
122
|
+
return JSON.parse(value) as V;
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function encodeColumnValue(value: any): any {
|
|
129
|
+
if (value instanceof Date) {
|
|
130
|
+
return value.toISOString();
|
|
131
|
+
}
|
|
132
|
+
if (typeof value === "number" && Number.isInteger(value)) {
|
|
133
|
+
return value.toString();
|
|
134
|
+
}
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function isTimestampColumn(columnName: string): boolean {
|
|
139
|
+
return columnName.endsWith("_at");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function normalizeParams(
|
|
143
|
+
params?: SQLiteRestBindParams
|
|
144
|
+
): SQLiteBindValue[] {
|
|
145
|
+
if (!params) {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (params.length === 1 && isBindParams(params[0])) {
|
|
150
|
+
const inner = params[0];
|
|
151
|
+
if (Array.isArray(inner)) {
|
|
152
|
+
return inner;
|
|
153
|
+
}
|
|
154
|
+
return Object.values(inner);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return params as SQLiteBindValue[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function isBindParams(value: unknown): value is SQLiteBindParams {
|
|
161
|
+
if (Array.isArray(value)) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (!value || typeof value !== "object") {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
const tag = Object.prototype.toString.call(value);
|
|
168
|
+
return tag === "[object Object]";
|
|
169
|
+
}
|