corebasic 1.0.232 → 1.0.234

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/libs/elabase.ts CHANGED
@@ -15,7 +15,7 @@ export const shard_stats = ShardStats
15
15
 
16
16
 
17
17
  let Events = {
18
- send: function(topic?: string, data?: any) { }
18
+ send: function(_topic?: string, _data?: any) { }
19
19
  }
20
20
 
21
21
 
@@ -24,7 +24,7 @@ let Events = {
24
24
  const url = process.env.DIP_URL || "http://127.0.0.1"; // Set DIP_URL to "http://dip" (Prod) or http://dip-dev (Dev) in CI/CD
25
25
  let port = process.env.DIP_PORT || 9401
26
26
  let api = 'execute'
27
- let fullurl = `${url}:${port}/${api}`
27
+ // let fullurl = `${url}:${port}/${api}`
28
28
 
29
29
 
30
30
  let Elabase = {
@@ -38,8 +38,10 @@ let Elabase = {
38
38
  }
39
39
  }
40
40
 
41
+ type Internal = {db: undefined | string, engineName: "lmdb" | "sled" | "sanakirja"}
42
+
41
43
  let engine = Elabase.Engine.Lmdb
42
- let internal = {
44
+ let internal: Internal = {
43
45
  db: undefined,
44
46
  engineName: engine === Elabase.Engine.Lmdb ? "lmdb" : (engine === Elabase.Engine.Sled ? "sled" : engine === Elabase.Engine.Sanakirja ? "sanakirja" : "lmdb")
45
47
  }
@@ -47,14 +49,14 @@ let internal = {
47
49
  let db = internal.db // default database
48
50
 
49
51
 
50
- export function start(dbName) {
52
+ export function start(dbName: string) {
51
53
  if (!Utils.isEmpty(dbName) && Utils.isEmpty(db)) {
52
54
  internal.db = "data/" + dbName
53
55
  db = "data/" + dbName
54
56
  }
55
57
  }
56
58
 
57
- function deepFreeze(obj) {
59
+ function deepFreeze(obj: Record<string, any>) {
58
60
  if (obj && typeof obj === "object" && !Object.isFrozen(obj)) {
59
61
  Object.freeze(obj);
60
62
 
@@ -65,20 +67,28 @@ function deepFreeze(obj) {
65
67
  return obj;
66
68
  }
67
69
  export class DipMeta {
68
- declare company?: string;
69
- declare outlet?: string;
70
-
71
- constructor(obj) {
70
+ declare company?: string | string[];
71
+ declare outlet?: string | string[];
72
+ declare suffix?: string | string[];
73
+ declare syncMode?: boolean;
74
+ declare db?: string;
75
+ declare DIP_DB?: string;
76
+ declare DIP_URL?: string;
77
+ declare executor?: "native" | "raw";
78
+ declare batch?: string;
79
+ declare allowDangerousRemove?: boolean;
80
+
81
+ constructor(obj: Record<string, unknown>) {
72
82
  Object.assign(this, deepFreeze(obj));
73
83
  Object.freeze(this);
74
84
  }
75
85
  }
76
- export const isDipMeta = meta => meta instanceof DipMeta
86
+ export const isDipMeta = (meta: DipMeta) => meta instanceof DipMeta
77
87
 
78
88
  export const globalMeta = (args?: any) => {
79
89
  return new DipMeta({ ...args, company: "GLOBAL", outlet: "GLOBAL" })
80
90
  }
81
- export const companyMeta = (company, args?: any) => {
91
+ export const companyMeta = (company: string | string[], args?: any) => {
82
92
  if (typeof company !== "string" && !Array.isArray(company))
83
93
  throw new Error("Error: Invalid company provided in Dip.companyMeta()")
84
94
  if (!company || (typeof company === "string" && company.trim() === "") || company === "GLOBAL" || (Array.isArray(company) && (!company.length || company.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL")) ))
@@ -86,7 +96,7 @@ export const companyMeta = (company, args?: any) => {
86
96
 
87
97
  return new DipMeta({...args, outlet: "GLOBAL", company})
88
98
  }
89
- export const outletMeta = (outlet, args?: any) => {
99
+ export const outletMeta = (outlet: string | string[], args?: any) => {
90
100
  if (typeof outlet !== "string" && !Array.isArray(outlet))
91
101
  throw new Error("Error: Invalid outlet provided in Dip.outletMeta()")
92
102
  if (!outlet || (typeof outlet === "string" && outlet.trim() === "") || outlet === "GLOBAL" || (Array.isArray(outlet) && (!outlet.length || outlet.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL")) ))
@@ -95,7 +105,7 @@ export const outletMeta = (outlet, args?: any) => {
95
105
  return new DipMeta({...args, company: "GLOBAL", outlet})
96
106
  }
97
107
 
98
- export const customMeta = (company, outlet, args?: any) => {
108
+ export const customMeta = (company: string | string[], outlet: string | string[], args?: any) => {
99
109
 
100
110
  if (typeof company !== "string" && !Array.isArray(company))
101
111
  throw new Error("Error: Invalid company provided in Dip.customMeta()")
@@ -110,13 +120,13 @@ export const customMeta = (company, outlet, args?: any) => {
110
120
  return new DipMeta({...args, company, outlet})
111
121
  }
112
122
 
113
- function validate_collection(collection, fn_name) {
123
+ function validate_collection(collection: string | string[], fn_name: string) {
114
124
  if ((typeof collection === 'string' && collection.trim() === "") || (typeof collection !== 'string' && !Array.isArray(collection)) || (Array.isArray(collection) && (!collection.length || collection.some(item => typeof item !== "string" || item.trim() === "")))) {
115
125
  throw new Error(`Error: Invalid collection ${fn_name}`)
116
126
  }
117
127
  }
118
128
 
119
- function validate_meta(meta, fn_name) {
129
+ function validate_meta(meta: DipMeta, fn_name: string) {
120
130
  if (!meta || typeof meta !== 'object') {
121
131
  throw new Error(`Error: Invalid meta ${fn_name}`)
122
132
  }
@@ -132,7 +142,7 @@ function validate_meta(meta, fn_name) {
132
142
  throw new Error(`Error: Invalid meta.suffix ${fn_name}`)
133
143
  }
134
144
 
135
- function generate_suffix(meta) {
145
+ function generate_suffix(meta: DipMeta) {
136
146
 
137
147
  // Assuming validate_meta() is called before reaching here. If not then this is intentional validation bypass
138
148
 
@@ -148,9 +158,9 @@ function generate_suffix(meta) {
148
158
  outlet = outlet.length ? outlet : [""]
149
159
  suffix = suffix.length ? suffix : [""]
150
160
 
151
- company = new Set(company)
152
- outlet = new Set(outlet)
153
- suffix = new Set(suffix)
161
+ company = [...new Set(company)]
162
+ outlet = [...new Set(outlet)]
163
+ suffix = [...new Set(suffix)]
154
164
 
155
165
  // console.log(company, outlet, suffix)
156
166
  let suffixes = []
@@ -170,21 +180,36 @@ function generate_suffix(meta) {
170
180
 
171
181
  // Ported
172
182
  let BATCH_COUNTER = 0n;
173
- let batches = {}
183
+ let batches: Record<string, (InsertRequest | QueryRequest | UpdateRequest | RemoveRequest)[]> = {}
174
184
 
175
185
  // Ported
176
- export function batchBegin() { // Manual Lifecycle. If you forget to batchSubmit() or batchAbort(), then memory leak due to dangling batch
177
- const uid = ++BATCH_COUNTER; // Safe. No skew in async ++BATCH_COUNTER as single thread and ++COUNTER is atomic in event loop sense. ⚠️ Only breaks on worker_threads or cluster (multi-process)
178
- batches[uid.toString()] = []
186
+ export function batchBegin(): string { // Manual Lifecycle. If you forget to batchSubmit() or batchAbort(), then memory leak due to dangling batch
187
+ const uid = (++BATCH_COUNTER).toString(); // Safe. No skew in async ++BATCH_COUNTER. Single thread ++COUNTER is atomic in event loop sense. ⚠️ Breaks on worker_threads or cluster (multi-process)
188
+ batches[uid] = []
179
189
  return uid
180
190
  }
181
191
  // Ported
182
- export function batchAbort(batch_id) { // Mandatory to prevent meory leak due to dangling batch if batchBegin() is called without batchSubmit()
192
+ export function batchAbort(batch_id: string) { // Mandatory to prevent meory leak due to dangling batch if batchBegin() is called without batchSubmit()
183
193
  delete batches[batch_id]
184
194
  }
185
195
 
196
+
197
+ type BufferItem = {buf: Buffer | Uint8Array; vlq: Uint8Array}
198
+ type HashItem = {buf: Buffer | Uint8Array; offset: number}
199
+ type RawManager = {
200
+ buffers: BufferItem[];
201
+ size: number;
202
+ hashes: Map<bigint, HashItem[]>;
203
+ add: (value: Buffer | string | number | any) => number | undefined;
204
+ }
205
+
206
+ type BatchArg = {
207
+ db?: string, collection?: string | string[], suffix?: string | string[],
208
+ executor?: "native" | "raw" | undefined, syncMode?: false | undefined, raw?: RawManager | undefined, engine?: string | undefined, port?: number | undefined, timeout?: number | undefined, version?: boolean | undefined, compression?: boolean | undefined
209
+ }
210
+
186
211
  // Ported
187
- export const batch = async (callback, arg) => { // Convenience function with auto lifecyle management and auto submit when callback returns. abort is called appropriately.
212
+ export const batch = async (callback: (batch_id: string) => Promise<void>, arg: BatchArg) => { // Convenience function with auto lifecyle management and auto submit when callback returns. abort is called appropriately.
188
213
  /**
189
214
  * Usage:
190
215
  * const result = await Dip.batch(async batch => {
@@ -205,8 +230,9 @@ export const batch = async (callback, arg) => { // Convenience function with aut
205
230
  }
206
231
  }
207
232
 
233
+
208
234
  // Ported
209
- export function batchSubmit(batch_id, arg) {
235
+ export function batchSubmit(batch_id: string, arg: BatchArg) {
210
236
  if (!batch_id || !batches[batch_id] || !batches[batch_id].length)
211
237
  throw new Error(`Error: Invalid batch in Dip.batchSubmit()`)
212
238
  let txns = batches[batch_id]
@@ -217,8 +243,8 @@ export function batchSubmit(batch_id, arg) {
217
243
  const port = arg?.port
218
244
  const timeout = arg?.timeout
219
245
  delete batches[batch_id]
220
- return new Promise<void>((resolve, reject) => resolve())
221
- .then(() => execute({ "batch": txns, version: arg?.version, raw, engine, compression: arg?.compression, executor, syncMode, port, timeout }))
246
+ return new Promise<void>((resolve, _reject) => resolve())
247
+ .then(() => execute({ "batch": txns, version: arg?.version, raw, engine, compression: arg?.compression, executor: executor ?? "native", syncMode: syncMode ?? false, port, timeout }))
222
248
  .then (result => {
223
249
  Events.send("Dip.batchSubmit", { response: result })
224
250
  return result
@@ -229,8 +255,8 @@ let PROJECT_ROOT_URL = new URL('../../..', import.meta.url)
229
255
  if (String(PROJECT_ROOT_URL).endsWith('node_modules/'))
230
256
  PROJECT_ROOT_URL = new URL('..', PROJECT_ROOT_URL)
231
257
 
232
- const SCHEMAS_JSON_PROMISES = {}
233
- export const schema = async (name) => {
258
+ const SCHEMAS_JSON_PROMISES: Record<string, Promise<unknown>> = {}
259
+ export const schema = async (name: string) => {
234
260
  // Cache the loading promise right away so parallel requests share it
235
261
  if (!SCHEMAS_JSON_PROMISES[name])
236
262
  SCHEMAS_JSON_PROMISES[name] = Utils.fileToJson(PROJECT_ROOT_URL, `schemas/${name}.json`)
@@ -245,18 +271,26 @@ export const schema = async (name) => {
245
271
  }
246
272
  }
247
273
 
248
- const COLLECTIONS_JSON = await (async () => {
274
+
275
+ type CoreConfig = { company?: string | {}, outlet?: string | {}, }
276
+ type CollectionConfig = CoreConfig & { suffix?: Record<string, CoreConfig> }
277
+
278
+ type SuffixItem = { key?: string; value?: string; type: string; ls_threshold?: number; min?: number; max?: number }
279
+ type CollectionsJsonType = Record<string, CollectionConfig & {policy?: {when: object, suffix: SuffixItem[]}[]}>
280
+
281
+ const COLLECTIONS_JSON: CollectionsJsonType = await (async () => {
249
282
  try {
250
- return await Utils.fileToJson(PROJECT_ROOT_URL, 'collections.json')
283
+ return await Utils.fileToJson(PROJECT_ROOT_URL, 'collections.json') as CollectionsJsonType
251
284
  } catch(e) {
252
285
  console.error(e)
253
286
  console.warn("Warn: Dip Failed to load collections.json. Semantics, topology and legality enforcement is not active")
254
287
  }
288
+ return {}
255
289
  })();
256
290
 
257
291
  function init_collections_config() {
258
292
  for (let collection in COLLECTIONS_JSON) {
259
- let config = COLLECTIONS_JSON[collection]
293
+ let config = COLLECTIONS_JSON[collection]!
260
294
  if (config.suffix !== undefined && (typeof config.suffix !== "object" || Array.isArray(config.suffix)) ) {
261
295
  throw new Error(`Error: Initiating collection configs failed. Invalid suffix in collection: ${collection}`)
262
296
  }
@@ -265,15 +299,16 @@ function init_collections_config() {
265
299
  if (COLLECTIONS_JSON)
266
300
  init_collections_config()
267
301
 
268
- const EXCLUDED_COLLECTIONS_CONFIG = {}
269
- export function excludeCollectionConfig(collection) {
302
+ const EXCLUDED_COLLECTIONS_CONFIG: Record<string, boolean> = {}
303
+ export function excludeCollectionConfig(collection: string) {
270
304
  EXCLUDED_COLLECTIONS_CONFIG[collection] = true
271
305
  }
272
- export function includeCollectionConfig(collection) {
306
+ export function includeCollectionConfig(collection: string) {
273
307
  delete EXCLUDED_COLLECTIONS_CONFIG[collection]
274
308
  }
275
309
 
276
- function validate_topology(meta, collection, fn_name) {
310
+ function validate_topology(meta: DipMeta, cols: string | string[], fn_name: string) {
311
+ const collection = typeof cols === "string" ? cols : cols[0]! // TODO: arrays
277
312
 
278
313
  let new_meta = meta
279
314
 
@@ -284,7 +319,7 @@ function validate_topology(meta, collection, fn_name) {
284
319
  return new_meta
285
320
  }
286
321
 
287
- function check_core_meta(config, meta, suffix?: string) {
322
+ function check_core_meta(config: CoreConfig, meta: DipMeta, suffix?: string) {
288
323
  if (config.company !== meta.company && typeof config.company !== "object")
289
324
  throw new Error(`Error: Incompatible meta.company config for collection: ${collection}${suffix ? ' suffix: ' + suffix : ''}${fn_name ? ` ${fn_name}` : ''}`)
290
325
  if (config.outlet !== meta.outlet && typeof config.outlet !== "object")
@@ -293,13 +328,14 @@ function validate_topology(meta, collection, fn_name) {
293
328
 
294
329
  check_core_meta(config, meta)
295
330
 
296
- if (config.suffix && meta.suffix) {
297
- if (!config.suffix[meta.suffix]) {
298
- console.warn(`Warn: Missing suffix config for collection: ${collection} suffix:${meta.suffix}${fn_name ? ` ${fn_name}` : ''}`)
331
+ const meta_suffix = meta.suffix as string // TODO: use loop
332
+ if (config.suffix && meta_suffix) {
333
+ if (!config.suffix[meta_suffix]) {
334
+ console.warn(`Warn: Missing suffix config for collection: ${collection} suffix:${meta_suffix}${fn_name ? ` ${fn_name}` : ''}`)
299
335
  return new_meta
300
336
  }
301
- check_core_meta(config.suffix[meta.suffix], meta, meta.suffix)
302
- new_meta = Object.assign({}, {...config, suffix: undefined, company: undefined, outlet: undefined}, {...config.suffix[meta.suffix], company: undefined, outlet: undefined}, meta)
337
+ check_core_meta(config.suffix[meta_suffix], meta, meta_suffix)
338
+ new_meta = Object.assign({}, {...config, suffix: undefined, company: undefined, outlet: undefined}, {...config.suffix[meta_suffix], company: undefined, outlet: undefined}, meta)
303
339
  } else {
304
340
  new_meta = Object.assign({}, {...config, suffix: undefined, company: undefined, outlet: undefined}, {company: undefined, outlet: undefined}, meta)
305
341
  }
@@ -308,7 +344,7 @@ function validate_topology(meta, collection, fn_name) {
308
344
  }
309
345
 
310
346
  // Ported
311
- export const operation = async (name, extras) => {
347
+ export const operation = async (name: string, extras: BatchArg) => {
312
348
  return execute({ operation: name, ...extras })
313
349
  }
314
350
 
@@ -318,6 +354,8 @@ type Options = {
318
354
  idempotent: boolean;
319
355
  $orderby: any;
320
356
  $fields: any;
357
+ $rangeFrom: any;
358
+ $rangeTo: any;
321
359
  _id?: string | number;
322
360
  }
323
361
  type InsertRequest = {
@@ -325,11 +363,11 @@ type InsertRequest = {
325
363
  executor: "native" | "raw";
326
364
  collection: string[];
327
365
  suffix: string | string[];
328
- _id?: string | number;
366
+ _id?: string | number | undefined;
329
367
  insert: number | any;
330
368
  options: Options;
331
- syncMode: boolean;
332
- DIP_URL?: string;
369
+ syncMode?: boolean;
370
+ DIP_URL?: string | undefined;
333
371
  DIP_DB?: string;
334
372
  }
335
373
 
@@ -337,8 +375,22 @@ type QueryRequest = Omit<InsertRequest, "_id" | "insert"> & { query: any }
337
375
  type UpdateRequest = Omit<InsertRequest, "insert"> & { query: any, update: any }
338
376
  type RemoveRequest = QueryRequest & { delete: true }
339
377
 
378
+ type BatchItem = (InsertRequest | QueryRequest | UpdateRequest | RemoveRequest)
379
+ type DipRequest = Omit<BatchItem, "syncMode" | "collection" | "suffix" | "options" | "executor" | "db" | "_id"> &
380
+ Omit<BatchArg, "syncMode" | "collection" | "suffix" | "options" | "executor" | "db" | "_id"> & {
381
+ batch?: BatchItem[],
382
+ syncMode?: boolean | undefined,
383
+ operation?: string,
384
+ options?: Options,
385
+ executor?: "native" | "raw" | undefined,
386
+ db?: string,
387
+ collection?: string | string[],
388
+ suffix?: string | string[],
389
+ _id?: string | number | undefined,
390
+ }
391
+
340
392
  // Ported
341
- export const insert = async (meta, collection, value, options?: any, extras?: any) => {
393
+ export const insert = async (meta: DipMeta, collection: string | string[], value: any, options?: any, extras?: any) => {
342
394
 
343
395
  if (!(meta instanceof DipMeta)) console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.insert()') // TODO: throw error once review completes
344
396
 
@@ -352,7 +404,7 @@ export const insert = async (meta, collection, value, options?: any, extras?: an
352
404
  collection: typeof collection === "string" ? [collection] : collection,
353
405
  insert: value,
354
406
  options: options ? options : {},
355
- syncMode: meta.syncMode,
407
+ syncMode: meta.syncMode ?? false,
356
408
  db: extras?.db ?? meta?.db ?? db,
357
409
  ...(meta.DIP_URL ? {DIP_URL: meta.DIP_URL} : {}),
358
410
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
@@ -373,10 +425,10 @@ export const insert = async (meta, collection, value, options?: any, extras?: an
373
425
  if (meta.batch) {
374
426
  if (!batches[meta.batch])
375
427
  throw new Error('Error: Invalid batch in Dip.insert()')
376
- batches[meta.batch].push(arg)
428
+ batches[meta.batch]!.push(arg)
377
429
  return
378
430
  }
379
- return new Promise<void>((resolve, reject) => resolve())
431
+ return new Promise<void>((resolve, _reject) => resolve())
380
432
  .then(() => execute(arg))
381
433
  .then(result => {
382
434
  Events.send("Dip.insert", { collection: collectionArray(collection), response: result })
@@ -385,7 +437,7 @@ export const insert = async (meta, collection, value, options?: any, extras?: an
385
437
  }
386
438
 
387
439
  // Ported
388
- export const query = async (meta, collection, query, options?: any, extras?: any) => {
440
+ export const query = async (meta: DipMeta, collection: string | string[], query: any, options?: any, extras?: any) => {
389
441
 
390
442
  if (!(meta instanceof DipMeta)) console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.query()') // TODO: throw error once review completes
391
443
 
@@ -399,7 +451,7 @@ export const query = async (meta, collection, query, options?: any, extras?: any
399
451
  collection: typeof collection === "string" ? [collection] : collection,
400
452
  query: query,
401
453
  options: options ? options : {},
402
- syncMode: meta.syncMode,
454
+ syncMode: meta.syncMode ?? false,
403
455
  db: extras?.db ?? meta?.db ?? db,
404
456
  ...(meta.DIP_URL ? {DIP_URL: meta.DIP_URL} : {}),
405
457
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
@@ -415,32 +467,21 @@ export const query = async (meta, collection, query, options?: any, extras?: any
415
467
  if (meta.batch) {
416
468
  if (!batches[meta.batch])
417
469
  throw new Error('Error: Invalid batch in Dip.query()')
418
- batches[meta.batch].push(arg)
470
+ batches[meta.batch]!.push(arg)
419
471
  return
420
472
  }
421
- return new Promise<void>((resolve, reject) => resolve())
473
+ return new Promise<void>((resolve, _reject) => resolve())
422
474
  .then(() => execute(arg))
423
475
  }
424
476
 
425
477
 
426
- function collectionArray(col) {
427
- let type = Object.prototype.toString.call(col)
428
- if (type === '[object Array]') {
429
- let newcol = []
430
- for (let i in col) {
431
- if (!Utils.isEmpty(col[i]))
432
- newcol.push(col[i])
433
- }
434
- return newcol
435
- } else if (type === '[object String]') {
436
- if (!Utils.isEmpty(col))
437
- return [col]
438
- }
439
- return []
478
+ function collectionArray(col: string | string[]) {
479
+ const collections = typeof col === 'string' ? [col] : Array.isArray(col) ? col : []
480
+ return collections.filter(collection => collection.trim())
440
481
  }
441
482
 
442
483
  // Ported
443
- export const update = async (meta, collection, query, update, options?: any, extras?: any) => {
484
+ export const update = async (meta: DipMeta, collection: string | string[], query: any, update: any, options?: any, extras?: any) => {
444
485
 
445
486
  if (!(meta instanceof DipMeta)) console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.update()') // TODO: throw error once review completes
446
487
 
@@ -455,7 +496,7 @@ export const update = async (meta, collection, query, update, options?: any, ext
455
496
  query: query,
456
497
  update: update,
457
498
  options: options ? options : {},
458
- syncMode: meta.syncMode,
499
+ syncMode: meta.syncMode ?? false,
459
500
  db: extras?.db ?? meta?.db ?? db,
460
501
  ...(meta.DIP_URL ? {DIP_URL: meta.DIP_URL} : {}),
461
502
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
@@ -471,10 +512,10 @@ export const update = async (meta, collection, query, update, options?: any, ext
471
512
  if (meta.batch) {
472
513
  if (!batches[meta.batch])
473
514
  throw new Error('Error: Invalid batch in Dip.update()')
474
- batches[meta.batch].push(arg)
515
+ batches[meta.batch]!.push(arg)
475
516
  return
476
517
  }
477
- return new Promise<void>((resolve, reject) => resolve())
518
+ return new Promise<void>((resolve, _reject) => resolve())
478
519
  .then(() => execute(arg))
479
520
  .then (result => {
480
521
  Events.send("Dip.update", { collection: collectionArray(collection), response: result })
@@ -483,7 +524,7 @@ export const update = async (meta, collection, query, update, options?: any, ext
483
524
  }
484
525
 
485
526
  // Ported
486
- export const remove = async (meta, collection, query, options?: any, extras?: any) => {
527
+ export const remove = async (meta: DipMeta, collection: string | string[], query: any, options?: any, extras?: any) => {
487
528
 
488
529
  if (!(meta instanceof DipMeta)) console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.remove()') // TODO: throw error once review completes
489
530
 
@@ -501,7 +542,7 @@ export const remove = async (meta, collection, query, options?: any, extras?: an
501
542
  query: query,
502
543
  options: options ? options : {},
503
544
  delete: true,
504
- syncMode: meta.syncMode,
545
+ syncMode: meta.syncMode ?? false,
505
546
  db: extras?.db ?? meta?.db ?? db,
506
547
  ...(meta.DIP_URL ? {DIP_URL: meta.DIP_URL} : {}),
507
548
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
@@ -517,10 +558,10 @@ export const remove = async (meta, collection, query, options?: any, extras?: an
517
558
  if (meta.batch) {
518
559
  if (!batches[meta.batch])
519
560
  throw new Error('Error: Invalid batch in Dip.query()')
520
- batches[meta.batch].push(arg)
561
+ batches[meta.batch]!.push(arg)
521
562
  return
522
563
  }
523
- return new Promise<void>((resolve, reject) => resolve())
564
+ return new Promise<void>((resolve, _reject) => resolve())
524
565
  .then(() => execute(arg))
525
566
  .then(result => {
526
567
  Events.send("Dip.remove", { collection: collectionArray(collection), response: result })
@@ -528,13 +569,19 @@ export const remove = async (meta, collection, query, options?: any, extras?: an
528
569
  })
529
570
  }
530
571
 
531
-
572
+ type BinaryResponse = {metadata: any, content: any}
573
+ type DipResponse = AxiosResponse & {
574
+ body: any;
575
+ getSliceAsText(offset: number, length: number): string;
576
+ getSliceAsArrayBuffer(offset: number, length: number): Buffer;
577
+ "Content-Type"?: string;
578
+ };
532
579
 
533
580
  export let config = {
534
581
  useDipper: false
535
582
  }
536
583
 
537
- function execute(arg) {
584
+ function execute(arg: DipRequest) {
538
585
  // arg example
539
586
  // {
540
587
  // db: "middle-earth",
@@ -546,7 +593,7 @@ function execute(arg) {
546
593
 
547
594
  // _id: 1 // Optional. Used with insert
548
595
  // }
549
- arg.db = arg.db ?? db
596
+ arg.db = arg.db ? arg.db : db ? db : ''
550
597
  arg.executor = arg.executor ?? "native"
551
598
  arg.engine = arg.engine ?? internal.engineName
552
599
  if (arg.compression === undefined)
@@ -559,20 +606,14 @@ function execute(arg) {
559
606
  delete arg.timeout
560
607
 
561
608
 
562
- return config.useDipper ? dipper(arg)
609
+ return config.useDipper ? dipper(arg)
563
610
  : axios
564
611
  .post(arg.DIP_URL ?? fullurl, buildHybridRequest({...arg, DIP_URL: undefined}), { responseType: 'arraybuffer', timeout: timeout ?? 5000, headers: {"Content-Type": "application/dip"} })
565
- .then(dip_result => {
612
+ .then((dip_result: AxiosResponse) => {
566
613
  // console.log(res.status);
567
614
  // console.log(JSON.stringify(res.header, null, 4));
568
615
  // console.log(JSON.stringify(res.body, null, 4));
569
616
 
570
- type DipResponse = AxiosResponse & {
571
- body: any;
572
- getSliceAsText(offset: number, length: number): string;
573
- getSliceAsArrayBuffer(offset: number, length: number): Buffer;
574
- "Content-Type"?: string;
575
- };
576
617
 
577
618
  const result = dip_result as DipResponse
578
619
 
@@ -608,7 +649,7 @@ let Essentials = {
608
649
 
609
650
 
610
651
 
611
- function prepareResult(result) {
652
+ function prepareResult(result: BinaryResponse) {
612
653
  let res = result.content?.length === 1 ? result.content[0].items : result.content // For raw, this resolves to result.content which is ArrayBuffer
613
654
  res.metadata = () => result.metadata
614
655
  if (result.metadata.executor === "raw")
@@ -616,7 +657,7 @@ function prepareResult(result) {
616
657
  return res
617
658
  }
618
659
 
619
- function parseBinaryResponse(result) {
660
+ function parseBinaryResponse(result: DipResponse): BinaryResponse {
620
661
  const contentType = (result["Content-Type"] || "").toLowerCase()
621
662
  if (contentType.includes("application/json")) {
622
663
  return {metadata: result.body, content: result.body.items}
@@ -639,7 +680,7 @@ function parseBinaryResponse(result) {
639
680
 
640
681
  // parseWireFormat() equivalent
641
682
  // =============================
642
- let dataView = new DataView(arrayBuffer.buffer, arrayBuffer.byteOffset, arrayBuffer.byteLength);
683
+ // let dataView = new DataView(arrayBuffer.buffer, arrayBuffer.byteOffset, arrayBuffer.byteLength);
643
684
  let offset = 0;
644
685
 
645
686
  // 1. Read the metadata size header
@@ -659,9 +700,20 @@ function parseBinaryResponse(result) {
659
700
  return { metadata: nativeResponse, content: content }
660
701
  }
661
702
 
703
+ type RawBatchBuffer = Uint8Array & {
704
+ metadata(): {
705
+ items: {
706
+ offset: number
707
+ size: number
708
+ count: number
709
+ kv: () => void
710
+ }[]
711
+ }
712
+ items?: unknown
713
+ }
662
714
 
663
- function setRawBatchIterator(arrayBuffer) {
664
- arrayBuffer.metadata().items.forEach(batch => {
715
+ function setRawBatchIterator(arrayBuffer: RawBatchBuffer) {
716
+ arrayBuffer.metadata().items.forEach((batch: {offset: number, size: number, count: number, kv: () => void}) => {
665
717
  batch.kv = () => {
666
718
  const batchItem = {
667
719
  count: batch.count,
@@ -695,7 +747,7 @@ function setRawBatchIterator(arrayBuffer) {
695
747
 
696
748
 
697
749
 
698
- function convert_to_array_buffer(value) {
750
+ function convert_to_array_buffer(value: ArrayBuffer | string | number | any) {
699
751
  if (typeof value === "string")
700
752
  return Essentials.stringToUtf8ArrayBuffer(value)
701
753
  else if (typeof value === "number")
@@ -703,20 +755,12 @@ function convert_to_array_buffer(value) {
703
755
  return Essentials.stringToUtf8ArrayBuffer(JSON.stringify(value))
704
756
  }
705
757
 
706
- export function newRaw() {
707
- type BufferItem = {buf: ArrayBuffer | Uint8Array; vlq: Uint8Array}
708
- type HashItem = {buf: ArrayBuffer | Uint8Array; offset: number}
709
- type RawManager = {
710
- buffers: BufferItem[];
711
- size: number;
712
- hashes: Map<bigint, HashItem[]>;
713
- add: (value: ArrayBuffer | string | number | any) => number;
714
- }
715
- let obj: RawManager = {buffers: [], size: 0, hashes: new Map()} as RawManager
716
- obj.add = (value: ArrayBuffer | string | number | any): number => {
758
+ export function newRaw(): RawManager {
759
+ let obj: RawManager = {buffers: [], size: 0, hashes: new Map(), add: (_value: Buffer | string | number | any) => 0} as RawManager
760
+ obj.add = (value: Buffer | string | number | any): number | undefined => {
717
761
  if (value === undefined)
718
762
  return undefined
719
- const buf = (value instanceof ArrayBuffer) ? value : convert_to_array_buffer(value);
763
+ const buf = (value instanceof Buffer) ? value : convert_to_array_buffer(value);
720
764
 
721
765
  const hash = Essentials.defaultHash(buf)
722
766
  for (const item of obj.hashes.get(hash) ?? []) { // Conflict. Fallback to verify
@@ -732,14 +776,16 @@ export function newRaw() {
732
776
 
733
777
  if (!obj.hashes.get(hash))
734
778
  obj.hashes.set(hash, [])
735
- obj.hashes.get(hash).push({offset, buf})
779
+ obj.hashes.get(hash)!.push({offset, buf})
736
780
 
737
781
  return offset
738
782
  }
739
783
  return obj
740
784
  }
741
785
 
742
- function buildHybridRequest(request) {
786
+
787
+
788
+ function buildHybridRequest(request: DipRequest) {
743
789
  const batch = request.batch ?? [request];
744
790
 
745
791
  let raw = request.raw ?? newRaw()
@@ -747,23 +793,23 @@ function buildHybridRequest(request) {
747
793
 
748
794
  // Pass 1: Direct offset assignment & exact size calculation (Zero allocation)
749
795
  for (let i = 0; i < batch.length; i++) {
750
- const item = batch[i];
751
- delete item.batch
752
- if (item.update) {
753
- if ( item._id === undefined && item.options?.upsert && item.query?._id !== undefined)
754
- item._id = item.query._id
755
- item.update = raw.add(item.update)
756
- } else if (item.insert) {
757
- if (item._id === undefined && item.insert?._id !== undefined)
758
- item._id = item.insert._id
759
- item.insert = raw.add(item.insert)
796
+ const item = batch[i]!;
797
+ delete (item as DipRequest).batch
798
+ if ((item as UpdateRequest).update) {
799
+ if ( (item as UpdateRequest)._id === undefined && (item as UpdateRequest).options?.upsert && (item as UpdateRequest).query?._id !== undefined)
800
+ (item as UpdateRequest)._id = (item as UpdateRequest).query._id;
801
+ (item as UpdateRequest).update = raw.add((item as UpdateRequest).update)
802
+ } else if ((item as InsertRequest).insert) {
803
+ if ((item as InsertRequest)._id === undefined && (item as InsertRequest).insert?._id !== undefined)
804
+ (item as InsertRequest)._id = (item as InsertRequest).insert._id;
805
+ (item as InsertRequest).insert = raw.add((item as InsertRequest).insert)
760
806
  }
761
- item._id = raw.add(item._id)
807
+ (item as InsertRequest | UpdateRequest)._id = raw.add((item as InsertRequest | UpdateRequest)._id)
762
808
 
763
809
  if (item.options?.$rangeFrom !== undefined)
764
810
  item.options.$rangeFrom = raw.add(item.options.$rangeFrom)
765
- if (item.options?.$rangeTo !== undefined)
766
- item.options.$rangeTo = raw.add(item.options.$rangeTo)
811
+ if (item.options?.$rangeTo !== undefined)
812
+ item.options.$rangeTo = raw.add(item.options.$rangeTo)
767
813
  }
768
814
 
769
815
  // Pass 2: Generate the final JSON payload string
@@ -815,12 +861,12 @@ function buildHybridRequest(request) {
815
861
 
816
862
 
817
863
 
818
- function bufferToString(arrayBuffer) {
819
- return Essentials.arrayBufferToString(arrayBuffer)
864
+ function bufferToString(arrayBuffer: string | undefined | ArrayBuffer | SharedArrayBuffer | Buffer) {
865
+ return Essentials.arrayBufferToString(arrayBuffer as Buffer)
820
866
  }
821
867
 
822
- function getRawKeyValue(arrayBuffer, offset) {
823
- let dataView = new DataView(arrayBuffer.buffer, arrayBuffer.byteOffset, arrayBuffer.byteLength);
868
+ function getRawKeyValue(arrayBuffer: Uint8Array, offset: number) {
869
+ // let dataView = new DataView(arrayBuffer.buffer, arrayBuffer.byteOffset, arrayBuffer.byteLength);
824
870
  let masterView = new Uint8Array(arrayBuffer);
825
871
 
826
872
  // 1. Extract Key Size and Key
@@ -834,7 +880,7 @@ function getRawKeyValue(arrayBuffer, offset) {
834
880
 
835
881
  // Zero-copy view window bounded strictly to the key bytes
836
882
  let _id = masterView.subarray(offset, offset + keySize) as EnhancedUint8Array;
837
- let _id_string
883
+ let _id_string: string | undefined | ArrayBuffer | SharedArrayBuffer
838
884
  _id.toText = () => {
839
885
  // Fix: Pass the typed array view itself, NOT the underlying root buffer
840
886
  _id_string = _id_string === undefined ? _id.buffer.slice(_id.byteOffset, _id.byteOffset + _id.byteLength) : _id_string