@mblaney/holster 1.0.36 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/holster.js +3 -3
- package/build/holster.js.map +3 -3
- package/dist/holster.js +3 -3
- package/dist/holster.js.map +3 -3
- package/package.json +4 -5
- package/src/dup.js +4 -5
- package/src/get.js +4 -1
- package/src/ham.js +5 -2
- package/src/holster.js +78 -47
- package/src/index.js +1 -1
- package/src/radisk.js +90 -87
- package/src/sea-utils.js +1 -1
- package/src/store.js +1 -1
- package/src/user.js +0 -4
- package/src/wire.js +204 -80
- package/ts/src/dup.ts +6 -17
- package/ts/src/ham.ts +5 -1
- package/ts/src/holster.ts +66 -33
- package/ts/src/radisk.ts +87 -81
- package/ts/src/schemas.ts +1 -5
- package/ts/src/sea-utils.ts +1 -1
- package/ts/src/store.ts +1 -1
- package/ts/src/user.ts +0 -4
- package/ts/src/wire.ts +201 -69
package/ts/src/holster.ts
CHANGED
|
@@ -123,28 +123,28 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
123
123
|
delete (msg.put[soul] as { _?: unknown })._
|
|
124
124
|
delete (msg.put[soul] as Record<string, unknown>)[utils.userPublicKey]
|
|
125
125
|
delete (msg.put[soul] as Record<string, unknown>)[utils.userSignature]
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
api(_ctxid).next(null as never, res as never, _opt)
|
|
126
|
+
const node = msg.put[soul]!
|
|
127
|
+
await Promise.all(Object.keys(node).map(async key => {
|
|
128
|
+
const id = utils.rel.is(node[key] as GraphValue)
|
|
129
|
+
if (!id) return
|
|
130
|
+
const attemptRead = async (retries = 0): Promise<unknown> => {
|
|
131
|
+
const data = await new Promise<unknown>(res => {
|
|
132
|
+
const _ctxid = utils.text.random()
|
|
133
|
+
const ctx = allctx.get(ctxid!)
|
|
134
|
+
allctx.set(_ctxid, {
|
|
135
|
+
chain: [{ item: null, soul: id }],
|
|
136
|
+
user: ctx ? ctx.user : null,
|
|
138
137
|
})
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return attemptRead(retries + 1)
|
|
138
|
+
api(_ctxid).next(null as never, res as never, _opt)
|
|
139
|
+
})
|
|
140
|
+
if (data !== null || retries >= 5) {
|
|
141
|
+
return data
|
|
144
142
|
}
|
|
145
|
-
|
|
143
|
+
await new Promise(resolve => setTimeout(resolve, 50))
|
|
144
|
+
return attemptRead(retries + 1)
|
|
146
145
|
}
|
|
147
|
-
|
|
146
|
+
node[key] = (await attemptRead()) as GraphValue
|
|
147
|
+
}))
|
|
148
148
|
ack(msg.put[soul])
|
|
149
149
|
} else {
|
|
150
150
|
ack(null)
|
|
@@ -192,13 +192,16 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
192
192
|
item: string,
|
|
193
193
|
ctx: ApiContext,
|
|
194
194
|
i: number,
|
|
195
|
-
request: { on?: LexFilter; _get?: boolean; _opt?: WireOptions },
|
|
196
|
-
cb: (data: unknown) => void
|
|
195
|
+
request: { on?: LexFilter; get?: LexFilter; _get?: boolean; _opt?: WireOptions },
|
|
196
|
+
cb: (data: unknown) => void,
|
|
197
|
+
on = true
|
|
197
198
|
): void => {
|
|
199
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
198
200
|
const handler = (): void => {
|
|
199
201
|
// Bail out if the context was removed by off().
|
|
200
202
|
if (!allctx.has(ctxid!)) {
|
|
201
203
|
wire.off({ "#": soul, ".": item }, handler)
|
|
204
|
+
if (timer) clearTimeout(timer)
|
|
202
205
|
return
|
|
203
206
|
}
|
|
204
207
|
wire.get(
|
|
@@ -206,16 +209,39 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
206
209
|
msg => {
|
|
207
210
|
const node = msg.put && msg.put[soul]
|
|
208
211
|
const id = utils.rel.is(node && node[item] as GraphValue)
|
|
209
|
-
if (!id)
|
|
212
|
+
if (!id) {
|
|
213
|
+
// If it's a plain value (not a rel) and this is a get, deliver it.
|
|
214
|
+
// node._ guards against timeout null-acks which lack metadata.
|
|
215
|
+
if (!on && node && node._ && typeof node[item] !== "undefined") {
|
|
216
|
+
if (timer) clearTimeout(timer)
|
|
217
|
+
wire.off({ "#": soul, ".": item }, handler)
|
|
218
|
+
cb(node[item])
|
|
219
|
+
}
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
if (timer) clearTimeout(timer)
|
|
210
223
|
wire.off({ "#": soul, ".": item }, handler)
|
|
211
224
|
ctx.chain[i]!.soul = id
|
|
212
225
|
allctx.set(ctxid!, { ...ctx })
|
|
213
|
-
|
|
226
|
+
if (on) {
|
|
227
|
+
api(ctxid).on(request.on!, cb, request._get, request._opt)
|
|
228
|
+
} else {
|
|
229
|
+
api(ctxid).next(null as never, request.get as never, cb as never, request._opt)
|
|
230
|
+
}
|
|
214
231
|
},
|
|
215
232
|
{ ...request._opt, secure: (typeof ctx.user === "boolean" ? ctx.user : !!ctx.user) || options.secure }
|
|
216
233
|
)
|
|
217
234
|
}
|
|
218
235
|
wire.on({ "#": soul, ".": item }, handler, false, request._opt)
|
|
236
|
+
// Time out after the same total duration as the on() retry loop
|
|
237
|
+
// (1+2+4+8+16 = 31s) so callers are not blocked forever if the node
|
|
238
|
+
// genuinely doesn't exist.
|
|
239
|
+
if (!on) {
|
|
240
|
+
timer = setTimeout(() => {
|
|
241
|
+
wire.off({ "#": soul, ".": item }, handler)
|
|
242
|
+
if (cb) cb(null)
|
|
243
|
+
}, 31000)
|
|
244
|
+
}
|
|
219
245
|
}
|
|
220
246
|
|
|
221
247
|
const resolve = (
|
|
@@ -240,7 +266,8 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
240
266
|
const off = typeof request.off !== "undefined"
|
|
241
267
|
|
|
242
268
|
let found = false
|
|
243
|
-
const ctx = allctx.get(ctxid!)
|
|
269
|
+
const ctx = allctx.get(ctxid!)
|
|
270
|
+
if (!ctx) return {item: null, soul: null}
|
|
244
271
|
for (let i = 1; i < ctx.chain.length; i++) {
|
|
245
272
|
if (ctx.chain[i]!.soul !== null) continue
|
|
246
273
|
found = true
|
|
@@ -321,7 +348,17 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
321
348
|
// Node doesn't exist yet — watch for it to appear.
|
|
322
349
|
watchForRel(soul!, item!, ctx, i, request, cb!)
|
|
323
350
|
if (request._get) cb!(null)
|
|
351
|
+
} else if (get && node) {
|
|
352
|
+
const sv = (node as Record<string, unknown> & {_?: {">": Record<string, unknown>}})._?.[">"]
|
|
353
|
+
if (sv && Object.keys(sv).length > 0 && typeof sv[item!] === "undefined") {
|
|
354
|
+
// State vector has other properties but not this one — never written.
|
|
355
|
+
if (cb) cb(null)
|
|
356
|
+
} else {
|
|
357
|
+
// Empty state vector or item is tracked — may arrive via push.
|
|
358
|
+
watchForRel(soul!, item!, ctx, i, request, cb!, false)
|
|
359
|
+
}
|
|
324
360
|
} else {
|
|
361
|
+
// Soul doesn't exist or no get — return null.
|
|
325
362
|
if (cb) cb(null)
|
|
326
363
|
}
|
|
327
364
|
}
|
|
@@ -484,8 +521,7 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
484
521
|
const ctx = allctx.get(ctxid!)
|
|
485
522
|
if (!ctx) return
|
|
486
523
|
|
|
487
|
-
if (!ctx.cb) {
|
|
488
|
-
if (!callback) return
|
|
524
|
+
if (!ctx.cb && callback) {
|
|
489
525
|
ctx.cb = callback as never
|
|
490
526
|
callback = undefined
|
|
491
527
|
}
|
|
@@ -499,7 +535,7 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
499
535
|
return
|
|
500
536
|
}
|
|
501
537
|
|
|
502
|
-
const resolved = resolve({ put: data }, _ack as never)
|
|
538
|
+
const resolved = resolve({ put: data, _opt: {put: true} }, _ack as never)
|
|
503
539
|
if (!resolved) return
|
|
504
540
|
|
|
505
541
|
const { item, soul } = resolved
|
|
@@ -566,7 +602,7 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
566
602
|
wire.put(g, _ack as never)
|
|
567
603
|
})
|
|
568
604
|
},
|
|
569
|
-
{ secure: (typeof ctx.user === "boolean" ? ctx.user : !!ctx.user) || options.secure }
|
|
605
|
+
{ secure: (typeof ctx.user === "boolean" ? ctx.user : !!ctx.user) || options.secure, put: true }
|
|
570
606
|
)
|
|
571
607
|
return
|
|
572
608
|
}
|
|
@@ -650,7 +686,7 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
650
686
|
|
|
651
687
|
wire.put(g, _ack as never)
|
|
652
688
|
},
|
|
653
|
-
{ secure: (typeof ctx.user === "boolean" ? ctx.user : !!ctx.user) || options.secure }
|
|
689
|
+
{ secure: (typeof ctx.user === "boolean" ? ctx.user : !!ctx.user) || options.secure, put: true }
|
|
654
690
|
)
|
|
655
691
|
}
|
|
656
692
|
attemptRead()
|
|
@@ -808,10 +844,7 @@ const Holster = (opt?: HolsterOptions | string | string[]): HolsterAPI => {
|
|
|
808
844
|
const id = utils.rel.is(current as GraphValue)
|
|
809
845
|
if (id) {
|
|
810
846
|
wire.off(initialLex as never, map.get(callback)!)
|
|
811
|
-
|
|
812
|
-
? utils.obj.put(initialLex as never, "#", id)
|
|
813
|
-
: { "#": id, ".": null }) as Lex
|
|
814
|
-
wire.on(relLex, map.get(callback)!, false, opts)
|
|
847
|
+
wire.on({ "#": id, ".": null } as never, map.get(callback)!, false, opts)
|
|
815
848
|
if (_get) map.get(callback)!()
|
|
816
849
|
} else if (_get) {
|
|
817
850
|
// Not a rel, but _get was requested, so trigger callback.
|
package/ts/src/radisk.ts
CHANGED
|
@@ -48,11 +48,7 @@ const Radisk = (opt: RadiskOptions) => {
|
|
|
48
48
|
|
|
49
49
|
const pendingReads = new Map<
|
|
50
50
|
string,
|
|
51
|
-
|
|
52
|
-
callbacks: Array<(err?: string, result?: EncodedValue | Record<string, EncodedValue>) => void>
|
|
53
|
-
fired: boolean
|
|
54
|
-
timeoutId: NodeJS.Timeout | null
|
|
55
|
-
}
|
|
51
|
+
Array<(err?: string | null, result?: EncodedValue | Record<string, EncodedValue>) => void>
|
|
56
52
|
>()
|
|
57
53
|
|
|
58
54
|
let lastMemoryCheck = 0
|
|
@@ -66,7 +62,6 @@ const Radisk = (opt: RadiskOptions) => {
|
|
|
66
62
|
write: opt.write || 1,
|
|
67
63
|
size: opt.size || 1024 * 1024,
|
|
68
64
|
memoryLimit: opt.memoryLimit || 500,
|
|
69
|
-
readTimeout: opt.readTimeout || 1000,
|
|
70
65
|
cache: opt.cache !== undefined ? opt.cache : true,
|
|
71
66
|
store: opt.store,
|
|
72
67
|
}
|
|
@@ -89,7 +84,7 @@ const Radisk = (opt: RadiskOptions) => {
|
|
|
89
84
|
|
|
90
85
|
const perfLog = (operation: string, startTime: number, key: string, size?: number): void => {
|
|
91
86
|
const duration = Date.now() - startTime
|
|
92
|
-
if (duration >
|
|
87
|
+
if (duration > 3000) {
|
|
93
88
|
console.log(
|
|
94
89
|
`[RADISK-SLOW] ${operation}: ${duration}ms for ${key}${size ? ` (${size} bytes)` : ""}`
|
|
95
90
|
)
|
|
@@ -143,35 +138,25 @@ const Radisk = (opt: RadiskOptions) => {
|
|
|
143
138
|
}
|
|
144
139
|
|
|
145
140
|
if (pendingReads.has(key)) {
|
|
146
|
-
pendingReads.get(key)!.
|
|
141
|
+
pendingReads.get(key)!.push(callback)
|
|
147
142
|
return
|
|
148
143
|
}
|
|
149
144
|
|
|
150
|
-
|
|
151
|
-
callbacks: Array<(err?: string | null, value?: EncodedValue | Record<string, EncodedValue>) => void>
|
|
152
|
-
fired: boolean
|
|
153
|
-
timeoutId: NodeJS.Timeout | null
|
|
154
|
-
} = { callbacks: [callback], fired: false, timeoutId: null }
|
|
155
|
-
pendingReads.set(key, pending)
|
|
156
|
-
|
|
157
|
-
pending.timeoutId = setTimeout(() => {
|
|
158
|
-
if (!pending.fired) {
|
|
159
|
-
pending.fired = true
|
|
160
|
-
pendingReads.delete(key)
|
|
161
|
-
const err = "radisk read timeout"
|
|
162
|
-
pending.callbacks.forEach(cb => cb(err, undefined))
|
|
163
|
-
}
|
|
164
|
-
}, options.readTimeout)
|
|
165
|
-
|
|
145
|
+
pendingReads.set(key, [callback])
|
|
166
146
|
const readStart = Date.now()
|
|
147
|
+
const timeout = setTimeout(() => {
|
|
148
|
+
const callbacks = pendingReads.get(key)
|
|
149
|
+
if (!callbacks) return
|
|
150
|
+
options.log(`radisk read hang detected for key: ${key}`)
|
|
151
|
+
pendingReads.delete(key)
|
|
152
|
+
callbacks.forEach(cb => cb(null, null as unknown as undefined))
|
|
153
|
+
}, 30000)
|
|
167
154
|
return radisk.read(key, (err, result) => {
|
|
168
|
-
|
|
155
|
+
clearTimeout(timeout)
|
|
169
156
|
perfLog("read", readStart, key)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
pending.callbacks.forEach(callback => callback(err, result))
|
|
174
|
-
}
|
|
157
|
+
const callbacks = pendingReads.get(key) || []
|
|
158
|
+
pendingReads.delete(key)
|
|
159
|
+
callbacks.forEach(callback => callback(err, result))
|
|
175
160
|
})
|
|
176
161
|
}
|
|
177
162
|
|
|
@@ -288,22 +273,55 @@ const Radisk = (opt: RadiskOptions) => {
|
|
|
288
273
|
done: false,
|
|
289
274
|
count: 0,
|
|
290
275
|
sub: undefined as RadixFunction | undefined,
|
|
291
|
-
|
|
276
|
+
halfKey: "", // soul ID at the ~options.size/2 mark for a balanced split
|
|
277
|
+
halfOffset: 0, // write.text.length before that entry
|
|
278
|
+
each: (
|
|
279
|
+
value: EncodedValue,
|
|
280
|
+
_key: string,
|
|
281
|
+
k: string,
|
|
282
|
+
pre: string[],
|
|
283
|
+
): void | boolean => {
|
|
292
284
|
if (write.done) return
|
|
293
285
|
write.count++
|
|
294
286
|
const valueStr =
|
|
295
287
|
typeof value === "undefined" ? "" : "=" + Radisk.encode(value)
|
|
296
288
|
const enc =
|
|
297
289
|
Radisk.encode(pre.length) + "#" + Radisk.encode(k) + valueStr + "\n"
|
|
290
|
+
const validBoundary =
|
|
291
|
+
pre.length === 0 || (pre.length === 1 && k.includes(enq))
|
|
292
|
+
|
|
293
|
+
// Record the first valid split boundary past the halfway mark so a
|
|
294
|
+
// full overflow can split here instead of at the tail, keeping both
|
|
295
|
+
// halves near options.size/2 rather than leaving the file always full.
|
|
296
|
+
if (
|
|
297
|
+
!write.halfKey &&
|
|
298
|
+
write.count > 1 &&
|
|
299
|
+
write.text.length > options.size / 2 &&
|
|
300
|
+
validBoundary
|
|
301
|
+
) {
|
|
302
|
+
const fullKey = pre.join("") + k
|
|
303
|
+
const endIdx = fullKey.indexOf(enq)
|
|
304
|
+
write.halfKey =
|
|
305
|
+
endIdx === -1 ? fullKey : fullKey.substring(0, endIdx)
|
|
306
|
+
write.halfOffset = write.text.length
|
|
307
|
+
}
|
|
298
308
|
|
|
299
309
|
if (
|
|
300
310
|
write.count > 1 &&
|
|
301
|
-
|
|
302
|
-
|
|
311
|
+
write.text.length + enc.length > options.size &&
|
|
312
|
+
validBoundary
|
|
303
313
|
) {
|
|
304
|
-
const
|
|
305
|
-
|
|
314
|
+
const fullKey = pre.join("") + k
|
|
315
|
+
const endIdx = fullKey.indexOf(enq)
|
|
316
|
+
write.limit =
|
|
317
|
+
write.halfKey ||
|
|
318
|
+
(endIdx === -1 ? fullKey : fullKey.substring(0, endIdx))
|
|
306
319
|
if (write.limit !== file) {
|
|
320
|
+
// Truncate to the balanced split point — text after halfOffset is
|
|
321
|
+
// handled by the write.slice call below, which reads from rad.
|
|
322
|
+
if (write.halfKey) {
|
|
323
|
+
write.text = write.text.substring(0, write.halfOffset)
|
|
324
|
+
}
|
|
307
325
|
write.done = true
|
|
308
326
|
write.sub = Radix()
|
|
309
327
|
Radix.map(rad, write.slice)
|
|
@@ -321,6 +339,13 @@ const Radisk = (opt: RadiskOptions) => {
|
|
|
321
339
|
Radix.map(rad, write.each, true)
|
|
322
340
|
const writeStart = Date.now()
|
|
323
341
|
store.put(file, write.text, err => {
|
|
342
|
+
// If a split occurred the cached radix tree still contains entries that
|
|
343
|
+
// were moved to the sub-file. Invalidate so the next save.mix re-reads
|
|
344
|
+
// from disk rather than re-writing those entries back to this file.
|
|
345
|
+
if (write.done) {
|
|
346
|
+
cache.delete(file)
|
|
347
|
+
fileListCache = null
|
|
348
|
+
}
|
|
324
349
|
perfLog("file-write", writeStart, file, write.text.length)
|
|
325
350
|
cb(err)
|
|
326
351
|
})
|
|
@@ -330,64 +355,45 @@ const Radisk = (opt: RadiskOptions) => {
|
|
|
330
355
|
const endIdx = key.indexOf(enq)
|
|
331
356
|
const soul = endIdx === -1 ? key : key.substring(0, endIdx)
|
|
332
357
|
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
read.value = cachedRadix(key) as EncodedValue | Record<string, EncodedValue> | undefined
|
|
344
|
-
return cb(undefined, read.value)
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
radisk.parse(read.file, read.it)
|
|
348
|
-
return
|
|
349
|
-
}
|
|
358
|
+
const findFile = (files: string[]): string | null => {
|
|
359
|
+
let lo = 0, hi = files.length - 1, result: string | null = null
|
|
360
|
+
while (lo <= hi) {
|
|
361
|
+
const mid = (lo + hi) >> 1
|
|
362
|
+
const f = files[mid]!
|
|
363
|
+
if (f <= soul) { result = f; lo = mid + 1 }
|
|
364
|
+
else { hi = mid - 1 }
|
|
365
|
+
}
|
|
366
|
+
return result
|
|
367
|
+
}
|
|
350
368
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
369
|
+
const read = (file: string | null): void => {
|
|
370
|
+
if (!file) { cb("no file found", undefined); return }
|
|
371
|
+
if (options.cache && cache.has(file)) {
|
|
372
|
+
return cb(undefined, cache.get(file)!(key) as EncodedValue | Record<string, EncodedValue> | undefined)
|
|
373
|
+
}
|
|
374
|
+
radisk.parse(file, (err, disk) => {
|
|
355
375
|
if (err) options.log(err)
|
|
356
|
-
if (disk) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
checkMemoryUsage()
|
|
360
|
-
}
|
|
361
|
-
read.value = disk(key) as EncodedValue | Record<string, EncodedValue> | undefined
|
|
376
|
+
if (disk && options.cache) {
|
|
377
|
+
cache.set(file, disk)
|
|
378
|
+
checkMemoryUsage()
|
|
362
379
|
}
|
|
363
|
-
cb(err,
|
|
364
|
-
}
|
|
365
|
-
file: undefined as string | undefined,
|
|
366
|
-
value: undefined as EncodedValue | Record<string, EncodedValue> | undefined,
|
|
380
|
+
cb(err, disk ? disk(key) as EncodedValue | Record<string, EncodedValue> | undefined : undefined)
|
|
381
|
+
})
|
|
367
382
|
}
|
|
368
383
|
|
|
369
384
|
const now = Date.now()
|
|
370
|
-
if (
|
|
371
|
-
|
|
372
|
-
fileListCache &&
|
|
373
|
-
now - fileListCacheTime < FILE_LIST_CACHE_TTL
|
|
374
|
-
) {
|
|
375
|
-
fileListCache.forEach(file => read.lex(file))
|
|
376
|
-
read.lex()
|
|
385
|
+
if (options.cache && fileListCache && now - fileListCacheTime < FILE_LIST_CACHE_TTL) {
|
|
386
|
+
read(findFile(fileListCache))
|
|
377
387
|
} else {
|
|
378
388
|
const files: string[] = []
|
|
379
|
-
const originalLex = read.lex
|
|
380
|
-
read.lex = (file?: string): void => {
|
|
381
|
-
if (file) files.push(file)
|
|
382
|
-
return originalLex(file)
|
|
383
|
-
}
|
|
384
|
-
|
|
385
389
|
store.list((file?: string) => {
|
|
386
|
-
|
|
387
|
-
|
|
390
|
+
if (file) { files.push(file); return }
|
|
391
|
+
files.sort()
|
|
392
|
+
if (options.cache) {
|
|
388
393
|
fileListCache = files
|
|
389
394
|
fileListCacheTime = now
|
|
390
395
|
}
|
|
396
|
+
read(findFile(files))
|
|
391
397
|
})
|
|
392
398
|
}
|
|
393
399
|
}
|
package/ts/src/schemas.ts
CHANGED
|
@@ -184,7 +184,7 @@ export const WireOptionsSchema = z
|
|
|
184
184
|
.object({
|
|
185
185
|
secure: z.boolean().optional(),
|
|
186
186
|
fast: z.boolean().optional(),
|
|
187
|
-
|
|
187
|
+
put: z.boolean().optional(),
|
|
188
188
|
})
|
|
189
189
|
.optional()
|
|
190
190
|
export type WireOptions = z.infer<typeof WireOptionsSchema>
|
|
@@ -319,7 +319,6 @@ export const RadiskOptionsSchema = z.object({
|
|
|
319
319
|
write: z.number().optional(),
|
|
320
320
|
size: z.number().optional(),
|
|
321
321
|
memoryLimit: z.number().optional(),
|
|
322
|
-
readTimeout: z.number().optional(),
|
|
323
322
|
cache: z.boolean().optional(),
|
|
324
323
|
store: FileSystemInterfaceSchema.optional(),
|
|
325
324
|
})
|
|
@@ -330,7 +329,6 @@ export interface RadiskOptions {
|
|
|
330
329
|
write?: number
|
|
331
330
|
size?: number
|
|
332
331
|
memoryLimit?: number
|
|
333
|
-
readTimeout?: number
|
|
334
332
|
cache?: boolean
|
|
335
333
|
store?: FileSystemInterface
|
|
336
334
|
}
|
|
@@ -404,11 +402,9 @@ export const HolsterOptionsSchema = z
|
|
|
404
402
|
port: z.number().optional(),
|
|
405
403
|
server: z.any().optional(),
|
|
406
404
|
wss: z.any().optional(),
|
|
407
|
-
maxAge: z.number().optional(),
|
|
408
405
|
maxConnections: z.number().optional(),
|
|
409
406
|
maxMessageSize: z.number().optional(),
|
|
410
407
|
maxQueueLength: z.number().optional(),
|
|
411
|
-
wait: z.number().optional(),
|
|
412
408
|
})
|
|
413
409
|
.passthrough()
|
|
414
410
|
export type HolsterOptions = z.infer<typeof HolsterOptionsSchema>
|
package/ts/src/sea-utils.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import SafeBuffer from "./buffer.ts"
|
|
7
7
|
import type { JWK } from "./schemas.ts"
|
|
8
8
|
|
|
9
|
-
const isNode = typeof
|
|
9
|
+
const isNode = typeof process !== "undefined" && process.versions?.node != null
|
|
10
10
|
|
|
11
11
|
// Get crypto based on environment - dynamic import for Node.js compatibility
|
|
12
12
|
const crypto: Crypto = isNode
|
package/ts/src/store.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
EncodedValue,
|
|
16
16
|
} from "./schemas.ts"
|
|
17
17
|
|
|
18
|
-
const isNode = typeof
|
|
18
|
+
const isNode = typeof process !== "undefined" && process.versions?.node != null
|
|
19
19
|
|
|
20
20
|
// Dynamic import for Node.js fs module - won't execute in browser/service worker
|
|
21
21
|
const fs = isNode
|
package/ts/src/user.ts
CHANGED
|
@@ -38,7 +38,6 @@ export interface UserInterface {
|
|
|
38
38
|
*/
|
|
39
39
|
const User = (opt: HolsterOptions | undefined, wire?: WireInterface): UserInterface => {
|
|
40
40
|
if (!wire) wire = Wire(opt as HolsterOptions)
|
|
41
|
-
const wait = opt?.wait ?? 5000
|
|
42
41
|
let pubs: string[] = []
|
|
43
42
|
let creating = false
|
|
44
43
|
let authing = false
|
|
@@ -117,7 +116,6 @@ const User = (opt: HolsterOptions | undefined, wire?: WireInterface): UserInterf
|
|
|
117
116
|
|
|
118
117
|
done(null)
|
|
119
118
|
},
|
|
120
|
-
{ wait: wait }
|
|
121
119
|
)
|
|
122
120
|
}
|
|
123
121
|
|
|
@@ -142,7 +140,6 @@ const User = (opt: HolsterOptions | undefined, wire?: WireInterface): UserInterf
|
|
|
142
140
|
pubs = Object.keys(data)
|
|
143
141
|
next()
|
|
144
142
|
},
|
|
145
|
-
{ wait: wait }
|
|
146
143
|
)
|
|
147
144
|
}
|
|
148
145
|
|
|
@@ -221,7 +218,6 @@ const User = (opt: HolsterOptions | undefined, wire?: WireInterface): UserInterf
|
|
|
221
218
|
})
|
|
222
219
|
})
|
|
223
220
|
},
|
|
224
|
-
{ wait: wait }
|
|
225
221
|
)
|
|
226
222
|
},
|
|
227
223
|
auth: (username, password, cb) => {
|