@mblaney/holster 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ts/src/index.ts CHANGED
@@ -1,35 +1,34 @@
1
1
  /**
2
2
  * Holster TypeScript Entry Point
3
- *
3
+ *
4
4
  * This is the main entry point for the TypeScript version of Holster.
5
5
  * It exports all the main modules and types.
6
6
  */
7
7
 
8
8
  // Main API
9
- export { default as Holster, type HolsterAPI } from "./holster.ts"
9
+ export {default as Holster, type HolsterAPI} from "./holster.ts"
10
10
 
11
11
  // Core modules
12
- export { default as Wire, type WireAPI } from "./wire.ts"
13
- export { default as User, type UserInterface } from "./user.ts"
14
- export { default as SEA } from "./sea.ts"
15
- export { default as Store, type StoreInterface } from "./store.ts"
12
+ export {default as Wire, type WireAPI} from "./wire.ts"
13
+ export {default as User, type UserInterface} from "./user.ts"
14
+ export {default as SEA} from "./sea.ts"
15
+ export {default as Store, type StoreInterface} from "./store.ts"
16
16
 
17
17
  // Data structure modules
18
- export { default as Ham } from "./ham.ts"
19
- export { default as Get } from "./get.ts"
20
- export { default as Radisk } from "./radisk.ts"
21
- export { default as Radix } from "./radix.ts"
22
- export { default as Dup, type DupInterface } from "./dup.ts"
18
+ export {default as Ham} from "./ham.ts"
19
+ export {default as Get} from "./get.ts"
20
+ export {default as Radisk} from "./radisk.ts"
21
+ export {default as Radix} from "./radix.ts"
22
+ export {default as Dup, type DupInterface} from "./dup.ts"
23
23
 
24
24
  // Utilities
25
25
  export * as utils from "./utils.ts"
26
26
  export * as seaUtils from "./sea-utils.ts"
27
- export { default as SafeBuffer } from "./buffer.ts"
28
- export { default as SeaArray } from "./array.ts"
27
+ export {default as SafeBuffer} from "./buffer.ts"
28
+ export {default as SeaArray} from "./array.ts"
29
29
 
30
30
  // Types and Schemas
31
31
  export * from "./schemas.ts"
32
32
 
33
33
  // Default export
34
- export { default } from "./holster.ts"
35
-
34
+ export {default} from "./holster.ts"
package/ts/src/radisk.ts CHANGED
@@ -4,9 +4,14 @@
4
4
  */
5
5
 
6
6
  import Radix from "./radix.ts"
7
- import type { RadixFunction } from "./schemas.ts"
7
+ import type {RadixFunction} from "./schemas.ts"
8
8
  import * as utils from "./utils.ts"
9
- import type { EncodedValue, RadiskOptions, GraphValue, Relation } from "./schemas.ts"
9
+ import type {
10
+ EncodedValue,
11
+ RadiskOptions,
12
+ GraphValue,
13
+ Relation,
14
+ } from "./schemas.ts"
10
15
 
11
16
  // ASCII character for end of text
12
17
  const etx = String.fromCharCode(3)
