toiljs 0.0.59 → 0.0.60
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/CHANGELOG.md +10 -0
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +309 -116
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/devserver/.tsbuildinfo +1 -1
- package/build/devserver/db/catalog.d.ts +1 -0
- package/build/devserver/db/catalog.js +80 -0
- package/build/devserver/db/database.d.ts +64 -0
- package/build/devserver/db/database.js +662 -0
- package/build/devserver/db/index.d.ts +3 -0
- package/build/devserver/db/index.js +3 -0
- package/build/devserver/db/types.d.ts +58 -0
- package/build/devserver/db/types.js +20 -0
- package/build/devserver/email/index.js +1 -1
- package/build/devserver/index.d.ts +9 -24
- package/build/devserver/index.js +4 -165
- package/build/devserver/{host.d.ts → runtime/host.d.ts} +1 -1
- package/build/devserver/{host.js → runtime/host.js} +6 -6
- package/build/devserver/{module.d.ts → runtime/module.d.ts} +1 -1
- package/build/devserver/{module.js → runtime/module.js} +8 -1
- package/build/devserver/server.d.ts +17 -0
- package/build/devserver/server.js +164 -0
- package/docs/time.md +2 -2
- package/examples/basic/server/migrations/GuestEntry.migration.ts +39 -0
- package/package.json +2 -2
- package/server/runtime/time.ts +3 -3
- package/src/cli/create.ts +38 -1
- package/src/cli/db.ts +158 -0
- package/src/cli/diagnostics.ts +19 -0
- package/src/cli/doctor.ts +20 -0
- package/src/cli/index.ts +10 -0
- package/src/cli/update.ts +58 -0
- package/src/devserver/db/catalog.ts +100 -0
- package/src/devserver/db/database.ts +1169 -0
- package/src/devserver/db/index.ts +18 -0
- package/src/devserver/db/types.ts +76 -0
- package/src/devserver/email/index.ts +1 -1
- package/src/devserver/index.ts +19 -287
- package/src/devserver/{host.ts → runtime/host.ts} +6 -6
- package/src/devserver/{module.ts → runtime/module.ts} +13 -1
- package/src/devserver/server.ts +292 -0
- package/test/db.test.ts +0 -0
- package/test/devserver-database.test.ts +114 -9
- package/test/devserver-pqauth.test.ts +1 -1
- package/test/devserver-secrets.test.ts +5 -1
- package/test/doctor.test.ts +13 -0
- package/test/example-guestbook.test.ts +43 -1
- package/test/pqauth-e2e.test.ts +1 -1
- package/build/devserver/database.d.ts +0 -8
- package/build/devserver/database.js +0 -418
- package/src/devserver/database.ts +0 -618
- /package/build/devserver/{dotenv.d.ts → config/dotenv.d.ts} +0 -0
- /package/build/devserver/{dotenv.js → config/dotenv.js} +0 -0
- /package/build/devserver/{env.d.ts → config/env.d.ts} +0 -0
- /package/build/devserver/{env.js → config/env.js} +0 -0
- /package/build/devserver/{ratelimit.d.ts → config/ratelimit.d.ts} +0 -0
- /package/build/devserver/{ratelimit.js → config/ratelimit.js} +0 -0
- /package/build/devserver/{cache.d.ts → http/cache.d.ts} +0 -0
- /package/build/devserver/{cache.js → http/cache.js} +0 -0
- /package/build/devserver/{envelope.d.ts → http/envelope.d.ts} +0 -0
- /package/build/devserver/{envelope.js → http/envelope.js} +0 -0
- /package/build/devserver/{proxy.d.ts → http/proxy.d.ts} +0 -0
- /package/build/devserver/{proxy.js → http/proxy.js} +0 -0
- /package/build/devserver/{crypto.d.ts → runtime/crypto.d.ts} +0 -0
- /package/build/devserver/{crypto.js → runtime/crypto.js} +0 -0
- /package/src/devserver/{dotenv.ts → config/dotenv.ts} +0 -0
- /package/src/devserver/{env.ts → config/env.ts} +0 -0
- /package/src/devserver/{ratelimit.ts → config/ratelimit.ts} +0 -0
- /package/src/devserver/{cache.ts → http/cache.ts} +0 -0
- /package/src/devserver/{envelope.ts → http/envelope.ts} +0 -0
- /package/src/devserver/{proxy.ts → http/proxy.ts} +0 -0
- /package/src/devserver/{crypto.ts → runtime/crypto.ts} +0 -0
|
@@ -1,418 +0,0 @@
|
|
|
1
|
-
const STORE = new Map();
|
|
2
|
-
const VIEWS = new Map();
|
|
3
|
-
const MEMBERS = new Map();
|
|
4
|
-
const COUNTERS = new Map();
|
|
5
|
-
const EVENTS = new Map();
|
|
6
|
-
const CAPACITY = new Map();
|
|
7
|
-
function capLedger(sk) {
|
|
8
|
-
let l = CAPACITY.get(sk);
|
|
9
|
-
if (l === undefined) {
|
|
10
|
-
l = { total: 0n, confirmed: 0n, holds: new Map(), nextId: 1n };
|
|
11
|
-
CAPACITY.set(sk, l);
|
|
12
|
-
}
|
|
13
|
-
return l;
|
|
14
|
-
}
|
|
15
|
-
function capPrune(l, nowMs) {
|
|
16
|
-
for (const [id, h] of l.holds)
|
|
17
|
-
if (h.expiresMs <= nowMs)
|
|
18
|
-
l.holds.delete(id);
|
|
19
|
-
}
|
|
20
|
-
function capHeld(l) {
|
|
21
|
-
let sum = 0n;
|
|
22
|
-
for (const h of l.holds.values())
|
|
23
|
-
sum += h.amount;
|
|
24
|
-
return sum;
|
|
25
|
-
}
|
|
26
|
-
const MAX_NAME = 512;
|
|
27
|
-
const MAX_KEY = 4096;
|
|
28
|
-
const MAX_VALUE = 256 * 1024;
|
|
29
|
-
const I64_MIN = -(2n ** 63n);
|
|
30
|
-
const I64_MAX = 2n ** 63n - 1n;
|
|
31
|
-
function satI64(v) {
|
|
32
|
-
return v < I64_MIN ? I64_MIN : v > I64_MAX ? I64_MAX : v;
|
|
33
|
-
}
|
|
34
|
-
const ABSENT = -2;
|
|
35
|
-
const TOO_SMALL = -1;
|
|
36
|
-
const INVALID_HANDLE = -1001;
|
|
37
|
-
const PRODUCT_ERR = -1000;
|
|
38
|
-
export function freshDbState() {
|
|
39
|
-
return { handles: [], lastResult: null };
|
|
40
|
-
}
|
|
41
|
-
function mem(ref) {
|
|
42
|
-
if (!ref.memory)
|
|
43
|
-
throw new Error('data host import called before memory was bound');
|
|
44
|
-
return Buffer.from(ref.memory.buffer);
|
|
45
|
-
}
|
|
46
|
-
function readCopy(ref, ptr, len) {
|
|
47
|
-
const m = mem(ref);
|
|
48
|
-
if (ptr < 0 || len < 0 || ptr + len > m.length)
|
|
49
|
-
throw new Error(`data read out of bounds: ptr=${String(ptr)} len=${String(len)}`);
|
|
50
|
-
return Buffer.from(m.subarray(ptr, ptr + len));
|
|
51
|
-
}
|
|
52
|
-
function storeKey(collection, key) {
|
|
53
|
-
return collection + '\0' + key.toString('latin1');
|
|
54
|
-
}
|
|
55
|
-
function collOf(db, handle) {
|
|
56
|
-
return handle >= 0 && handle < db.handles.length ? db.handles[handle] : null;
|
|
57
|
-
}
|
|
58
|
-
export function buildDatabaseImports(ref, db) {
|
|
59
|
-
return {
|
|
60
|
-
'data.resolve_collection': (namePtr, nameLen, outHandlePtr) => {
|
|
61
|
-
if (nameLen < 0 || nameLen > MAX_NAME)
|
|
62
|
-
throw new Error('data: collection name too long');
|
|
63
|
-
const name = readCopy(ref, namePtr, nameLen).toString('utf8');
|
|
64
|
-
const handle = db.handles.length;
|
|
65
|
-
db.handles.push(name);
|
|
66
|
-
const m = mem(ref);
|
|
67
|
-
if (outHandlePtr < 0 || outHandlePtr + 4 > m.length)
|
|
68
|
-
throw new Error('data: resolve out-handle out of bounds');
|
|
69
|
-
m.writeUInt32LE(handle, outHandlePtr);
|
|
70
|
-
return 0;
|
|
71
|
-
},
|
|
72
|
-
'data.get': (handle, keyPtr, keyLen) => {
|
|
73
|
-
const coll = collOf(db, handle);
|
|
74
|
-
if (coll === null)
|
|
75
|
-
return INVALID_HANDLE;
|
|
76
|
-
if (keyLen > MAX_KEY)
|
|
77
|
-
throw new Error('data: key too long');
|
|
78
|
-
const v = STORE.get(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
79
|
-
if (v === undefined)
|
|
80
|
-
return ABSENT;
|
|
81
|
-
db.lastResult = v;
|
|
82
|
-
return v.length;
|
|
83
|
-
},
|
|
84
|
-
'data.get_many': (handle, keysPtr, keysLen) => {
|
|
85
|
-
const coll = collOf(db, handle);
|
|
86
|
-
if (coll === null)
|
|
87
|
-
return INVALID_HANDLE;
|
|
88
|
-
if (keysLen > MAX_VALUE)
|
|
89
|
-
throw new Error('data: keys blob too large');
|
|
90
|
-
const blob = readCopy(ref, keysPtr, keysLen);
|
|
91
|
-
let off = 0;
|
|
92
|
-
const count = blob.readUInt32LE(off);
|
|
93
|
-
off += 4;
|
|
94
|
-
if (count > 1024)
|
|
95
|
-
return PRODUCT_ERR;
|
|
96
|
-
const header = Buffer.alloc(4);
|
|
97
|
-
header.writeUInt32LE(count, 0);
|
|
98
|
-
const parts = [header];
|
|
99
|
-
for (let i = 0; i < count; i++) {
|
|
100
|
-
const len = blob.readUInt32LE(off);
|
|
101
|
-
off += 4;
|
|
102
|
-
const key = blob.subarray(off, off + len);
|
|
103
|
-
off += len;
|
|
104
|
-
const v = STORE.get(storeKey(coll, key));
|
|
105
|
-
if (v === undefined) {
|
|
106
|
-
parts.push(Buffer.from([0]));
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
const h = Buffer.alloc(5);
|
|
110
|
-
h.writeUInt8(1, 0);
|
|
111
|
-
h.writeUInt32LE(v.length, 1);
|
|
112
|
-
parts.push(h, v);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
db.lastResult = Buffer.concat(parts);
|
|
116
|
-
return db.lastResult.length;
|
|
117
|
-
},
|
|
118
|
-
'data.exists': (handle, keyPtr, keyLen) => {
|
|
119
|
-
const coll = collOf(db, handle);
|
|
120
|
-
if (coll === null)
|
|
121
|
-
return INVALID_HANDLE;
|
|
122
|
-
return STORE.has(storeKey(coll, readCopy(ref, keyPtr, keyLen))) ? 1 : 0;
|
|
123
|
-
},
|
|
124
|
-
'data.create': (handle, keyPtr, keyLen, valPtr, valLen, _idemPtr) => {
|
|
125
|
-
const coll = collOf(db, handle);
|
|
126
|
-
if (coll === null)
|
|
127
|
-
return INVALID_HANDLE;
|
|
128
|
-
if (keyLen > MAX_KEY || valLen > MAX_VALUE)
|
|
129
|
-
throw new Error('data: key/value too large');
|
|
130
|
-
const sk = storeKey(coll, readCopy(ref, keyPtr, keyLen));
|
|
131
|
-
if (STORE.has(sk))
|
|
132
|
-
return PRODUCT_ERR;
|
|
133
|
-
STORE.set(sk, readCopy(ref, valPtr, valLen));
|
|
134
|
-
return 0;
|
|
135
|
-
},
|
|
136
|
-
'data.patch': (handle, keyPtr, keyLen, patchPtr, patchLen, _idemPtr) => {
|
|
137
|
-
const coll = collOf(db, handle);
|
|
138
|
-
if (coll === null)
|
|
139
|
-
return INVALID_HANDLE;
|
|
140
|
-
if (keyLen > MAX_KEY || patchLen > MAX_VALUE)
|
|
141
|
-
throw new Error('data: key/patch too large');
|
|
142
|
-
const sk = storeKey(coll, readCopy(ref, keyPtr, keyLen));
|
|
143
|
-
if (!STORE.has(sk))
|
|
144
|
-
return PRODUCT_ERR;
|
|
145
|
-
const v = readCopy(ref, patchPtr, patchLen);
|
|
146
|
-
STORE.set(sk, v);
|
|
147
|
-
db.lastResult = v;
|
|
148
|
-
return v.length;
|
|
149
|
-
},
|
|
150
|
-
'data.delete': (handle, keyPtr, keyLen, _idemPtr) => {
|
|
151
|
-
const coll = collOf(db, handle);
|
|
152
|
-
if (coll === null)
|
|
153
|
-
return INVALID_HANDLE;
|
|
154
|
-
STORE.delete(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
155
|
-
return 0;
|
|
156
|
-
},
|
|
157
|
-
'data.get_delete': (handle, keyPtr, keyLen, _idemPtr) => {
|
|
158
|
-
const coll = collOf(db, handle);
|
|
159
|
-
if (coll === null)
|
|
160
|
-
return INVALID_HANDLE;
|
|
161
|
-
const sk = storeKey(coll, readCopy(ref, keyPtr, keyLen));
|
|
162
|
-
const v = STORE.get(sk);
|
|
163
|
-
if (v === undefined)
|
|
164
|
-
return ABSENT;
|
|
165
|
-
STORE.delete(sk);
|
|
166
|
-
db.lastResult = v;
|
|
167
|
-
return v.length;
|
|
168
|
-
},
|
|
169
|
-
'data.unique_lookup': (handle, keyPtr, keyLen) => {
|
|
170
|
-
const coll = collOf(db, handle);
|
|
171
|
-
if (coll === null)
|
|
172
|
-
return INVALID_HANDLE;
|
|
173
|
-
const v = STORE.get(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
174
|
-
if (v === undefined)
|
|
175
|
-
return ABSENT;
|
|
176
|
-
db.lastResult = v;
|
|
177
|
-
return v.length;
|
|
178
|
-
},
|
|
179
|
-
'data.unique_claim': (handle, keyPtr, keyLen, valPtr, valLen, _idemPtr) => {
|
|
180
|
-
const coll = collOf(db, handle);
|
|
181
|
-
if (coll === null)
|
|
182
|
-
return INVALID_HANDLE;
|
|
183
|
-
if (keyLen > MAX_KEY || valLen > MAX_VALUE)
|
|
184
|
-
throw new Error('data: key/value too large');
|
|
185
|
-
const sk = storeKey(coll, readCopy(ref, keyPtr, keyLen));
|
|
186
|
-
const owner = readCopy(ref, valPtr, valLen);
|
|
187
|
-
const existing = STORE.get(sk);
|
|
188
|
-
if (existing === undefined) {
|
|
189
|
-
STORE.set(sk, owner);
|
|
190
|
-
return 0;
|
|
191
|
-
}
|
|
192
|
-
if (existing.equals(owner))
|
|
193
|
-
return 2;
|
|
194
|
-
db.lastResult = existing;
|
|
195
|
-
return 1;
|
|
196
|
-
},
|
|
197
|
-
'data.unique_release': (handle, keyPtr, keyLen, valPtr, valLen, _idemPtr) => {
|
|
198
|
-
const coll = collOf(db, handle);
|
|
199
|
-
if (coll === null)
|
|
200
|
-
return INVALID_HANDLE;
|
|
201
|
-
const sk = storeKey(coll, readCopy(ref, keyPtr, keyLen));
|
|
202
|
-
const existing = STORE.get(sk);
|
|
203
|
-
if (existing === undefined)
|
|
204
|
-
return 0;
|
|
205
|
-
if (!existing.equals(readCopy(ref, valPtr, valLen)))
|
|
206
|
-
return PRODUCT_ERR;
|
|
207
|
-
STORE.delete(sk);
|
|
208
|
-
return 0;
|
|
209
|
-
},
|
|
210
|
-
'data.membership_contains': (handle, setPtr, setLen, memberPtr, memberLen) => {
|
|
211
|
-
const coll = collOf(db, handle);
|
|
212
|
-
if (coll === null)
|
|
213
|
-
return INVALID_HANDLE;
|
|
214
|
-
const set = MEMBERS.get(storeKey(coll, readCopy(ref, setPtr, setLen)));
|
|
215
|
-
if (set === undefined)
|
|
216
|
-
return 0;
|
|
217
|
-
return set.has(readCopy(ref, memberPtr, memberLen).toString('latin1')) ? 1 : 0;
|
|
218
|
-
},
|
|
219
|
-
'data.membership_add': (handle, setPtr, setLen, memberPtr, memberLen, _idemPtr) => {
|
|
220
|
-
const coll = collOf(db, handle);
|
|
221
|
-
if (coll === null)
|
|
222
|
-
return INVALID_HANDLE;
|
|
223
|
-
if (setLen > MAX_KEY || memberLen > MAX_VALUE)
|
|
224
|
-
throw new Error('data: set/member too large');
|
|
225
|
-
const sk = storeKey(coll, readCopy(ref, setPtr, setLen));
|
|
226
|
-
const member = readCopy(ref, memberPtr, memberLen);
|
|
227
|
-
let set = MEMBERS.get(sk);
|
|
228
|
-
if (set === undefined) {
|
|
229
|
-
set = new Map();
|
|
230
|
-
MEMBERS.set(sk, set);
|
|
231
|
-
}
|
|
232
|
-
set.set(member.toString('latin1'), member);
|
|
233
|
-
return 0;
|
|
234
|
-
},
|
|
235
|
-
'data.membership_remove': (handle, setPtr, setLen, memberPtr, memberLen, _idemPtr) => {
|
|
236
|
-
const coll = collOf(db, handle);
|
|
237
|
-
if (coll === null)
|
|
238
|
-
return INVALID_HANDLE;
|
|
239
|
-
const set = MEMBERS.get(storeKey(coll, readCopy(ref, setPtr, setLen)));
|
|
240
|
-
if (set !== undefined)
|
|
241
|
-
set.delete(readCopy(ref, memberPtr, memberLen).toString('latin1'));
|
|
242
|
-
return 0;
|
|
243
|
-
},
|
|
244
|
-
'data.membership_list': (handle, setPtr, setLen, limit) => {
|
|
245
|
-
const coll = collOf(db, handle);
|
|
246
|
-
if (coll === null)
|
|
247
|
-
return INVALID_HANDLE;
|
|
248
|
-
const set = MEMBERS.get(storeKey(coll, readCopy(ref, setPtr, setLen)));
|
|
249
|
-
const n = Math.max(0, Math.min(limit, 0xffff));
|
|
250
|
-
const members = set === undefined ? [] : Array.from(set.values()).sort(Buffer.compare).slice(0, n);
|
|
251
|
-
const header = Buffer.alloc(4);
|
|
252
|
-
header.writeUInt32LE(members.length, 0);
|
|
253
|
-
const parts = [header];
|
|
254
|
-
for (const m of members) {
|
|
255
|
-
const h = Buffer.alloc(4);
|
|
256
|
-
h.writeUInt32LE(m.length, 0);
|
|
257
|
-
parts.push(h, m);
|
|
258
|
-
}
|
|
259
|
-
db.lastResult = Buffer.concat(parts);
|
|
260
|
-
return db.lastResult.length;
|
|
261
|
-
},
|
|
262
|
-
'data.view_get': (handle, keyPtr, keyLen) => {
|
|
263
|
-
const coll = collOf(db, handle);
|
|
264
|
-
if (coll === null)
|
|
265
|
-
return INVALID_HANDLE;
|
|
266
|
-
const v = VIEWS.get(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
267
|
-
if (v === undefined)
|
|
268
|
-
return ABSENT;
|
|
269
|
-
db.lastResult = v;
|
|
270
|
-
return v.length;
|
|
271
|
-
},
|
|
272
|
-
'data.view_publish': (handle, keyPtr, keyLen, valPtr, valLen, _idemPtr) => {
|
|
273
|
-
const coll = collOf(db, handle);
|
|
274
|
-
if (coll === null)
|
|
275
|
-
return INVALID_HANDLE;
|
|
276
|
-
if (keyLen > MAX_KEY || valLen > MAX_VALUE)
|
|
277
|
-
throw new Error('data: key/view too large');
|
|
278
|
-
VIEWS.set(storeKey(coll, readCopy(ref, keyPtr, keyLen)), readCopy(ref, valPtr, valLen));
|
|
279
|
-
return 0;
|
|
280
|
-
},
|
|
281
|
-
'data.counter_get': (handle, keyPtr, keyLen) => {
|
|
282
|
-
const coll = collOf(db, handle);
|
|
283
|
-
if (coll === null)
|
|
284
|
-
return INVALID_HANDLE;
|
|
285
|
-
const sum = COUNTERS.get(storeKey(coll, readCopy(ref, keyPtr, keyLen))) ?? 0n;
|
|
286
|
-
const out = Buffer.alloc(8);
|
|
287
|
-
out.writeBigInt64LE(sum);
|
|
288
|
-
db.lastResult = out;
|
|
289
|
-
return out.length;
|
|
290
|
-
},
|
|
291
|
-
'data.counter_add': (handle, keyPtr, keyLen, delta, _idemPtr) => {
|
|
292
|
-
const coll = collOf(db, handle);
|
|
293
|
-
if (coll === null)
|
|
294
|
-
return INVALID_HANDLE;
|
|
295
|
-
const sk = storeKey(coll, readCopy(ref, keyPtr, keyLen));
|
|
296
|
-
COUNTERS.set(sk, satI64((COUNTERS.get(sk) ?? 0n) + BigInt(delta)));
|
|
297
|
-
return 0;
|
|
298
|
-
},
|
|
299
|
-
'data.append': (handle, keyPtr, keyLen, evPtr, evLen, _idemPtr) => {
|
|
300
|
-
const coll = collOf(db, handle);
|
|
301
|
-
if (coll === null)
|
|
302
|
-
return INVALID_HANDLE;
|
|
303
|
-
if (keyLen > MAX_KEY || evLen > MAX_VALUE)
|
|
304
|
-
throw new Error('data: key/event too large');
|
|
305
|
-
const sk = storeKey(coll, readCopy(ref, keyPtr, keyLen));
|
|
306
|
-
const log = EVENTS.get(sk);
|
|
307
|
-
const ev = readCopy(ref, evPtr, evLen);
|
|
308
|
-
if (log === undefined)
|
|
309
|
-
EVENTS.set(sk, [ev]);
|
|
310
|
-
else
|
|
311
|
-
log.push(ev);
|
|
312
|
-
return 0;
|
|
313
|
-
},
|
|
314
|
-
'data.latest': (handle, keyPtr, keyLen, limit) => {
|
|
315
|
-
const coll = collOf(db, handle);
|
|
316
|
-
if (coll === null)
|
|
317
|
-
return INVALID_HANDLE;
|
|
318
|
-
const log = EVENTS.get(storeKey(coll, readCopy(ref, keyPtr, keyLen))) ?? [];
|
|
319
|
-
const n = Math.max(0, Math.min(limit, 0xffff));
|
|
320
|
-
const newest = log.slice(Math.max(0, log.length - n)).reverse();
|
|
321
|
-
let size = 4;
|
|
322
|
-
for (const ev of newest)
|
|
323
|
-
size += 4 + ev.length;
|
|
324
|
-
const out = Buffer.alloc(size);
|
|
325
|
-
let off = out.writeUInt32LE(newest.length, 0);
|
|
326
|
-
for (const ev of newest) {
|
|
327
|
-
off = out.writeUInt32LE(ev.length, off);
|
|
328
|
-
off += ev.copy(out, off);
|
|
329
|
-
}
|
|
330
|
-
db.lastResult = out;
|
|
331
|
-
return out.length;
|
|
332
|
-
},
|
|
333
|
-
'data.capacity_set_total': (handle, keyPtr, keyLen, total, _idemPtr) => {
|
|
334
|
-
const coll = collOf(db, handle);
|
|
335
|
-
if (coll === null)
|
|
336
|
-
return INVALID_HANDLE;
|
|
337
|
-
const l = capLedger(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
338
|
-
const t = BigInt(total);
|
|
339
|
-
l.total = satI64(t < 0n ? 0n : t);
|
|
340
|
-
return 0;
|
|
341
|
-
},
|
|
342
|
-
'data.capacity_available': (handle, keyPtr, keyLen) => {
|
|
343
|
-
const coll = collOf(db, handle);
|
|
344
|
-
if (coll === null)
|
|
345
|
-
return INVALID_HANDLE;
|
|
346
|
-
const l = capLedger(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
347
|
-
capPrune(l, Date.now());
|
|
348
|
-
const avail = l.total - l.confirmed - capHeld(l);
|
|
349
|
-
const out = Buffer.alloc(8);
|
|
350
|
-
out.writeBigInt64LE(avail < 0n ? 0n : avail);
|
|
351
|
-
db.lastResult = out;
|
|
352
|
-
return out.length;
|
|
353
|
-
},
|
|
354
|
-
'data.capacity_reserve': (handle, keyPtr, keyLen, amount, ttlMs, _idemPtr) => {
|
|
355
|
-
const coll = collOf(db, handle);
|
|
356
|
-
if (coll === null)
|
|
357
|
-
return INVALID_HANDLE;
|
|
358
|
-
const want = BigInt(amount);
|
|
359
|
-
if (want <= 0n)
|
|
360
|
-
return ABSENT;
|
|
361
|
-
const l = capLedger(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
362
|
-
const now = Date.now();
|
|
363
|
-
capPrune(l, now);
|
|
364
|
-
if (l.total - l.confirmed - capHeld(l) < want)
|
|
365
|
-
return ABSENT;
|
|
366
|
-
const id = l.nextId++;
|
|
367
|
-
l.holds.set(id, { amount: want, expiresMs: now + Math.max(0, Number(ttlMs)) });
|
|
368
|
-
const out = Buffer.alloc(8);
|
|
369
|
-
out.writeBigUInt64LE(id);
|
|
370
|
-
db.lastResult = out;
|
|
371
|
-
return out.length;
|
|
372
|
-
},
|
|
373
|
-
'data.capacity_confirm': (handle, keyPtr, keyLen, reservationId, _idemPtr) => {
|
|
374
|
-
const coll = collOf(db, handle);
|
|
375
|
-
if (coll === null)
|
|
376
|
-
return INVALID_HANDLE;
|
|
377
|
-
const l = capLedger(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
378
|
-
capPrune(l, Date.now());
|
|
379
|
-
const h = l.holds.get(BigInt(reservationId));
|
|
380
|
-
if (h === undefined)
|
|
381
|
-
return 0;
|
|
382
|
-
l.holds.delete(BigInt(reservationId));
|
|
383
|
-
l.confirmed = satI64(l.confirmed + h.amount);
|
|
384
|
-
return 1;
|
|
385
|
-
},
|
|
386
|
-
'data.capacity_cancel': (handle, keyPtr, keyLen, reservationId, _idemPtr) => {
|
|
387
|
-
const coll = collOf(db, handle);
|
|
388
|
-
if (coll === null)
|
|
389
|
-
return INVALID_HANDLE;
|
|
390
|
-
const l = capLedger(storeKey(coll, readCopy(ref, keyPtr, keyLen)));
|
|
391
|
-
capPrune(l, Date.now());
|
|
392
|
-
return l.holds.delete(BigInt(reservationId)) ? 1 : 0;
|
|
393
|
-
},
|
|
394
|
-
'data.take_result': (outPtr, outCap) => {
|
|
395
|
-
const v = db.lastResult;
|
|
396
|
-
if (v === null)
|
|
397
|
-
return 0;
|
|
398
|
-
if (v.length > outCap)
|
|
399
|
-
return TOO_SMALL;
|
|
400
|
-
const m = mem(ref);
|
|
401
|
-
if (outPtr < 0 || outPtr + v.length > m.length)
|
|
402
|
-
throw new Error('data: take_result out of bounds');
|
|
403
|
-
v.copy(m, outPtr);
|
|
404
|
-
db.lastResult = null;
|
|
405
|
-
return v.length;
|
|
406
|
-
},
|
|
407
|
-
'data.result_schema_version': () => -1n,
|
|
408
|
-
'data.write_allowed': () => 1,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
export function __resetDbForTests() {
|
|
412
|
-
STORE.clear();
|
|
413
|
-
VIEWS.clear();
|
|
414
|
-
MEMBERS.clear();
|
|
415
|
-
COUNTERS.clear();
|
|
416
|
-
EVENTS.clear();
|
|
417
|
-
CAPACITY.clear();
|
|
418
|
-
}
|