@graphrefly/ts 0.0.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 +21 -0
- package/dist/adapters/index.cjs +9015 -0
- package/dist/adapters/index.cjs.map +1 -0
- package/dist/adapters/index.d.cts +678 -0
- package/dist/adapters/index.d.ts +678 -0
- package/dist/adapters/index.js +2894 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/observe-storage.cjs +260 -0
- package/dist/adapters/observe-storage.cjs.map +1 -0
- package/dist/adapters/observe-storage.d.cts +77 -0
- package/dist/adapters/observe-storage.d.ts +77 -0
- package/dist/adapters/observe-storage.js +161 -0
- package/dist/adapters/observe-storage.js.map +1 -0
- package/dist/append-log-DisvEReb.d.cts +189 -0
- package/dist/append-log-DzKMmjxx.d.ts +189 -0
- package/dist/chunk-2ILL7HQI.js +1189 -0
- package/dist/chunk-2ILL7HQI.js.map +1 -0
- package/dist/chunk-4VLAQHZI.js +330 -0
- package/dist/chunk-4VLAQHZI.js.map +1 -0
- package/dist/chunk-6PHB5CJS.js +229 -0
- package/dist/chunk-6PHB5CJS.js.map +1 -0
- package/dist/chunk-COHO25CZ.js +2449 -0
- package/dist/chunk-COHO25CZ.js.map +1 -0
- package/dist/chunk-D6BG7U6A.js +161 -0
- package/dist/chunk-D6BG7U6A.js.map +1 -0
- package/dist/chunk-DJC4CHLQ.js +818 -0
- package/dist/chunk-DJC4CHLQ.js.map +1 -0
- package/dist/chunk-DK554R7P.js +67 -0
- package/dist/chunk-DK554R7P.js.map +1 -0
- package/dist/chunk-DKP56CSW.js +322 -0
- package/dist/chunk-DKP56CSW.js.map +1 -0
- package/dist/chunk-G4M3NHRJ.js +688 -0
- package/dist/chunk-G4M3NHRJ.js.map +1 -0
- package/dist/chunk-GAJW5I5P.js +1 -0
- package/dist/chunk-GAJW5I5P.js.map +1 -0
- package/dist/chunk-GDL26N2T.js +282 -0
- package/dist/chunk-GDL26N2T.js.map +1 -0
- package/dist/chunk-GTPCOEOZ.js +741 -0
- package/dist/chunk-GTPCOEOZ.js.map +1 -0
- package/dist/chunk-H2HTHFVN.js +1 -0
- package/dist/chunk-H2HTHFVN.js.map +1 -0
- package/dist/chunk-HDRL4VQQ.js +218 -0
- package/dist/chunk-HDRL4VQQ.js.map +1 -0
- package/dist/chunk-I3IHOHCJ.js +2267 -0
- package/dist/chunk-I3IHOHCJ.js.map +1 -0
- package/dist/chunk-JIMUDQN3.js +965 -0
- package/dist/chunk-JIMUDQN3.js.map +1 -0
- package/dist/chunk-JR4IKCR2.js +462 -0
- package/dist/chunk-JR4IKCR2.js.map +1 -0
- package/dist/chunk-K3FXTC3I.js +165 -0
- package/dist/chunk-K3FXTC3I.js.map +1 -0
- package/dist/chunk-OOEN33FB.js +65 -0
- package/dist/chunk-OOEN33FB.js.map +1 -0
- package/dist/chunk-PKVBHGBM.js +554 -0
- package/dist/chunk-PKVBHGBM.js.map +1 -0
- package/dist/chunk-RIIOUTGM.js +1857 -0
- package/dist/chunk-RIIOUTGM.js.map +1 -0
- package/dist/chunk-SCRFRCGR.js +33 -0
- package/dist/chunk-SCRFRCGR.js.map +1 -0
- package/dist/chunk-SWTLEQL6.js +53 -0
- package/dist/chunk-SWTLEQL6.js.map +1 -0
- package/dist/chunk-SZAETNNA.js +1 -0
- package/dist/chunk-SZAETNNA.js.map +1 -0
- package/dist/chunk-TEW47IVR.js +49 -0
- package/dist/chunk-TEW47IVR.js.map +1 -0
- package/dist/chunk-Y3ZLRGHC.js +1482 -0
- package/dist/chunk-Y3ZLRGHC.js.map +1 -0
- package/dist/chunk-Z2ANQ6JW.js +149 -0
- package/dist/chunk-Z2ANQ6JW.js.map +1 -0
- package/dist/codec-BB7p8fJc.d.cts +38 -0
- package/dist/codec-BB7p8fJc.d.ts +38 -0
- package/dist/composition/index.cjs +2505 -0
- package/dist/composition/index.cjs.map +1 -0
- package/dist/composition/index.d.cts +95 -0
- package/dist/composition/index.d.ts +95 -0
- package/dist/composition/index.js +19 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/core/index.cjs +2475 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +25 -0
- package/dist/core/index.d.ts +25 -0
- package/dist/core/index.js +74 -0
- package/dist/core/index.js.map +1 -0
- package/dist/cqrs/index.cjs +595 -0
- package/dist/cqrs/index.cjs.map +1 -0
- package/dist/cqrs/index.d.cts +200 -0
- package/dist/cqrs/index.d.ts +200 -0
- package/dist/cqrs/index.js +557 -0
- package/dist/cqrs/index.js.map +1 -0
- package/dist/data-structures/index.cjs +4277 -0
- package/dist/data-structures/index.cjs.map +1 -0
- package/dist/data-structures/index.d.cts +22 -0
- package/dist/data-structures/index.d.ts +22 -0
- package/dist/data-structures/index.js +31 -0
- package/dist/data-structures/index.js.map +1 -0
- package/dist/describe-BZb7AS2y.d.ts +57 -0
- package/dist/describe-Ciu8SUnN.d.cts +57 -0
- package/dist/graph/index.cjs +7832 -0
- package/dist/graph/index.cjs.map +1 -0
- package/dist/graph/index.d.cts +251 -0
- package/dist/graph/index.d.ts +251 -0
- package/dist/graph/index.js +131 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph-DfdF9zy4.d.ts +666 -0
- package/dist/graph-s23RbbFO.d.cts +666 -0
- package/dist/index-CAEmLCYF.d.cts +166 -0
- package/dist/index-SnzZu3x7.d.ts +166 -0
- package/dist/index.cjs +15409 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +582 -0
- package/dist/index.js.map +1 -0
- package/dist/messages-BZqrGGm1.d.cts +55 -0
- package/dist/messages-BZqrGGm1.d.ts +55 -0
- package/dist/messaging/index.cjs +818 -0
- package/dist/messaging/index.cjs.map +1 -0
- package/dist/messaging/index.d.cts +235 -0
- package/dist/messaging/index.d.ts +235 -0
- package/dist/messaging/index.js +767 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/observe-event-log-0SVsx7JG.d.cts +88 -0
- package/dist/observe-event-log-Dnm76owp.d.ts +88 -0
- package/dist/operators/index.cjs +3774 -0
- package/dist/operators/index.cjs.map +1 -0
- package/dist/operators/index.d.cts +308 -0
- package/dist/operators/index.d.ts +308 -0
- package/dist/operators/index.js +112 -0
- package/dist/operators/index.js.map +1 -0
- package/dist/orchestration/index.cjs +3541 -0
- package/dist/orchestration/index.cjs.map +1 -0
- package/dist/orchestration/index.d.cts +302 -0
- package/dist/orchestration/index.d.ts +302 -0
- package/dist/orchestration/index.js +1004 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/patterns/index.cjs +1045 -0
- package/dist/patterns/index.cjs.map +1 -0
- package/dist/patterns/index.d.cts +39 -0
- package/dist/patterns/index.d.ts +39 -0
- package/dist/patterns/index.js +33 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/reactive-collection-BxBqtIOE.d.cts +344 -0
- package/dist/reactive-collection-Cb1II1Fi.d.ts +344 -0
- package/dist/reactive-collection-storage-BNiEc-Gd.d.ts +217 -0
- package/dist/reactive-collection-storage-D-KmjE0J.d.cts +217 -0
- package/dist/reactive-map-BcB4KsQR.d.ts +256 -0
- package/dist/reactive-map-D-g3dv8I.d.cts +256 -0
- package/dist/read-through-B1CYPfq_.d.cts +82 -0
- package/dist/read-through-DwyJhGs1.d.ts +82 -0
- package/dist/render/index.cjs +250 -0
- package/dist/render/index.cjs.map +1 -0
- package/dist/render/index.d.cts +58 -0
- package/dist/render/index.d.ts +58 -0
- package/dist/render/index.js +20 -0
- package/dist/render/index.js.map +1 -0
- package/dist/resilience-Dig3Q7n0.d.cts +45 -0
- package/dist/resilience-Dig3Q7n0.d.ts +45 -0
- package/dist/semantic-memory-graph-BYoIlP35.d.cts +356 -0
- package/dist/semantic-memory-graph-CxyXLms3.d.ts +356 -0
- package/dist/solutions/index.cjs +3249 -0
- package/dist/solutions/index.cjs.map +1 -0
- package/dist/solutions/index.d.cts +520 -0
- package/dist/solutions/index.d.ts +520 -0
- package/dist/solutions/index.js +31 -0
- package/dist/solutions/index.js.map +1 -0
- package/dist/sources/browser.cjs +3095 -0
- package/dist/sources/browser.cjs.map +1 -0
- package/dist/sources/browser.d.cts +39 -0
- package/dist/sources/browser.d.ts +39 -0
- package/dist/sources/browser.js +137 -0
- package/dist/sources/browser.js.map +1 -0
- package/dist/sources/index.cjs +3021 -0
- package/dist/sources/index.cjs.map +1 -0
- package/dist/sources/index.d.cts +7 -0
- package/dist/sources/index.d.ts +7 -0
- package/dist/sources/index.js +63 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/node.cjs +675 -0
- package/dist/sources/node.cjs.map +1 -0
- package/dist/sources/node.d.cts +109 -0
- package/dist/sources/node.d.ts +109 -0
- package/dist/sources/node.js +639 -0
- package/dist/sources/node.js.map +1 -0
- package/dist/storage/browser.cjs +777 -0
- package/dist/storage/browser.cjs.map +1 -0
- package/dist/storage/browser.d.cts +40 -0
- package/dist/storage/browser.d.ts +40 -0
- package/dist/storage/browser.js +275 -0
- package/dist/storage/browser.js.map +1 -0
- package/dist/storage/index.cjs +1989 -0
- package/dist/storage/index.cjs.map +1 -0
- package/dist/storage/index.d.cts +92 -0
- package/dist/storage/index.d.ts +92 -0
- package/dist/storage/index.js +161 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/node.cjs +898 -0
- package/dist/storage/node.cjs.map +1 -0
- package/dist/storage/node.d.cts +66 -0
- package/dist/storage/node.d.ts +66 -0
- package/dist/storage/node.js +402 -0
- package/dist/storage/node.js.map +1 -0
- package/dist/testing/index.cjs +95 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +20 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-bNMSWKqF.d.cts +732 -0
- package/dist/types-h12mNYbq.d.ts +732 -0
- package/package.json +250 -0
|
@@ -0,0 +1,898 @@
|
|
|
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/storage/node.ts
|
|
21
|
+
var node_exports = {};
|
|
22
|
+
__export(node_exports, {
|
|
23
|
+
fileAppendLog: () => fileAppendLog,
|
|
24
|
+
fileBackend: () => fileBackend,
|
|
25
|
+
fileKv: () => fileKv,
|
|
26
|
+
sqliteAppendLog: () => sqliteAppendLog,
|
|
27
|
+
sqliteBackend: () => sqliteBackend,
|
|
28
|
+
sqliteKv: () => sqliteKv
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(node_exports);
|
|
31
|
+
var import_node_crypto = require("crypto");
|
|
32
|
+
var import_node_fs = require("fs");
|
|
33
|
+
var import_node_module = require("module");
|
|
34
|
+
var import_node_path = require("path");
|
|
35
|
+
|
|
36
|
+
// src/storage/backend.ts
|
|
37
|
+
var HEX_TABLE = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
38
|
+
function hasStoragePutIfAbsent(backend) {
|
|
39
|
+
return typeof backend.putIfAbsent === "function";
|
|
40
|
+
}
|
|
41
|
+
function hasStorageVersioned(backend) {
|
|
42
|
+
return typeof backend.getVersioned === "function" && typeof backend.setIfMatch === "function";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/json/codec.ts
|
|
46
|
+
var JS_MIN_NORMAL_NUMBER = 2 ** -1022;
|
|
47
|
+
function assertStableJsonNumber(value, path) {
|
|
48
|
+
if (!Number.isFinite(value)) {
|
|
49
|
+
throw new TypeError(`stableJsonString: non-finite number at ${path}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function assertStrictJsonNumber(value, path) {
|
|
53
|
+
assertStableJsonNumber(value, path);
|
|
54
|
+
if (Object.is(value, -0)) {
|
|
55
|
+
throw new TypeError(`stableJsonString: non-canonical number at ${path}`);
|
|
56
|
+
}
|
|
57
|
+
const abs = Math.abs(value);
|
|
58
|
+
if (abs > 0 && abs < JS_MIN_NORMAL_NUMBER) {
|
|
59
|
+
throw new TypeError(`stableJsonString: subnormal number at ${path}`);
|
|
60
|
+
}
|
|
61
|
+
if (Number.isInteger(value) && !Number.isSafeInteger(value)) {
|
|
62
|
+
throw new TypeError(`stableJsonString: integer outside safe range at ${path}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function sortedJsonValue(value, seen = /* @__PURE__ */ new Set(), path = "$", strictNumbers = false) {
|
|
66
|
+
if (value === null) return null;
|
|
67
|
+
if (typeof value === "string" || typeof value === "boolean") return value;
|
|
68
|
+
if (typeof value === "number") {
|
|
69
|
+
if (strictNumbers) assertStrictJsonNumber(value, path);
|
|
70
|
+
else assertStableJsonNumber(value, path);
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
if (typeof value !== "object") {
|
|
74
|
+
throw new TypeError(`stableJsonString: value at ${path} is not JSON-encodable`);
|
|
75
|
+
}
|
|
76
|
+
if (seen.has(value)) throw new TypeError(`stableJsonString: circular reference at ${path}`);
|
|
77
|
+
const proto = Object.getPrototypeOf(value);
|
|
78
|
+
if (!Array.isArray(value) && proto !== Object.prototype && proto !== null) {
|
|
79
|
+
throw new TypeError(`stableJsonString: non-plain object at ${path}`);
|
|
80
|
+
}
|
|
81
|
+
seen.add(value);
|
|
82
|
+
try {
|
|
83
|
+
if (Array.isArray(value)) {
|
|
84
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
85
|
+
throw new TypeError(`stableJsonString: symbol-keyed properties at ${path}`);
|
|
86
|
+
}
|
|
87
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
88
|
+
const isIndex = /^(0|[1-9]\d*)$/.test(key) && Number.isSafeInteger(Number(key)) && Number(key) < value.length;
|
|
89
|
+
if (key !== "length" && !isIndex) {
|
|
90
|
+
throw new TypeError(`stableJsonString: non-index array property at ${path}.${key}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const out2 = [];
|
|
94
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
95
|
+
if (!(i in value)) {
|
|
96
|
+
throw new TypeError(`stableJsonString: sparse array hole at ${path}[${i}]`);
|
|
97
|
+
}
|
|
98
|
+
out2.push(sortedJsonValue(value[i], seen, `${path}[${i}]`, strictNumbers));
|
|
99
|
+
}
|
|
100
|
+
return out2;
|
|
101
|
+
}
|
|
102
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
103
|
+
throw new TypeError(`stableJsonString: symbol-keyed properties at ${path}`);
|
|
104
|
+
}
|
|
105
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
106
|
+
for (const key of Object.keys(value).sort()) {
|
|
107
|
+
out[key] = sortedJsonValue(
|
|
108
|
+
value[key],
|
|
109
|
+
seen,
|
|
110
|
+
`${path}.${key}`,
|
|
111
|
+
strictNumbers
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
} finally {
|
|
116
|
+
seen.delete(value);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function stableJsonString(value) {
|
|
120
|
+
return JSON.stringify(sortedJsonValue(value));
|
|
121
|
+
}
|
|
122
|
+
function strictStableJsonString(value) {
|
|
123
|
+
return JSON.stringify(sortedJsonValue(value, /* @__PURE__ */ new Set(), "$", true));
|
|
124
|
+
}
|
|
125
|
+
function jsonCodecFor() {
|
|
126
|
+
const encoder2 = new TextEncoder();
|
|
127
|
+
const decoder2 = new TextDecoder();
|
|
128
|
+
return {
|
|
129
|
+
encode(value) {
|
|
130
|
+
return encoder2.encode(stableJsonString(value));
|
|
131
|
+
},
|
|
132
|
+
decode(bytes) {
|
|
133
|
+
return JSON.parse(decoder2.decode(bytes));
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
var jsonCodec = jsonCodecFor();
|
|
138
|
+
function bytesEqual(a, b) {
|
|
139
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
140
|
+
for (let i = 0; i < a.byteLength; i += 1) {
|
|
141
|
+
if (a[i] !== b[i]) return false;
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
function hasUnpairedSurrogate(value) {
|
|
146
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
147
|
+
const code = value.charCodeAt(i);
|
|
148
|
+
if (code >= 55296 && code <= 56319) {
|
|
149
|
+
const next = value.charCodeAt(i + 1);
|
|
150
|
+
if (next >= 56320 && next <= 57343) {
|
|
151
|
+
i += 1;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
if (code >= 56320 && code <= 57343) return true;
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
function assertNoUnpairedSurrogates(value, seen = /* @__PURE__ */ new Set(), path = "$") {
|
|
161
|
+
if (typeof value === "string") {
|
|
162
|
+
if (hasUnpairedSurrogate(value)) {
|
|
163
|
+
throw new TypeError(`strictJsonCodec: unpaired surrogate at ${path}`);
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (value === null || typeof value !== "object") return;
|
|
168
|
+
if (seen.has(value)) return;
|
|
169
|
+
seen.add(value);
|
|
170
|
+
try {
|
|
171
|
+
if (Array.isArray(value)) {
|
|
172
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
173
|
+
assertNoUnpairedSurrogates(value[i], seen, `${path}[${i}]`);
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
for (const key of Object.keys(value)) {
|
|
178
|
+
if (hasUnpairedSurrogate(key)) {
|
|
179
|
+
throw new TypeError(`strictJsonCodec: unpaired surrogate at ${path}.${key}`);
|
|
180
|
+
}
|
|
181
|
+
assertNoUnpairedSurrogates(value[key], seen, `${path}.${key}`);
|
|
182
|
+
}
|
|
183
|
+
} finally {
|
|
184
|
+
seen.delete(value);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function assertNoDuplicateJsonObjectKeys(text) {
|
|
188
|
+
let index = 0;
|
|
189
|
+
function fail(message) {
|
|
190
|
+
throw new TypeError(`strictJsonCodec: ${message}`);
|
|
191
|
+
}
|
|
192
|
+
function skipWhitespace() {
|
|
193
|
+
while (/\s/.test(text[index] ?? "")) index += 1;
|
|
194
|
+
}
|
|
195
|
+
function readJsonString() {
|
|
196
|
+
const start = index;
|
|
197
|
+
index += 1;
|
|
198
|
+
while (index < text.length) {
|
|
199
|
+
const ch = text[index];
|
|
200
|
+
if (ch === '"') {
|
|
201
|
+
index += 1;
|
|
202
|
+
try {
|
|
203
|
+
return JSON.parse(text.slice(start, index));
|
|
204
|
+
} catch {
|
|
205
|
+
fail("malformed JSON string");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (ch === "\\") {
|
|
209
|
+
index += 2;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
index += 1;
|
|
213
|
+
}
|
|
214
|
+
fail("unterminated JSON string");
|
|
215
|
+
}
|
|
216
|
+
function consumeLiteral(literal) {
|
|
217
|
+
if (text.slice(index, index + literal.length) !== literal) {
|
|
218
|
+
fail(`malformed JSON near byte ${index}`);
|
|
219
|
+
}
|
|
220
|
+
index += literal.length;
|
|
221
|
+
}
|
|
222
|
+
function consumeNumber() {
|
|
223
|
+
const match = /^-?(0|[1-9]\d*)(\.\d+)?([eE][+-]?\d+)?/.exec(text.slice(index));
|
|
224
|
+
if (!match) fail(`malformed JSON number near byte ${index}`);
|
|
225
|
+
index += match[0].length;
|
|
226
|
+
}
|
|
227
|
+
function parseValue(path) {
|
|
228
|
+
skipWhitespace();
|
|
229
|
+
const ch = text[index];
|
|
230
|
+
if (ch === "{") {
|
|
231
|
+
parseObject(path);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (ch === "[") {
|
|
235
|
+
parseArray(path);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (ch === '"') {
|
|
239
|
+
readJsonString();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (ch === "t") {
|
|
243
|
+
consumeLiteral("true");
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (ch === "f") {
|
|
247
|
+
consumeLiteral("false");
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (ch === "n") {
|
|
251
|
+
consumeLiteral("null");
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (ch === "-" || ch !== void 0 && ch >= "0" && ch <= "9") {
|
|
255
|
+
consumeNumber();
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
fail(`malformed JSON near byte ${index}`);
|
|
259
|
+
}
|
|
260
|
+
function parseObject(path) {
|
|
261
|
+
const keys = /* @__PURE__ */ new Set();
|
|
262
|
+
index += 1;
|
|
263
|
+
skipWhitespace();
|
|
264
|
+
if (text[index] === "}") {
|
|
265
|
+
index += 1;
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
while (index < text.length) {
|
|
269
|
+
skipWhitespace();
|
|
270
|
+
if (text[index] !== '"') fail(`expected object key near byte ${index}`);
|
|
271
|
+
const key = readJsonString();
|
|
272
|
+
if (keys.has(key)) {
|
|
273
|
+
throw new TypeError(
|
|
274
|
+
`strictJsonCodec: duplicate object key ${JSON.stringify(key)} at ${path}`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
keys.add(key);
|
|
278
|
+
skipWhitespace();
|
|
279
|
+
if (text[index] !== ":") fail(`expected ':' after object key near byte ${index}`);
|
|
280
|
+
index += 1;
|
|
281
|
+
parseValue(`${path}.${key}`);
|
|
282
|
+
skipWhitespace();
|
|
283
|
+
if (text[index] === ",") {
|
|
284
|
+
index += 1;
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (text[index] === "}") {
|
|
288
|
+
index += 1;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
fail(`expected ',' or '}' near byte ${index}`);
|
|
292
|
+
}
|
|
293
|
+
fail("unterminated JSON object");
|
|
294
|
+
}
|
|
295
|
+
function parseArray(path) {
|
|
296
|
+
index += 1;
|
|
297
|
+
skipWhitespace();
|
|
298
|
+
if (text[index] === "]") {
|
|
299
|
+
index += 1;
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
let item = 0;
|
|
303
|
+
while (index < text.length) {
|
|
304
|
+
parseValue(`${path}[${item}]`);
|
|
305
|
+
item += 1;
|
|
306
|
+
skipWhitespace();
|
|
307
|
+
if (text[index] === ",") {
|
|
308
|
+
index += 1;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (text[index] === "]") {
|
|
312
|
+
index += 1;
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
fail(`expected ',' or ']' near byte ${index}`);
|
|
316
|
+
}
|
|
317
|
+
fail("unterminated JSON array");
|
|
318
|
+
}
|
|
319
|
+
parseValue("$");
|
|
320
|
+
skipWhitespace();
|
|
321
|
+
if (index !== text.length) fail(`trailing JSON token near byte ${index}`);
|
|
322
|
+
}
|
|
323
|
+
function strictJsonCodecFor() {
|
|
324
|
+
const encoder2 = new TextEncoder();
|
|
325
|
+
const decoder2 = new TextDecoder("utf-8", { fatal: true });
|
|
326
|
+
return {
|
|
327
|
+
encode(value) {
|
|
328
|
+
assertNoUnpairedSurrogates(value);
|
|
329
|
+
return encoder2.encode(strictStableJsonString(value));
|
|
330
|
+
},
|
|
331
|
+
decode(bytes) {
|
|
332
|
+
const text = decoder2.decode(bytes);
|
|
333
|
+
assertNoDuplicateJsonObjectKeys(text);
|
|
334
|
+
const decoded = JSON.parse(text);
|
|
335
|
+
assertNoUnpairedSurrogates(decoded);
|
|
336
|
+
const canonical = encoder2.encode(strictStableJsonString(decoded));
|
|
337
|
+
if (!bytesEqual(bytes, canonical)) {
|
|
338
|
+
throw new TypeError("strictJsonCodec: bytes are not canonical stable JSON");
|
|
339
|
+
}
|
|
340
|
+
return decoded;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
var strictJsonCodec = strictJsonCodecFor();
|
|
345
|
+
|
|
346
|
+
// src/storage/kv.ts
|
|
347
|
+
function defer(fn) {
|
|
348
|
+
return Promise.resolve().then(fn);
|
|
349
|
+
}
|
|
350
|
+
function kvStorage(opts) {
|
|
351
|
+
const codec = opts.codec ?? jsonCodecFor();
|
|
352
|
+
const { backend } = opts;
|
|
353
|
+
const tier = {
|
|
354
|
+
get(key) {
|
|
355
|
+
return defer(() => backend.get(key)).then(
|
|
356
|
+
(bytes) => bytes === void 0 ? void 0 : codec.decode(bytes)
|
|
357
|
+
);
|
|
358
|
+
},
|
|
359
|
+
set(key, value) {
|
|
360
|
+
return defer(() => backend.put(key, codec.encode(value))).then(() => void 0);
|
|
361
|
+
},
|
|
362
|
+
delete(key) {
|
|
363
|
+
return defer(() => backend.delete?.(key)).then(() => void 0);
|
|
364
|
+
},
|
|
365
|
+
list(prefix = "") {
|
|
366
|
+
return defer(() => {
|
|
367
|
+
if (!backend.list) throw new Error("kvStorage.list: backend does not support listing");
|
|
368
|
+
return backend.list(prefix);
|
|
369
|
+
}).then((keys) => [...keys].sort());
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
let out = tier;
|
|
373
|
+
if (hasStoragePutIfAbsent(backend)) {
|
|
374
|
+
out = {
|
|
375
|
+
...out,
|
|
376
|
+
putIfAbsent(key, value) {
|
|
377
|
+
return defer(() => backend.putIfAbsent(key, codec.encode(value)));
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (hasStorageVersioned(backend)) {
|
|
382
|
+
out = {
|
|
383
|
+
...out,
|
|
384
|
+
getVersioned(key) {
|
|
385
|
+
return defer(() => backend.getVersioned(key)).then((result) => {
|
|
386
|
+
if (result.kind === "miss") return { kind: "miss", generation: result.generation };
|
|
387
|
+
return {
|
|
388
|
+
kind: "hit",
|
|
389
|
+
value: codec.decode(result.value),
|
|
390
|
+
generation: result.generation
|
|
391
|
+
};
|
|
392
|
+
});
|
|
393
|
+
},
|
|
394
|
+
setIfMatch(key, value, generation) {
|
|
395
|
+
return defer(() => backend.setIfMatch(key, codec.encode(value), generation));
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
return out;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// src/storage/append-log.ts
|
|
403
|
+
var APPEND_LOG_SEQ_PAD = 20;
|
|
404
|
+
function appendLogKey(prefix, seq) {
|
|
405
|
+
if (!Number.isSafeInteger(seq) || seq < 0) {
|
|
406
|
+
throw new RangeError(`appendLogKey: seq must be a non-negative safe integer, got ${seq}`);
|
|
407
|
+
}
|
|
408
|
+
return `${prefix}/${seq.toString().padStart(APPEND_LOG_SEQ_PAD, "0")}`;
|
|
409
|
+
}
|
|
410
|
+
function seqFromKey(prefix, key) {
|
|
411
|
+
const head = `${prefix}/`;
|
|
412
|
+
if (!key.startsWith(head)) throw new Error(`append log key outside prefix: ${key}`);
|
|
413
|
+
const raw = key.slice(head.length);
|
|
414
|
+
if (!/^\d+$/.test(raw)) {
|
|
415
|
+
throw new Error(`append log key has a non-numeric sequence: ${key}`);
|
|
416
|
+
}
|
|
417
|
+
if (raw.length !== APPEND_LOG_SEQ_PAD) {
|
|
418
|
+
throw new Error(`append log key sequence must be ${APPEND_LOG_SEQ_PAD} padded digits: ${key}`);
|
|
419
|
+
}
|
|
420
|
+
const seq = Number(raw);
|
|
421
|
+
if (!Number.isSafeInteger(seq)) {
|
|
422
|
+
throw new Error(`append log key sequence is outside the safe integer range: ${key}`);
|
|
423
|
+
}
|
|
424
|
+
return seq;
|
|
425
|
+
}
|
|
426
|
+
function nextSeqFromKeys(prefix, keys) {
|
|
427
|
+
if (keys.length === 0) return 0;
|
|
428
|
+
const next = Math.max(...keys.map((key) => seqFromKey(prefix, key))) + 1;
|
|
429
|
+
if (!Number.isSafeInteger(next)) {
|
|
430
|
+
throw new RangeError(`append log next sequence is outside the safe integer range: ${prefix}`);
|
|
431
|
+
}
|
|
432
|
+
return next;
|
|
433
|
+
}
|
|
434
|
+
function sizeFromKeys(prefix, keys) {
|
|
435
|
+
for (const key of keys) seqFromKey(prefix, key);
|
|
436
|
+
return keys.length;
|
|
437
|
+
}
|
|
438
|
+
function validateReadOptions(opts) {
|
|
439
|
+
const after = opts.after ?? -1;
|
|
440
|
+
const limit = opts.limit ?? Number.POSITIVE_INFINITY;
|
|
441
|
+
if (!Number.isSafeInteger(after) || after < -1) {
|
|
442
|
+
throw new RangeError(
|
|
443
|
+
`appendLogStorage.read: after must be an integer cursor >= -1, got ${after}`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
if (limit !== Number.POSITIVE_INFINITY && (!Number.isSafeInteger(limit) || limit < 0)) {
|
|
447
|
+
throw new RangeError(
|
|
448
|
+
`appendLogStorage.read: limit must be a non-negative safe integer or Infinity, got ${limit}`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
return { after, limit };
|
|
452
|
+
}
|
|
453
|
+
function readAppendLogEntries(kv, prefix, opts) {
|
|
454
|
+
const { after, limit } = validateReadOptions(opts);
|
|
455
|
+
return kv.list(`${prefix}/`).then((listed) => {
|
|
456
|
+
const keys = listed.map((key) => ({ key, seq: seqFromKey(prefix, key) })).filter(({ seq }) => seq > after).sort((a, b) => a.seq - b.seq).slice(0, limit);
|
|
457
|
+
return Promise.all(
|
|
458
|
+
keys.map(
|
|
459
|
+
({ key, seq }) => kv.get(key).then((value) => {
|
|
460
|
+
if (value === void 0) {
|
|
461
|
+
throw new Error(`append log listed key is missing: ${key}`);
|
|
462
|
+
}
|
|
463
|
+
return { key, seq, value };
|
|
464
|
+
})
|
|
465
|
+
)
|
|
466
|
+
).then((entries) => {
|
|
467
|
+
const out = [];
|
|
468
|
+
for (const entry of entries) if (entry !== void 0) out.push(entry);
|
|
469
|
+
return out;
|
|
470
|
+
});
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
function deleteAppendLogEntriesAfter(kv, prefix, seq) {
|
|
474
|
+
return kv.list(`${prefix}/`).then(
|
|
475
|
+
(keys) => Promise.all(keys.filter((key) => seqFromKey(prefix, key) > seq).map((key) => kv.delete(key)))
|
|
476
|
+
).then(() => kv.list(`${prefix}/`)).then(() => void 0);
|
|
477
|
+
}
|
|
478
|
+
function appendLogStorage(opts) {
|
|
479
|
+
const { kv, prefix = "event-log" } = opts;
|
|
480
|
+
let tail = Promise.resolve();
|
|
481
|
+
function initNextSeq() {
|
|
482
|
+
return kv.list(`${prefix}/`).then((keys) => {
|
|
483
|
+
return nextSeqFromKeys(prefix, keys);
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
function enqueue(task) {
|
|
487
|
+
const run = tail.then(task, task);
|
|
488
|
+
tail = run.then(
|
|
489
|
+
() => void 0,
|
|
490
|
+
() => void 0
|
|
491
|
+
);
|
|
492
|
+
return run;
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
append(value) {
|
|
496
|
+
return enqueue(
|
|
497
|
+
() => initNextSeq().then((seq) => {
|
|
498
|
+
const key = appendLogKey(prefix, seq);
|
|
499
|
+
return kv.set(key, value).then(() => {
|
|
500
|
+
return { key, seq, value };
|
|
501
|
+
});
|
|
502
|
+
})
|
|
503
|
+
);
|
|
504
|
+
},
|
|
505
|
+
read(opts2 = {}) {
|
|
506
|
+
return enqueue(() => readAppendLogEntries(kv, prefix, opts2));
|
|
507
|
+
},
|
|
508
|
+
truncateAfter(seq) {
|
|
509
|
+
return enqueue(() => deleteAppendLogEntriesAfter(kv, prefix, seq));
|
|
510
|
+
},
|
|
511
|
+
size() {
|
|
512
|
+
return enqueue(() => kv.list(`${prefix}/`).then((keys) => sizeFromKeys(prefix, keys)));
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// src/storage/node.ts
|
|
518
|
+
var FILE_STEM_PREFIX = "k-";
|
|
519
|
+
var NAMESPACE_SEPARATOR = "\0";
|
|
520
|
+
var SQLITE_GENERATION = /* @__PURE__ */ Symbol("graphrefly.sqliteBackend.generation");
|
|
521
|
+
var encoder = new TextEncoder();
|
|
522
|
+
var decoder = new TextDecoder("utf-8", { fatal: true });
|
|
523
|
+
var require2 = (0, import_node_module.createRequire)("/graphrefly-storage-node.js");
|
|
524
|
+
function isErrno(error, code) {
|
|
525
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
526
|
+
}
|
|
527
|
+
function keyToStem(key) {
|
|
528
|
+
let out = "";
|
|
529
|
+
for (const ch of key) {
|
|
530
|
+
if (/^[a-zA-Z0-9_-]$/.test(ch)) {
|
|
531
|
+
out += ch;
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
for (const byte of encoder.encode(ch)) out += `%${byte.toString(16).padStart(2, "0")}`;
|
|
535
|
+
}
|
|
536
|
+
return out;
|
|
537
|
+
}
|
|
538
|
+
function stemToKey(stem) {
|
|
539
|
+
const bytes = [];
|
|
540
|
+
let i = 0;
|
|
541
|
+
while (i < stem.length) {
|
|
542
|
+
const ch = stem[i];
|
|
543
|
+
if (ch === "%" && i + 2 < stem.length) {
|
|
544
|
+
const hex = stem.slice(i + 1, i + 3);
|
|
545
|
+
if (/^[0-9a-f]{2}$/i.test(hex)) {
|
|
546
|
+
bytes.push(Number.parseInt(hex, 16));
|
|
547
|
+
i += 3;
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const code = ch.charCodeAt(0);
|
|
552
|
+
if (code > 127) return null;
|
|
553
|
+
bytes.push(code);
|
|
554
|
+
i += 1;
|
|
555
|
+
}
|
|
556
|
+
try {
|
|
557
|
+
return decoder.decode(new Uint8Array(bytes));
|
|
558
|
+
} catch {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
function validateExtension(extension) {
|
|
563
|
+
if (extension.length < 2 || !extension.startsWith(".") || extension.includes("..") || /[/\\\0]/.test(extension) || !/^[.A-Za-z0-9_-]+$/.test(extension)) {
|
|
564
|
+
throw new TypeError("fileBackend: extension must be a simple suffix such as .bin");
|
|
565
|
+
}
|
|
566
|
+
return extension;
|
|
567
|
+
}
|
|
568
|
+
function validateNamespace(label, namespace) {
|
|
569
|
+
if (typeof namespace !== "string") {
|
|
570
|
+
throw new TypeError(`${label}: namespace must be a string`);
|
|
571
|
+
}
|
|
572
|
+
if (namespace.includes(NAMESPACE_SEPARATOR)) {
|
|
573
|
+
throw new TypeError(`${label}: namespace must not contain U+0000`);
|
|
574
|
+
}
|
|
575
|
+
return namespace;
|
|
576
|
+
}
|
|
577
|
+
function validateLogicalKey(label, key) {
|
|
578
|
+
if (typeof key !== "string") {
|
|
579
|
+
throw new TypeError(`${label}: key must be a string`);
|
|
580
|
+
}
|
|
581
|
+
if (key.includes(NAMESPACE_SEPARATOR)) {
|
|
582
|
+
throw new TypeError(`${label}: key must not contain U+0000`);
|
|
583
|
+
}
|
|
584
|
+
return key;
|
|
585
|
+
}
|
|
586
|
+
function validateListPrefix(label, prefix) {
|
|
587
|
+
if (typeof prefix !== "string") {
|
|
588
|
+
throw new TypeError(`${label}: list prefix must be a string`);
|
|
589
|
+
}
|
|
590
|
+
if (prefix.includes(NAMESPACE_SEPARATOR)) {
|
|
591
|
+
throw new TypeError(`${label}: list prefix must not contain U+0000`);
|
|
592
|
+
}
|
|
593
|
+
return prefix;
|
|
594
|
+
}
|
|
595
|
+
function validateSqliteTableName(tableName) {
|
|
596
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) {
|
|
597
|
+
throw new TypeError("sqliteBackend: tableName must be a simple SQLite identifier");
|
|
598
|
+
}
|
|
599
|
+
return tableName;
|
|
600
|
+
}
|
|
601
|
+
function sqliteGeneration(storageId, key, rowGeneration, epoch) {
|
|
602
|
+
return Object.freeze({
|
|
603
|
+
[SQLITE_GENERATION]: Object.freeze([storageId, key, rowGeneration, epoch])
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
function readSqliteGeneration(generation) {
|
|
607
|
+
if (typeof generation !== "object" || generation === null) return void 0;
|
|
608
|
+
const maybe = generation;
|
|
609
|
+
const token = maybe[SQLITE_GENERATION];
|
|
610
|
+
if (Array.isArray(token) && token.length === 4 && typeof token[0] === "object" && token[0] !== null && typeof token[1] === "string" && (token[2] === null || typeof token[2] === "number") && typeof token[3] === "number") {
|
|
611
|
+
return token;
|
|
612
|
+
}
|
|
613
|
+
return void 0;
|
|
614
|
+
}
|
|
615
|
+
function sqliteChanges(result) {
|
|
616
|
+
return typeof result === "object" && result !== null && "changes" in result && typeof result.changes === "number" ? result.changes : 0;
|
|
617
|
+
}
|
|
618
|
+
function sqliteBytes(value) {
|
|
619
|
+
return Uint8Array.from(value instanceof Uint8Array ? value : new Uint8Array(value));
|
|
620
|
+
}
|
|
621
|
+
function loadSqliteDatabaseSync() {
|
|
622
|
+
try {
|
|
623
|
+
const DatabaseSync = require2("node:sqlite").DatabaseSync;
|
|
624
|
+
if (typeof DatabaseSync !== "function") {
|
|
625
|
+
throw new TypeError("DatabaseSync export is missing");
|
|
626
|
+
}
|
|
627
|
+
return DatabaseSync;
|
|
628
|
+
} catch (error) {
|
|
629
|
+
throw new Error("sqliteBackend: node:sqlite is not available in this Node runtime", {
|
|
630
|
+
cause: error
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function fileBackend(dir, opts = {}) {
|
|
635
|
+
const extension = validateExtension(opts.extension ?? ".bin");
|
|
636
|
+
const namespace = opts.namespace === void 0 ? "" : validateNamespace("fileBackend", opts.namespace);
|
|
637
|
+
const namespacePrefix = namespace.length > 0 ? `${namespace}${NAMESPACE_SEPARATOR}` : "";
|
|
638
|
+
const storageKey = (key) => `${namespacePrefix}${validateLogicalKey("fileBackend", key)}`;
|
|
639
|
+
const pathFor = (key) => (0, import_node_path.join)(dir, `${FILE_STEM_PREFIX}${keyToStem(storageKey(key))}${extension}`);
|
|
640
|
+
const keyFromFilename = (filename) => {
|
|
641
|
+
if (!filename.endsWith(extension)) return null;
|
|
642
|
+
const stem = filename.slice(0, -extension.length);
|
|
643
|
+
if (!stem.startsWith(FILE_STEM_PREFIX)) return null;
|
|
644
|
+
const key = stemToKey(stem.slice(FILE_STEM_PREFIX.length));
|
|
645
|
+
if (key === null || !key.startsWith(namespacePrefix)) return null;
|
|
646
|
+
const logical = key.slice(namespacePrefix.length);
|
|
647
|
+
if (logical.includes(NAMESPACE_SEPARATOR)) {
|
|
648
|
+
throw new TypeError("fileBackend: malformed stored key");
|
|
649
|
+
}
|
|
650
|
+
return logical;
|
|
651
|
+
};
|
|
652
|
+
return {
|
|
653
|
+
get(key) {
|
|
654
|
+
try {
|
|
655
|
+
return Uint8Array.from((0, import_node_fs.readFileSync)(pathFor(key)));
|
|
656
|
+
} catch (error) {
|
|
657
|
+
if (isErrno(error, "ENOENT")) return void 0;
|
|
658
|
+
throw error;
|
|
659
|
+
}
|
|
660
|
+
},
|
|
661
|
+
put(key, value) {
|
|
662
|
+
(0, import_node_fs.mkdirSync)(dir, { recursive: true });
|
|
663
|
+
const filePath = pathFor(key);
|
|
664
|
+
const base = (0, import_node_path.basename)(filePath);
|
|
665
|
+
const parent = (0, import_node_path.dirname)(filePath);
|
|
666
|
+
const tmp = (0, import_node_path.join)(parent, `.${base}.${(0, import_node_crypto.randomBytes)(8).toString("hex")}.tmp`);
|
|
667
|
+
try {
|
|
668
|
+
(0, import_node_fs.writeFileSync)(tmp, value);
|
|
669
|
+
(0, import_node_fs.renameSync)(tmp, filePath);
|
|
670
|
+
} catch (error) {
|
|
671
|
+
try {
|
|
672
|
+
(0, import_node_fs.unlinkSync)(tmp);
|
|
673
|
+
} catch {
|
|
674
|
+
}
|
|
675
|
+
throw error;
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
putIfAbsent(key, value) {
|
|
679
|
+
(0, import_node_fs.mkdirSync)(dir, { recursive: true });
|
|
680
|
+
const filePath = pathFor(key);
|
|
681
|
+
let fd;
|
|
682
|
+
try {
|
|
683
|
+
fd = (0, import_node_fs.openSync)(filePath, "wx");
|
|
684
|
+
(0, import_node_fs.writeFileSync)(fd, value);
|
|
685
|
+
return true;
|
|
686
|
+
} catch (error) {
|
|
687
|
+
if (isErrno(error, "EEXIST")) return false;
|
|
688
|
+
if (fd !== void 0) {
|
|
689
|
+
try {
|
|
690
|
+
(0, import_node_fs.unlinkSync)(filePath);
|
|
691
|
+
} catch {
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
throw error;
|
|
695
|
+
} finally {
|
|
696
|
+
if (fd !== void 0) (0, import_node_fs.closeSync)(fd);
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
delete(key) {
|
|
700
|
+
try {
|
|
701
|
+
(0, import_node_fs.unlinkSync)(pathFor(key));
|
|
702
|
+
} catch (error) {
|
|
703
|
+
if (!isErrno(error, "ENOENT")) throw error;
|
|
704
|
+
}
|
|
705
|
+
},
|
|
706
|
+
list(prefix = "") {
|
|
707
|
+
const validatedPrefix = validateListPrefix("fileBackend", prefix);
|
|
708
|
+
let entries;
|
|
709
|
+
try {
|
|
710
|
+
entries = (0, import_node_fs.readdirSync)(dir);
|
|
711
|
+
} catch (error) {
|
|
712
|
+
if (isErrno(error, "ENOENT")) return [];
|
|
713
|
+
throw error;
|
|
714
|
+
}
|
|
715
|
+
const keys = [];
|
|
716
|
+
for (const entry of entries) {
|
|
717
|
+
if (entry.startsWith(".")) continue;
|
|
718
|
+
const key = keyFromFilename(entry);
|
|
719
|
+
if (key?.startsWith(validatedPrefix)) keys.push(key);
|
|
720
|
+
}
|
|
721
|
+
return keys.sort();
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
function fileKv(dir, opts = {}) {
|
|
726
|
+
return kvStorage({
|
|
727
|
+
backend: fileBackend(dir, opts),
|
|
728
|
+
codec: opts.codec
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
function fileAppendLog(dir, opts = {}) {
|
|
732
|
+
return appendLogStorage({
|
|
733
|
+
kv: fileKv(dir, opts),
|
|
734
|
+
prefix: opts.prefix ?? "event-log"
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
function sqliteBackend(path, opts = {}) {
|
|
738
|
+
const table = validateSqliteTableName(opts.tableName ?? "graphrefly_storage");
|
|
739
|
+
const metaTable = validateSqliteTableName(`${table}_meta`);
|
|
740
|
+
const namespace = opts.namespace === void 0 ? "" : validateNamespace("sqliteBackend", opts.namespace);
|
|
741
|
+
const DatabaseSync = loadSqliteDatabaseSync();
|
|
742
|
+
const namespacePrefix = namespace.length > 0 ? `${namespace}${NAMESPACE_SEPARATOR}` : "";
|
|
743
|
+
const storageKey = (key) => `${namespacePrefix}${validateLogicalKey("sqliteBackend", key)}`;
|
|
744
|
+
const storageId = Object.freeze({});
|
|
745
|
+
const logicalKey = (key) => {
|
|
746
|
+
if (typeof key !== "string") {
|
|
747
|
+
throw new TypeError("sqliteBackend: stored key is corrupt");
|
|
748
|
+
}
|
|
749
|
+
if (!key.startsWith(namespacePrefix)) return void 0;
|
|
750
|
+
const logical = key.slice(namespacePrefix.length);
|
|
751
|
+
if (logical.includes(NAMESPACE_SEPARATOR)) {
|
|
752
|
+
throw new TypeError("sqliteBackend: malformed stored key");
|
|
753
|
+
}
|
|
754
|
+
return logical;
|
|
755
|
+
};
|
|
756
|
+
const db = new DatabaseSync(path);
|
|
757
|
+
db.exec(
|
|
758
|
+
`CREATE TABLE IF NOT EXISTS ${table} (k TEXT PRIMARY KEY, v BLOB NOT NULL, g INTEGER NOT NULL DEFAULT 0)`
|
|
759
|
+
);
|
|
760
|
+
const columns = db.prepare(`PRAGMA table_info(${table})`).all();
|
|
761
|
+
if (!columns.some((column) => column.name === "g")) {
|
|
762
|
+
db.exec(`ALTER TABLE ${table} ADD COLUMN g INTEGER NOT NULL DEFAULT 0`);
|
|
763
|
+
}
|
|
764
|
+
db.exec(`CREATE TABLE IF NOT EXISTS ${metaTable} (k TEXT PRIMARY KEY, v INTEGER NOT NULL)`);
|
|
765
|
+
db.exec(`
|
|
766
|
+
CREATE TRIGGER IF NOT EXISTS ${table}_generation_insert
|
|
767
|
+
AFTER INSERT ON ${table}
|
|
768
|
+
BEGIN
|
|
769
|
+
INSERT INTO ${metaTable} (k, v) VALUES (NEW.k, 1)
|
|
770
|
+
ON CONFLICT(k) DO UPDATE SET v = ${metaTable}.v + 1;
|
|
771
|
+
END
|
|
772
|
+
`);
|
|
773
|
+
db.exec(`
|
|
774
|
+
CREATE TRIGGER IF NOT EXISTS ${table}_generation_update
|
|
775
|
+
AFTER UPDATE ON ${table}
|
|
776
|
+
BEGIN
|
|
777
|
+
INSERT INTO ${metaTable} (k, v) VALUES (NEW.k, 1)
|
|
778
|
+
ON CONFLICT(k) DO UPDATE SET v = ${metaTable}.v + 1;
|
|
779
|
+
END
|
|
780
|
+
`);
|
|
781
|
+
db.exec(`
|
|
782
|
+
CREATE TRIGGER IF NOT EXISTS ${table}_generation_delete
|
|
783
|
+
AFTER DELETE ON ${table}
|
|
784
|
+
BEGIN
|
|
785
|
+
INSERT INTO ${metaTable} (k, v) VALUES (OLD.k, 1)
|
|
786
|
+
ON CONFLICT(k) DO UPDATE SET v = ${metaTable}.v + 1;
|
|
787
|
+
END
|
|
788
|
+
`);
|
|
789
|
+
const keyEpoch = (key) => {
|
|
790
|
+
const row = db.prepare(`SELECT v FROM ${metaTable} WHERE k = ?`).get(key);
|
|
791
|
+
const value = row?.v ?? 0;
|
|
792
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
793
|
+
throw new Error("sqliteBackend: per-key generation epoch is corrupt");
|
|
794
|
+
}
|
|
795
|
+
return value;
|
|
796
|
+
};
|
|
797
|
+
const readRow = (key) => {
|
|
798
|
+
const row = db.prepare(`SELECT v, g FROM ${table} WHERE k = ?`).get(storageKey(key));
|
|
799
|
+
if (row?.v === void 0) return void 0;
|
|
800
|
+
const generation = row.g;
|
|
801
|
+
if (typeof generation !== "number" || !Number.isSafeInteger(generation) || generation < 0) {
|
|
802
|
+
throw new Error("sqliteBackend: row generation is corrupt");
|
|
803
|
+
}
|
|
804
|
+
return { value: sqliteBytes(row.v), generation };
|
|
805
|
+
};
|
|
806
|
+
return {
|
|
807
|
+
name: `sqlite:${path}/${table}`,
|
|
808
|
+
get(key) {
|
|
809
|
+
return readRow(key)?.value;
|
|
810
|
+
},
|
|
811
|
+
put(key, value) {
|
|
812
|
+
db.prepare(
|
|
813
|
+
`INSERT INTO ${table} (k, v, g) VALUES (?, ?, 0) ON CONFLICT(k) DO UPDATE SET v = excluded.v, g = ${table}.g + 1`
|
|
814
|
+
).run(storageKey(key), value);
|
|
815
|
+
},
|
|
816
|
+
putIfAbsent(key, value) {
|
|
817
|
+
const result = db.prepare(`INSERT OR IGNORE INTO ${table} (k, v, g) VALUES (?, ?, 0)`).run(storageKey(key), value);
|
|
818
|
+
return sqliteChanges(result) === 1;
|
|
819
|
+
},
|
|
820
|
+
getVersioned(key) {
|
|
821
|
+
const row = readRow(key);
|
|
822
|
+
if (row === void 0) {
|
|
823
|
+
return {
|
|
824
|
+
kind: "miss",
|
|
825
|
+
generation: sqliteGeneration(storageId, storageKey(key), null, keyEpoch(storageKey(key)))
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
return {
|
|
829
|
+
kind: "hit",
|
|
830
|
+
value: row.value,
|
|
831
|
+
generation: sqliteGeneration(
|
|
832
|
+
storageId,
|
|
833
|
+
storageKey(key),
|
|
834
|
+
row.generation,
|
|
835
|
+
keyEpoch(storageKey(key))
|
|
836
|
+
)
|
|
837
|
+
};
|
|
838
|
+
},
|
|
839
|
+
setIfMatch(key, value, generation) {
|
|
840
|
+
const keyForStorage = storageKey(key);
|
|
841
|
+
const observed = readSqliteGeneration(generation);
|
|
842
|
+
if (observed === void 0 || observed[0] !== storageId || observed[1] !== keyForStorage) {
|
|
843
|
+
return false;
|
|
844
|
+
}
|
|
845
|
+
if (observed[2] === null) {
|
|
846
|
+
return sqliteChanges(
|
|
847
|
+
db.prepare(
|
|
848
|
+
`INSERT INTO ${table} (k, v, g) SELECT ?, ?, 0 WHERE COALESCE((SELECT v FROM ${metaTable} WHERE k = ?), 0) = ? AND NOT EXISTS (SELECT 1 FROM ${table} WHERE k = ?)`
|
|
849
|
+
).run(keyForStorage, value, keyForStorage, observed[3], keyForStorage)
|
|
850
|
+
) === 1;
|
|
851
|
+
}
|
|
852
|
+
return sqliteChanges(
|
|
853
|
+
db.prepare(
|
|
854
|
+
`UPDATE ${table} SET v = ?, g = g + 1 WHERE k = ? AND g = ? AND COALESCE((SELECT v FROM ${metaTable} WHERE k = ?), 0) = ?`
|
|
855
|
+
).run(value, keyForStorage, observed[2], keyForStorage, observed[3])
|
|
856
|
+
) === 1;
|
|
857
|
+
},
|
|
858
|
+
delete(key) {
|
|
859
|
+
db.prepare(`DELETE FROM ${table} WHERE k = ?`).run(storageKey(key));
|
|
860
|
+
},
|
|
861
|
+
list(prefix = "") {
|
|
862
|
+
const validatedPrefix = validateListPrefix("sqliteBackend", prefix);
|
|
863
|
+
const rows = db.prepare(`SELECT k FROM ${table} ORDER BY k`).all();
|
|
864
|
+
const out = [];
|
|
865
|
+
for (const row of rows) {
|
|
866
|
+
const key = logicalKey(row.k);
|
|
867
|
+
if (key?.startsWith(validatedPrefix)) out.push(key);
|
|
868
|
+
}
|
|
869
|
+
return out.sort();
|
|
870
|
+
},
|
|
871
|
+
close() {
|
|
872
|
+
db.close();
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
function sqliteKv(path, opts = {}) {
|
|
877
|
+
const backend = sqliteBackend(path, opts);
|
|
878
|
+
const tier = kvStorage({
|
|
879
|
+
backend,
|
|
880
|
+
codec: opts.codec
|
|
881
|
+
});
|
|
882
|
+
return Object.assign(tier, { close: () => backend.close() });
|
|
883
|
+
}
|
|
884
|
+
function sqliteAppendLog(path, opts = {}) {
|
|
885
|
+
const kv = sqliteKv(path, opts);
|
|
886
|
+
const log = appendLogStorage({ kv, prefix: opts.prefix ?? "event-log" });
|
|
887
|
+
return Object.assign(log, { close: () => kv.close() });
|
|
888
|
+
}
|
|
889
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
890
|
+
0 && (module.exports = {
|
|
891
|
+
fileAppendLog,
|
|
892
|
+
fileBackend,
|
|
893
|
+
fileKv,
|
|
894
|
+
sqliteAppendLog,
|
|
895
|
+
sqliteBackend,
|
|
896
|
+
sqliteKv
|
|
897
|
+
});
|
|
898
|
+
//# sourceMappingURL=node.cjs.map
|