@@ -18,8 +23,18 @@ const unit = String.fromCharCode(31)
18
23
  export interface RadiskInterface extends RadixFunction {
19
24
  // Override call signature to support both get (with callback) and put (with value and optional callback)
20
25
  // Accepts GraphValue (raw values) OR EncodedValue (tuples) - see src/radisk.js and tests
21
- (key?: string, value?: GraphValue | EncodedValue | ((err?: string | null, value?: EncodedValue | Record<string, EncodedValue>) => void), cb?: (err?: string | null) => void): void
22
-
26
+ (
27
+ key?: string,
28
+ value?:
29
+ | GraphValue
30
+ | EncodedValue
31
+ | ((
32
+ err?: string | null,
33
+ value?: EncodedValue | Record<string, EncodedValue>,
34
+ ) => void),
35
+ cb?: (err?: string | null) => void,
36
+ ): void
37
+
23
38
  batch: RadixFunction & {
24
39
  acks: Array<(err?: string | null) => void>
25
40
  ed: number
@@ -32,9 +47,22 @@ export interface RadiskInterface extends RadixFunction {
32
47
  more?: boolean
33
48
  }
34
49
  save: (rad: RadixFunction, cb: (err?: string | null) => void) => void
35
- write: (file: string, rad: RadixFunction, cb: (err?: string | null) => void) => void
36
- read: (key: string, cb: (err?: string | null, value?: EncodedValue | Record<string, EncodedValue>) => void) => void
37
- parse: (file: string, cb: (err?: string | null, disk?: RadixFunction) => void) => void
50
+ write: (
51
+ file: string,
52
+ rad: RadixFunction,
53
+ cb: (err?: string | null) => void,
54
+ ) => void
55
+ read: (
56
+ key: string,
57
+ cb: (
58
+ err?: string | null,
59
+ value?: EncodedValue | Record<string, EncodedValue>,
60
+ ) => void,
61
+ ) => void
62
+ parse: (
63
+ file: string,
64
+ cb: (err?: string | null, disk?: RadixFunction) => void,
65
+ ) => void
38
66
  }
39
67
 
40
68
  /**
@@ -48,7 +76,12 @@ const Radisk = (opt: RadiskOptions) => {
48
76
 
49
77
  const pendingReads = new Map<
50
78
  string,
51
- Array<(err?: string | null, result?: EncodedValue | Record<string, EncodedValue>) => void>
79
+ Array<
80
+ (
81
+ err?: string | null,
82
+ result?: EncodedValue | Record<string, EncodedValue>,
83
+ ) => void
84
+ >
52
85
  >()
53
86
 
54
87
  let lastMemoryCheck = 0
@@ -67,30 +100,27 @@ const Radisk = (opt: RadiskOptions) => {
67
100
  }
68
101
 
69
102
  if (!options.store) {
70
- throw new Error("Radisk needs `store` interface with `{get: fn, put: fn, list: fn}`")
103
+ throw new Error(
104
+ "Radisk needs `store` interface with `{get: fn, put: fn, list: fn}`",
105
+ )
71
106
  }
72
107
  if (!options.store.get) {
73
108
  throw new Error("Radisk needs `store.get` interface with `(file, cb)`")
74
109
  }
75
110
  if (!options.store.put) {
76
- throw new Error("Radisk needs `store.put` interface with `(file, data, cb)`")
111
+ throw new Error(
112
+ "Radisk needs `store.put` interface with `(file, data, cb)`",
113
+ )
77
114
  }
78
115
  if (!options.store.list) {
79
- throw new Error("Radisk needs a streaming `store.list` interface with `(cb)`")
116
+ throw new Error(
117
+ "Radisk needs a streaming `store.list` interface with `(cb)`",
118
+ )
80
119
  }
81
120
 
82
121
  // After validation, store is guaranteed to be defined
83
122
  const store = options.store
84
123
 
85
- const perfLog = (operation: string, startTime: number, key: string, size?: number): void => {
86
- const duration = Date.now() - startTime
87
- if (duration > 3000) {
88
- console.log(
89
- `[RADISK-SLOW] ${operation}: ${duration}ms for ${key}${size ? ` (${size} bytes)` : ""}`
90
- )
91
- }
92
- }
93
-
94
124
  const checkMemoryUsage = (): void => {
95
125
  if (typeof process === "undefined" || !process.memoryUsage) return
96
126
 
@@ -106,21 +136,31 @@ const Radisk = (opt: RadiskOptions) => {
106
136
  if (heapUsageRatio > HEAP_CLEANUP_THRESHOLD) {
107
137
  const cacheSize = cache.size
108
138
  console.log(
109
- `[RADISK-MEMORY] High memory usage: ${Math.round(heapUsageRatio * 100)}% of heap limit. Clearing ${cacheSize} cached files.`
139
+ `[RADISK-MEMORY] High memory usage: ${Math.round(heapUsageRatio * 100)}% of heap limit. Clearing ${cacheSize} cached files.`,
110
140
  )
111
141
  cache.clear()
112
- if ((global as { gc?: () => void }).gc) {
113
- (global as { gc: () => void }).gc()
142
+ if ((global as {gc?: () => void}).gc) {
143
+ ;(global as {gc: () => void}).gc()
114
144
  }
115
145
  lastMemoryCheck = now + MEMORY_CHECK_INTERVAL
116
146
  } else if (heapUsageRatio > HEAP_WARNING_THRESHOLD) {
117
147
  console.log(
118
- `[RADISK-MEMORY] Memory warning: ${Math.round(heapUsageRatio * 100)}% of heap limit used. Cache size: ${cache.size} files.`
148
+ `[RADISK-MEMORY] Memory warning: ${Math.round(heapUsageRatio * 100)}% of heap limit used. Cache size: ${cache.size} files.`,
119
149
  )
120
150
  }
121
151
  }
122
152
 
123
- const radisk = ((key?: string, value?: GraphValue | EncodedValue | ((err?: string | null, value?: EncodedValue | Record<string, EncodedValue>) => void), cb?: (err?: string | null) => void) => {
153
+ const radisk = ((
154
+ key?: string,
155
+ value?:
156
+ | GraphValue
157
+ | EncodedValue
158
+ | ((
159
+ err?: string | null,
160
+ value?: EncodedValue | Record<string, EncodedValue>,
161
+ ) => void),
162
+ cb?: (err?: string | null) => void,
163
+ ) => {
124
164
  if (typeof key !== "string") return undefined
125
165
 
126
166
  if (typeof value === "function") {
@@ -143,7 +183,6 @@ const Radisk = (opt: RadiskOptions) => {
143
183
  }
144
184
 
145
185
  pendingReads.set(key, [callback])
146
- const readStart = Date.now()
147
186
  const timeout = setTimeout(() => {
148
187
  const callbacks = pendingReads.get(key)
149
188
  if (!callbacks) return
@@ -153,7 +192,6 @@ const Radisk = (opt: RadiskOptions) => {
153
192
  }, 30000)
154
193
  return radisk.read(key, (err, result) => {
155
194
  clearTimeout(timeout)
156
- perfLog("read", readStart, key)
157
195
  const callbacks = pendingReads.get(key) || []
158
196
  pendingReads.delete(key)
159
197
  callbacks.forEach(callback => callback(err, result))
@@ -184,7 +222,6 @@ const Radisk = (opt: RadiskOptions) => {
184
222
  return
185
223
  }
186
224
 
187
- const thrashStart = Date.now()
188
225
  clearTimeout(radisk.batch.timeout)
189
226
  radisk.thrash.more = false
190
227
  radisk.thrash.ing = true
@@ -196,7 +233,6 @@ const Radisk = (opt: RadiskOptions) => {
196
233
  radisk.save(batch, err => {
197
234
  if (++i > 1) return
198
235
 
199
- perfLog("thrash", thrashStart, `batch-${batch.ed}`)
200
236
  if (err) options.log(err)
201
237
  batch.acks.forEach(cb => cb(err))
202
238
  radisk.thrash.at = undefined
@@ -273,7 +309,7 @@ const Radisk = (opt: RadiskOptions) => {
273
309
  done: false,
274
310
  count: 0,
275
311
  sub: undefined as RadixFunction | undefined,
276
- halfKey: "", // soul ID at the ~options.size/2 mark for a balanced split
312
+ halfKey: "", // soul ID at the ~options.size/2 mark for a balanced split
277
313
  halfOffset: 0, // write.text.length before that entry
278
314
  each: (
279
315
  value: EncodedValue,
@@ -301,8 +337,7 @@ const Radisk = (opt: RadiskOptions) => {
301
337
  ) {
302
338
  const fullKey = pre.join("") + k
303
339
  const endIdx = fullKey.indexOf(enq)
304
- write.halfKey =
305
- endIdx === -1 ? fullKey : fullKey.substring(0, endIdx)
340
+ write.halfKey = endIdx === -1 ? fullKey : fullKey.substring(0, endIdx)
306
341
  write.halfOffset = write.text.length
307
342
  }
308
343
 
@@ -337,7 +372,6 @@ const Radisk = (opt: RadiskOptions) => {
337
372
  },
338
373
  }
339
374
  Radix.map(rad, write.each, true)
340
- const writeStart = Date.now()
341
375
  store.put(file, write.text, err => {
342
376
  // If a split occurred the cached radix tree still contains entries that
343
377
  // were moved to the sub-file. Invalidate so the next save.mix re-reads
@@ -346,7 +380,6 @@ const Radisk = (opt: RadiskOptions) => {
346
380
  cache.delete(file)
347
381
  fileListCache = null
348
382
  }
349
- perfLog("file-write", writeStart, file, write.text.length)
350
383
  cb(err)
351
384
  })
352
385
  }
@@ -356,20 +389,35 @@ const Radisk = (opt: RadiskOptions) => {
356
389
  const soul = endIdx === -1 ? key : key.substring(0, endIdx)
357
390
 
358
391
  const findFile = (files: string[]): string | null => {
359
- let lo = 0, hi = files.length - 1, result: string | null = null
392
+ let lo = 0,
393
+ hi = files.length - 1,
394
+ result: string | null = null
360
395
  while (lo <= hi) {
361
396
  const mid = (lo + hi) >> 1
362
397
  const f = files[mid]!
363
- if (f <= soul) { result = f; lo = mid + 1 }
364
- else { hi = mid - 1 }
398
+ if (f <= soul) {
399
+ result = f
400
+ lo = mid + 1
401
+ } else {
402
+ hi = mid - 1
403
+ }
365
404
  }
366
405
  return result
367
406
  }
368
407
 
369
408
  const read = (file: string | null): void => {
370
- if (!file) { cb("no file found", undefined); return }
409
+ if (!file) {
410
+ cb("no file found", undefined)
411
+ return
412
+ }
371
413
  if (options.cache && cache.has(file)) {
372
- return cb(undefined, cache.get(file)!(key) as EncodedValue | Record<string, EncodedValue> | undefined)
414
+ return cb(
415
+ undefined,
416
+ cache.get(file)!(key) as
417
+ | EncodedValue
418
+ | Record<string, EncodedValue>
419
+ | undefined,
420
+ )
373
421
  }
374
422
  radisk.parse(file, (err, disk) => {
375
423
  if (err) options.log(err)
@@ -377,17 +425,32 @@ const Radisk = (opt: RadiskOptions) => {
377
425
  cache.set(file, disk)
378
426
  checkMemoryUsage()
379
427
  }
380
- cb(err, disk ? disk(key) as EncodedValue | Record<string, EncodedValue> | undefined : undefined)
428
+ cb(
429
+ err,
430
+ disk
431
+ ? (disk(key) as
432
+ | EncodedValue
433
+ | Record<string, EncodedValue>
434
+ | undefined)
435
+ : undefined,
436
+ )
381
437
  })
382
438
  }
383
439
 
384
440
  const now = Date.now()
385
- if (options.cache && fileListCache && now - fileListCacheTime < FILE_LIST_CACHE_TTL) {
441
+ if (
442
+ options.cache &&
443
+ fileListCache &&
444
+ now - fileListCacheTime < FILE_LIST_CACHE_TTL
445
+ ) {
386
446
  read(findFile(fileListCache))
387
447
  } else {
388
448
  const files: string[] = []
389
449
  store.list((file?: string) => {
390
- if (file) { files.push(file); return }
450
+ if (file) {
451
+ files.push(file)
452
+ return
453
+ }
391
454
  files.sort()
392
455
  if (options.cache) {
393
456
  fileListCache = files
@@ -401,7 +464,10 @@ const Radisk = (opt: RadiskOptions) => {
401
464
  radisk.parse = (file, cb) => {
402
465
  const parse = {
403
466
  disk: Radix(),
404
- read: (err?: string | null, data?: string | EncodedValue | Record<string, unknown>): void => {
467
+ read: (
468
+ err?: string | null,
469
+ data?: string | EncodedValue | Record<string, unknown>,
470
+ ): void => {
405
471
  if (err) return cb(err)
406
472
  if (!data) return cb(null, parse.disk)
407
473
 
@@ -412,7 +478,12 @@ const Radisk = (opt: RadiskOptions) => {
412
478
  let key: string | undefined
413
479
  let value: EncodedValue | undefined
414
480
  const tmpVal = tmp[1]
415
- const i = typeof tmpVal === "number" ? tmpVal : (typeof tmpVal === "string" ? parseInt(tmpVal, 10) : 0)
481
+ const i =
482
+ typeof tmpVal === "number"
483
+ ? tmpVal
484
+ : typeof tmpVal === "string"
485
+ ? parseInt(tmpVal, 10)
486
+ : 0
416
487
  tmp = parse.split(tmp[2]) || ("" as never)
417
488
  if (tmp[0] === "#") {
418
489
  const tmpKey = tmp[1]
@@ -439,16 +510,14 @@ const Radisk = (opt: RadiskOptions) => {
439
510
  }
440
511
  cb(null, parse.disk)
441
512
  },
442
- split: (
443
- data: string
444
- ): [string, unknown, string] | undefined => {
513
+ split: (data: string): [string, unknown, string] | undefined => {
445
514
  if (!data) return undefined
446
515
 
447
516
  const i = data.indexOf(unit)
448
517
  if (i === -1) return undefined
449
518
 
450
519
  const a = data.slice(0, i)
451
- const o: { i?: number } = {}
520
+ const o: {i?: number} = {}
452
521
  return [a, Radisk.decode(data.slice(i), o), data.slice(i + o.i!)]
453
522
  },
454
523
  }
@@ -466,7 +535,7 @@ Radisk.encode = (input: EncodedValue | GraphValue): string => {
466
535
  let state = ""
467
536
  let sig = ""
468
537
  let data: GraphValue
469
-
538
+
470
539
  if (Array.isArray(input) && (input.length === 2 || input.length === 3)) {
471
540
  // input is EncodedValue - extract the GraphValue and metadata
472
541
  state = etx + input[1]
@@ -506,7 +575,10 @@ Radisk.encode = (input: EncodedValue | GraphValue): string => {
506
575
  /**
507
576
  * Decode value from storage
508
577
  */
509
- Radisk.decode = (data: string, obj?: { i?: number }): EncodedValue | GraphValue | Relation | null | undefined => {
578
+ Radisk.decode = (
579
+ data: string,
580
+ obj?: {i?: number},
581
+ ): EncodedValue | GraphValue | Relation | null | undefined => {
510
582
  let i = -1
511
583
  let n = 0
512
584
  let current: string | undefined = undefined
@@ -588,4 +660,3 @@ Radisk.decode = (data: string, obj?: { i?: number }): EncodedValue | GraphValue
588
660
  }
589
661
 
590
662
  export default Radisk
591
-
package/ts/src/radix.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import * as utils from "./utils.ts"
7
- import type { EncodedValue, RadixFunction } from "./schemas.ts"
7
+ import type {EncodedValue, RadixFunction} from "./schemas.ts"
8
8
 
9
9
  // ASCII character for group separator
10
10
  const group = String.fromCharCode(29)
@@ -34,10 +34,11 @@ const Radix = (): RadixFunction => {
34
34
  const radix = ((
35
35
  keys?: string,
36
36
  value?: EncodedValue,
37
- tree?: RadixTree
37
+ tree?: RadixTree,
38
38
  ): RadixNode | EncodedValue | undefined | Record<string, EncodedValue> => {
39
39
  if (!tree) {
40
- if (!(radix as Record<string, unknown>)[group]) (radix as Record<string, unknown>)[group] = {}
40
+ if (!(radix as Record<string, unknown>)[group])
41
+ (radix as Record<string, unknown>)[group] = {}
41
42
  tree = (radix as Record<string, RadixTree>)[group]!
42
43
  }
43
44
  if (!keys) return tree
@@ -57,32 +58,35 @@ const Radix = (): RadixFunction => {
57
58
 
58
59
  if (!found) {
59
60
  // If not found from the provided keys try matching with an existing key
60
- const result = utils.obj.map(tree!, (hasValue: RadixValue, hasKey: string) => {
61
- let j = 0
62
- let matchingKey = ""
63
- while (hasKey[j] === keys[j]) {
64
- matchingKey += hasKey[j]
65
- j++
66
- }
67
- if (matchingKey) {
68
- if (noValue) {
69
- // matchingKey has to be as long as the original keys when reading
70
- if (j <= max) return undefined
71
-
72
- tmp[hasKey.slice(j)] = hasValue
73
- return hasValue
61
+ const result = utils.obj.map(
62
+ tree!,
63
+ (hasValue: RadixValue, hasKey: string) => {
64
+ let j = 0
65
+ let matchingKey = ""
66
+ while (hasKey[j] === keys[j]) {
67
+ matchingKey += hasKey[j]
68
+ j++
74
69
  }
75
-
76
- const replace: RadixTree = {
77
- [hasKey.slice(j)]: hasValue,
78
- [keys.slice(j)]: { [record]: value! },
70
+ if (matchingKey) {
71
+ if (noValue) {
72
+ // matchingKey has to be as long as the original keys when reading
73
+ if (j <= max) return undefined
74
+
75
+ tmp[hasKey.slice(j)] = hasValue
76
+ return hasValue
77
+ }
78
+
79
+ const replace: RadixTree = {
80
+ [hasKey.slice(j)]: hasValue,
81
+ [keys.slice(j)]: {[record]: value!},
82
+ }
83
+ tree![matchingKey] = {[group]: replace}
84
+ delete tree![hasKey]
85
+ return true
79
86
  }
80
- tree![matchingKey] = { [group]: replace }
81
- delete tree![hasKey]
82
- return true
83
- }
84
- return undefined
85
- })
87
+ return undefined
88
+ },
89
+ )
86
90
 
87
91
  if (!result) {
88
92
  if (noValue) return undefined
@@ -96,7 +100,9 @@ const Radix = (): RadixFunction => {
96
100
  // If no value use the key provided to return a whole group or record
97
101
  if (noValue) {
98
102
  // If an individual record isn't found then return the whole group
99
- return typeof found[record] === "undefined" ? found[group] : found[record]
103
+ return typeof found[record] === "undefined"
104
+ ? found[group]
105
+ : found[record]
100
106
  }
101
107
  // Otherwise create a new record at the provided key for value
102
108
  found[record] = value!
@@ -120,22 +126,33 @@ const Radix = (): RadixFunction => {
120
126
  */
121
127
  Radix.map = function map(
122
128
  radix: RadixFunction | RadixNode,
123
- cb: (value: EncodedValue, fullKey: string, key: string, pre: string[]) => unknown,
129
+ cb: (
130
+ value: EncodedValue,
131
+ fullKey: string,
132
+ key: string,
133
+ pre: string[],
134
+ ) => unknown,
124
135
  opt?: boolean,
125
- pre: string[] = []
136
+ pre: string[] = [],
126
137
  ): unknown {
127
- const tree = ((radix as Record<string, RadixTree>)[group] || radix) as RadixTree
138
+ const tree = ((radix as Record<string, RadixTree>)[group] ||
139
+ radix) as RadixTree
128
140
  const keys = Object.keys(tree).sort()
129
141
 
130
142
  for (let i = 0; i < keys.length; i++) {
131
143
  const key = keys[i]!
132
144
  const found = tree[key]
133
145
  if (!found) continue
134
-
146
+
135
147
  const recordValue = found[record]
136
148
 
137
149
  if (typeof recordValue !== "undefined") {
138
- const result = cb(recordValue as EncodedValue, pre.join("") + key, key, pre)
150
+ const result = cb(
151
+ recordValue as EncodedValue,
152
+ pre.join("") + key,
153
+ key,
154
+ pre,
155
+ )
139
156
  if (typeof result !== "undefined") return result
140
157
  } else if (opt) {
141
158
  cb(undefined as never, pre.join(""), key, pre)
@@ -154,4 +171,3 @@ Radix.map = function map(
154
171
  }
155
172
 
156
173
  export default Radix
157
-
package/ts/src/schemas.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { z } from "zod"
1
+ import {z} from "zod"
2
2
 
3
3
  // ============================================================================
4
4
  // Core Primitive Types
@@ -48,7 +48,7 @@ export const GraphValueSchema: z.ZodType<GraphValue> = z.lazy(() =>
48
48
  z.null(),
49
49
  RelationSchema,
50
50
  z.record(z.string(), GraphValueSchema),
51
- ])
51
+ ]),
52
52
  )
53
53
 
54
54
  export type GraphValue =
@@ -57,7 +57,7 @@ export type GraphValue =
57
57
  | boolean
58
58
  | null
59
59
  | Relation
60
- | { [key: string]: GraphValue }
60
+ | {[key: string]: GraphValue}
61
61
 
62
62
  /**
63
63
  * State vector - tracks timestamps for each property
@@ -91,9 +91,11 @@ export const USER_SIGNATURE = "_holster_user_signature"
91
91
  * Graph node - contains metadata and properties
92
92
  * Note: Using manual type to properly handle the index signature with special _ key
93
93
  */
94
- export const GraphNodeSchema = z.object({
95
- _: GraphMetadataSchema,
96
- }).and(z.record(z.string(), GraphValueSchema))
94
+ export const GraphNodeSchema = z
95
+ .object({
96
+ _: GraphMetadataSchema,
97
+ })
98
+ .and(z.record(z.string(), GraphValueSchema))
97
99
 
98
100
  export type GraphNode = {
99
101
  _: GraphMetadata
@@ -141,9 +143,7 @@ export const LexFilterSchema = z.union([
141
143
  export type LexFilter = z.infer<typeof LexFilterSchema>
142
144
 
143
145
  // LexFilter with optional "." property for nested queries
144
- export type LexWithDot =
145
- | LexFilter
146
- | { ".": LexFilter }
146
+ export type LexWithDot = LexFilter | {".": LexFilter}
147
147
 
148
148
  /**
149
149
  * Lex query object
@@ -294,8 +294,18 @@ export const FileSystemInterfaceSchema = z.object({
294
294
  // FileSystemInterface: Flexible to support both string-based and EncodedValue storage
295
295
  // In-memory stores use strings, disk stores use EncodedValue/RadixNode
296
296
  export interface FileSystemInterface {
297
- get: (file: string, cb: (err?: string | null, data?: string | EncodedValue | Record<string, unknown>) => void) => void
298
- put: (file: string, data: string | EncodedValue | Record<string, unknown>, cb: (err?: string | null) => void) => void
297
+ get: (
298
+ file: string,
299
+ cb: (
300
+ err?: string | null,
301
+ data?: string | EncodedValue | Record<string, unknown>,
302
+ ) => void,
303
+ ) => void
304
+ put: (
305
+ file: string,
306
+ data: string | EncodedValue | Record<string, unknown>,
307
+ cb: (err?: string | null) => void,
308
+ ) => void
299
309
  list: (cb: (file?: string) => void) => void
300
310
  }
301
311
 
@@ -405,6 +415,9 @@ export const HolsterOptionsSchema = z
405
415
  maxConnections: z.number().optional(),
406
416
  maxMessageSize: z.number().optional(),
407
417
  maxQueueLength: z.number().optional(),
418
+ userLimit: z.boolean().optional(),
419
+ defaultLimit: z.number().optional(),
420
+ maxGraphSize: z.number().optional(),
408
421
  })
409
422
  .passthrough()
410
423
  export type HolsterOptions = z.infer<typeof HolsterOptionsSchema>
@@ -462,20 +475,28 @@ export type RadixValue = GraphValue | EncodedValue | RadixNode
462
475
  */
463
476
  export type RadixFunction = {
464
477
  // Main call signature: synchronous get/put operations
465
- (keys?: string, value?: GraphValue | EncodedValue, tree?: RadixNode):
466
- RadixNode | EncodedValue | undefined | Record<string, EncodedValue>
467
-
478
+ (
479
+ keys?: string,
480
+ value?: GraphValue | EncodedValue,
481
+ tree?: RadixNode,
482
+ ): RadixNode | EncodedValue | undefined | Record<string, EncodedValue>
483
+
468
484
  // Callback form: async operations
469
485
  (key?: string, value?: RadixValue, cb?: (err?: string) => void): void
470
-
486
+
471
487
  // Static map method for iterating over radix tree values
472
488
  map: (
473
- radix: RadixFunction | RadixNode,
474
- cb: (value: EncodedValue, fullKey: string, key: string, pre: string[]) => unknown,
489
+ radix: RadixFunction | RadixNode,
490
+ cb: (
491
+ value: EncodedValue,
492
+ fullKey: string,
493
+ key: string,
494
+ pre: string[],
495
+ ) => unknown,
475
496
  opt?: boolean,
476
- pre?: string[]
497
+ pre?: string[],
477
498
  ) => unknown
478
-
499
+
479
500
  // Dynamic properties for internal state (e.g., group separator key)
480
501
  [key: string]: unknown
481
502
  }
@@ -506,10 +527,9 @@ export type Dup = z.infer<typeof DupSchema> & {
506
527
  // ============================================================================
507
528
 
508
529
  // Export RadiskInterface from radisk module for test usage
509
- export type { RadiskInterface } from "./radisk.ts"
530
+ export type {RadiskInterface} from "./radisk.ts"
510
531
 
511
532
  // Export other interfaces for test usage
512
- export type { WireAPI as WireInterface } from "./wire.ts"
513
- export type { UserInterface } from "./user.ts"
514
- export type { StoreInterface } from "./store.ts"
515
-
533
+ export type {WireAPI as WireInterface} from "./wire.ts"
534
+ export type {UserInterface} from "./user.ts"
535
+ export type {StoreInterface} from "./store.ts"