corebasic 1.0.229 → 1.0.231

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.
@@ -2,6 +2,7 @@ import { describe, test } from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
  import {matchPolicy, overlaps, contains, intersects, applySuffixPolicy} from "../policy.ts";
4
4
 
5
+ const defaultBounds = {values: [], from: -Infinity, to: Infinity, fromOp: "$gte", toOp: "$lte"}
5
6
 
6
7
  /* ============================================================
7
8
  * overlaps()
@@ -10,35 +11,35 @@ describe("overlaps()", () => {
10
11
 
11
12
  test("overlaps: identical ranges", () => {
12
13
  assert.equal(
13
- overlaps({ from: 10, to: 20 }, { from: 10, to: 20 }),
14
+ overlaps({ ...defaultBounds, from: 10, to: 20 }, { ...defaultBounds, from: 10, to: 20 }),
14
15
  true
15
16
  );
16
17
  });
17
18
 
18
19
  test("overlaps: partial overlap", () => {
19
20
  assert.equal(
20
- overlaps({ from: 10, to: 20 }, { from: 15, to: 25 }),
21
+ overlaps({ ...defaultBounds, from: 10, to: 20 }, { ...defaultBounds, from: 15, to: 25 }),
21
22
  true
22
23
  );
23
24
  });
24
25
 
25
26
  test("overlaps: no overlap", () => {
26
27
  assert.equal(
27
- overlaps({ from: 10, to: 20 }, { from: 21, to: 30 }),
28
+ overlaps({ ...defaultBounds, from: 10, to: 20 }, { ...defaultBounds, from: 21, to: 30 }),
28
29
  false
29
30
  );
30
31
  });
31
32
 
32
33
  test("overlaps: open ended lower", () => {
33
34
  assert.equal(
34
- overlaps({ to: 10 }, { from: 5 }),
35
+ overlaps({ ...defaultBounds, to: 10 }, { ...defaultBounds, from: 5 }),
35
36
  true
36
37
  );
37
38
  });
38
39
 
39
40
  test("overlaps: open ended upper", () => {
40
41
  assert.equal(
41
- overlaps({ from: 20 }, { to: 10 }),
42
+ overlaps({ ...defaultBounds, from: 20 }, { ...defaultBounds, to: 10 }),
42
43
  false
43
44
  );
44
45
  });
@@ -48,39 +49,28 @@ describe("overlaps()", () => {
48
49
 
49
50
  test("touching: open/open does not overlap", () => {
50
51
  assert.equal(
51
- overlaps(
52
- { to: 10, toOp: "$lt" },
53
- { from: 10, fromOp: "$gt" }
54
- ),
52
+ overlaps({ ...defaultBounds, to: 10, toOp: "$lt" }, { ...defaultBounds, from: 10, fromOp: "$gt" }),
55
53
  false
56
54
  );
57
55
  });
58
56
 
59
57
  test("touching: closed/closed overlaps", () => {
60
58
  assert.equal(
61
- overlaps(
62
- { to: 10, toOp: "$lte" },
63
- { from: 10, fromOp: "$gte" }
64
- ),
59
+ overlaps({ ...defaultBounds, to: 10, toOp: "$lte" }, { ...defaultBounds, from: 10, fromOp: "$gte" }),
65
60
  true
66
61
  );
67
62
  });
68
63
 
69
64
  test("touching: closed/open does not overlap", () => {
70
65
  assert.equal(
71
- overlaps(
72
- { to: 10, toOp: "$lte" },
73
- { from: 10, fromOp: "$gt" }
74
- ),
66
+ overlaps({ ...defaultBounds, to: 10, toOp: "$lte" }, { ...defaultBounds, from: 10, fromOp: "$gt" }),
75
67
  false
76
68
  );
77
69
  });
78
70
 
79
71
  test("touching: open/closed does not overlap", () => {
80
72
  assert.equal(
81
- overlaps(
82
- { to: 10, toOp: "$lt" },
83
- { from: 10, fromOp: "$gte" }
73
+ overlaps({ ...defaultBounds, to: 10, toOp: "$lt" }, { ...defaultBounds, from: 10, fromOp: "$gte" }
84
74
  ),
85
75
  false
86
76
  );
@@ -88,80 +78,42 @@ describe("overlaps()", () => {
88
78
 
89
79
  test("touching: reverse order closed/closed overlaps", () => {
90
80
  assert.equal(
91
- overlaps(
92
- { from: 10, fromOp: "$gte" },
93
- { to: 10, toOp: "$lte" }
94
- ),
81
+ overlaps({ ...defaultBounds, from: 10, fromOp: "$gte" }, { ...defaultBounds, to: 10, toOp: "$lte" }),
95
82
  true
96
83
  );
97
84
  });
98
85
 
99
86
  test("touching: reverse order open/open does not overlap", () => {
100
87
  assert.equal(
101
- overlaps(
102
- { from: 10, fromOp: "$gt" },
103
- { to: 10, toOp: "$lt" }
104
- ),
88
+ overlaps({ ...defaultBounds, from: 10, fromOp: "$gt" }, { ...defaultBounds, to: 10, toOp: "$lt" }),
105
89
  false
106
90
  );
107
91
  });
108
92
 
109
93
  test("identical single-point closed intervals overlap", () => {
110
94
  assert.equal(
111
- overlaps(
112
- {
113
- from: 10,
114
- to: 10,
115
- fromOp: "$gte",
116
- toOp: "$lte"
117
- },
118
- {
119
- from: 10,
120
- to: 10,
121
- fromOp: "$gte",
122
- toOp: "$lte"
123
- }
124
- ),
95
+ overlaps({ ...defaultBounds, from: 10, to: 10, fromOp: "$gte", toOp: "$lte" }, { ...defaultBounds, from: 10, to: 10, fromOp: "$gte", toOp: "$lte" }),
125
96
  true
126
97
  );
127
98
  });
128
99
 
129
100
  test("identical single-point open intervals do not overlap", () => {
130
101
  assert.equal(
131
- overlaps(
132
- {
133
- from: 10,
134
- to: 10,
135
- fromOp: "$gt",
136
- toOp: "$lt"
137
- },
138
- {
139
- from: 10,
140
- to: 10,
141
- fromOp: "$gt",
142
- toOp: "$lt"
143
- }
144
- ),
102
+ overlaps({ ...defaultBounds, from: 10, to: 10, fromOp: "$gt", toOp: "$lt" }, { ...defaultBounds, from: 10, to: 10, fromOp: "$gt", toOp: "$lt" }),
145
103
  false
146
104
  );
147
105
  });
148
106
 
149
107
  test("infinite lower bound with touching closed endpoint overlaps", () => {
150
108
  assert.equal(
151
- overlaps(
152
- { to: 5, toOp: "$lte" },
153
- { from: 5, fromOp: "$gte" }
154
- ),
109
+ overlaps({ ...defaultBounds, to: 5, toOp: "$lte" }, { ...defaultBounds, from: 5, fromOp: "$gte" }),
155
110
  true
156
111
  );
157
112
  });
158
113
 
159
114
  test("infinite lower bound with touching open endpoint does not overlap", () => {
160
115
  assert.equal(
161
- overlaps(
162
- { to: 5, toOp: "$lt" },
163
- { from: 5, fromOp: "$gt" }
164
- ),
116
+ overlaps({ ...defaultBounds, to: 5, toOp: "$lt" }, { ...defaultBounds, from: 5, fromOp: "$gt" }),
165
117
  false
166
118
  );
167
119
  });
@@ -178,35 +130,35 @@ describe("contains()", () => {
178
130
 
179
131
  test("contains: inside", () => {
180
132
  assert.equal(
181
- contains({ from: 10, to: 20 }, 15),
133
+ contains({ ...defaultBounds, from: 10, to: 20 }, 15),
182
134
  true
183
135
  );
184
136
  });
185
137
 
186
138
  test("contains: below", () => {
187
139
  assert.equal(
188
- contains({ from: 10, to: 20 }, 5),
140
+ contains({ ...defaultBounds, from: 10, to: 20 }, 5),
189
141
  false
190
142
  );
191
143
  });
192
144
 
193
145
  test("contains: above", () => {
194
146
  assert.equal(
195
- contains({ from: 10, to: 20 }, 25),
147
+ contains({ ...defaultBounds, from: 10, to: 20 }, 25),
196
148
  false
197
149
  );
198
150
  });
199
151
 
200
152
  test("contains: lower bound", () => {
201
153
  assert.equal(
202
- contains({ from: 10, to: 20 }, 10),
154
+ contains({ ...defaultBounds, from: 10, to: 20 }, 10),
203
155
  true
204
156
  );
205
157
  });
206
158
 
207
159
  test("contains: upper bound", () => {
208
160
  assert.equal(
209
- contains({ from: 10, to: 20 }, 20),
161
+ contains({ ...defaultBounds, from: 10, to: 20 }, 20),
210
162
  true
211
163
  );
212
164
  });
@@ -214,39 +166,34 @@ describe("contains()", () => {
214
166
 
215
167
  test("contains: gt excludes lower bound", () => {
216
168
  assert.equal(
217
- contains({ from: 5, fromOp: "$gt" }, 5),
169
+ contains({ ...defaultBounds, from: 5, fromOp: "$gt" }, 5),
218
170
  false
219
171
  );
220
172
  });
221
173
 
222
174
  test("contains: gte includes lower bound", () => {
223
175
  assert.equal(
224
- contains({ from: 5, fromOp: "$gte" }, 5),
176
+ contains({ ...defaultBounds, from: 5, fromOp: "$gte" }, 5),
225
177
  true
226
178
  );
227
179
  });
228
180
 
229
181
  test("contains: lt excludes upper bound", () => {
230
182
  assert.equal(
231
- contains({ to: 10, toOp: "$lt" }, 10),
183
+ contains({ ...defaultBounds, to: 10, toOp: "$lt" }, 10),
232
184
  false
233
185
  );
234
186
  });
235
187
 
236
188
  test("contains: lte includes upper bound", () => {
237
189
  assert.equal(
238
- contains({ to: 10, toOp: "$lte" }, 10),
190
+ contains({ ...defaultBounds, to: 10, toOp: "$lte" }, 10),
239
191
  true
240
192
  );
241
193
  });
242
194
 
243
195
  test("contains: gt/lt excludes both endpoints", () => {
244
- const bounds = {
245
- from: 5,
246
- fromOp: "$gt",
247
- to: 10,
248
- toOp: "$lt"
249
- };
196
+ const bounds = { ...defaultBounds, from: 5, fromOp: "$gt", to: 10, toOp: "$lt"};
250
197
 
251
198
  assert.equal(contains(bounds, 5), false);
252
199
  assert.equal(contains(bounds, 10), false);
@@ -254,12 +201,7 @@ describe("contains()", () => {
254
201
  });
255
202
 
256
203
  test("contains: gte/lte includes both endpoints", () => {
257
- const bounds = {
258
- from: 5,
259
- fromOp: "$gte",
260
- to: 10,
261
- toOp: "$lte"
262
- };
204
+ const bounds = { ...defaultBounds, from: 5, fromOp: "$gte", to: 10, toOp: "$lte" };
263
205
 
264
206
  assert.equal(contains(bounds, 5), true);
265
207
  assert.equal(contains(bounds, 10), true);
@@ -267,24 +209,14 @@ describe("contains()", () => {
267
209
  });
268
210
 
269
211
  test("contains: gt/lte mixed", () => {
270
- const bounds = {
271
- from: 5,
272
- fromOp: "$gt",
273
- to: 10,
274
- toOp: "$lte"
275
- };
212
+ const bounds = { ...defaultBounds, from: 5, fromOp: "$gt", to: 10, toOp: "$lte" };
276
213
 
277
214
  assert.equal(contains(bounds, 5), false);
278
215
  assert.equal(contains(bounds, 10), true);
279
216
  });
280
217
 
281
218
  test("contains: gte/lt mixed", () => {
282
- const bounds = {
283
- from: 5,
284
- fromOp: "$gte",
285
- to: 10,
286
- toOp: "$lt"
287
- };
219
+ const bounds = { ...defaultBounds, from: 5, fromOp: "$gte", to: 10, toOp: "$lt" };
288
220
 
289
221
  assert.equal(contains(bounds, 5), true);
290
222
  assert.equal(contains(bounds, 10), false);
@@ -292,39 +224,39 @@ describe("contains()", () => {
292
224
 
293
225
  test("contains: value below lower bound", () => {
294
226
  assert.equal(
295
- contains({ from: 5, fromOp: "$gte" }, 4),
227
+ contains({ ...defaultBounds, from: 5, fromOp: "$gte" }, 4),
296
228
  false
297
229
  );
298
230
  });
299
231
 
300
232
  test("contains: value above upper bound", () => {
301
233
  assert.equal(
302
- contains({ to: 10, toOp: "$lte" }, 11),
234
+ contains({ ...defaultBounds, to: 10, toOp: "$lte" }, 11),
303
235
  false
304
236
  );
305
237
  });
306
238
 
307
239
  test("contains: open lower bound", () => {
308
240
  assert.equal(
309
- contains({ to: 10, toOp: "$lte" }, -1000),
241
+ contains({ ...defaultBounds, to: 10, toOp: "$lte" }, -1000),
310
242
  true
311
243
  );
312
244
  });
313
245
 
314
246
  test("contains: open upper bound", () => {
315
247
  assert.equal(
316
- contains({ from: 5, fromOp: "$gte" }, 1000),
248
+ contains({ ...defaultBounds, from: 5, fromOp: "$gte" }, 1000),
317
249
  true
318
250
  );
319
251
  });
320
252
 
321
253
  test("contains: completely unbounded", () => {
322
254
  assert.equal(
323
- contains({}, -100),
255
+ contains({ ...defaultBounds, }, -100),
324
256
  true
325
257
  );
326
258
  assert.equal(
327
- contains({}, 100),
259
+ contains({ ...defaultBounds, }, 100),
328
260
  true
329
261
  );
330
262
  });
@@ -353,42 +285,42 @@ describe("intersects()", () => {
353
285
 
354
286
  test("intersects: value ↔ range", () => {
355
287
  assert.equal(
356
- intersects([10], null, [], { from: 5 }),
288
+ intersects([10], null, [], { ...defaultBounds, from: 5 }),
357
289
  true
358
290
  );
359
291
  });
360
292
 
361
293
  test("intersects: value ↔ range miss", () => {
362
294
  assert.equal(
363
- intersects([2], null, [], { from: 5 }),
295
+ intersects([2], null, [], { ...defaultBounds, from: 5 }),
364
296
  false
365
297
  );
366
298
  });
367
299
 
368
300
  test("intersects: range ↔ value", () => {
369
301
  assert.equal(
370
- intersects([], { from: 5 }, [10], null),
302
+ intersects([], { ...defaultBounds, from: 5 }, [10], null),
371
303
  true
372
304
  );
373
305
  });
374
306
 
375
307
  test("intersects: range ↔ value miss", () => {
376
308
  assert.equal(
377
- intersects([], { from: 5 }, [2], null),
309
+ intersects([], { ...defaultBounds, from: 5 }, [2], null),
378
310
  false
379
311
  );
380
312
  });
381
313
 
382
314
  test("intersects: range ↔ range", () => {
383
315
  assert.equal(
384
- intersects([], { from: 10 }, [], { from: 20 }),
316
+ intersects([], { ...defaultBounds, from: 10 }, [], { ...defaultBounds, from: 20 }),
385
317
  true
386
318
  );
387
319
  });
388
320
 
389
321
  test("intersects: range ↔ range miss", () => {
390
322
  assert.equal(
391
- intersects([], { to: 5 }, [], { from: 10 }),
323
+ intersects([], { ...defaultBounds, to: 5 }, [], { ...defaultBounds, from: 10 }),
392
324
  false
393
325
  );
394
326
  });
@@ -229,7 +229,7 @@ describe("suffix()", () => {
229
229
  {
230
230
  type: "boolean",
231
231
  value: true
232
- }
232
+ } as any
233
233
  ],
234
234
  true,
235
235
  arg
@@ -249,7 +249,7 @@ describe("suffix()", () => {
249
249
  [
250
250
  {
251
251
  key: "id"
252
- }
252
+ } as any
253
253
  ],
254
254
  true,
255
255
  arg
package/libs/dip.ts CHANGED
@@ -25,7 +25,21 @@ export const includeCollectionConfig = Elabase.includeCollectionConfig
25
25
  export const shard_stats = Elabase.shard_stats
26
26
  export let config = Elabase.config
27
27
 
28
- export async function insertSync(meta, feature, date, uid, ref, type) {
28
+
29
+ type DipQuery = Parameters<typeof Elabase.update>[2]
30
+ type DipUpdate = Parameters<typeof Elabase.update>[3]
31
+
32
+ type IdempotentDip = {
33
+ new: (meta: Elabase.DipMeta, txn: string, blank?: { blank: boolean }) => Promise<IdempotentDip | false>
34
+ insert: (collection: string, query: DipQuery, data: DipUpdate) => Promise<void>
35
+ update: (collection: string, query: DipQuery, data: DipUpdate, rollback?: boolean) => Promise<boolean | number>
36
+ upsert: (collection: string, query: DipQuery, data: DipUpdate, rollback?: boolean) => Promise<boolean | number>
37
+ cleanup: (collection: string, query: DipQuery) => Promise<void>
38
+ finish: () => Promise<unknown>
39
+ }
40
+
41
+
42
+ export async function insertSync(meta: Elabase.DipMeta, feature: string, date: number, uid: string, ref: unknown, type: "REMOVE" | "UPSERT") {
29
43
  let stamp = new Date(date).toISOString()
30
44
  let _id = `${meta.outlet}_${stamp}_${uid}`
31
45
  let data = { _id, ref, type: type === "REMOVE" ? type : "UPSERT" }
@@ -33,44 +47,56 @@ export async function insertSync(meta, feature, date, uid, ref, type) {
33
47
  await Elabase.insert(meta, collection, data)
34
48
  }
35
49
 
36
- export const IdempotentDip = () => {
37
- return {
50
+ export const IdempotentDip = (): IdempotentDip => {
51
+ const state = {
38
52
  txn: '',
39
- meta: undefined,
40
- new: (async function (meta, txn, blank?: {blank: boolean}) {
41
- this.txn = txn
42
- this.meta = meta
43
- return blank ? this : ((await Elabase.query(this.meta, "txns",{_id: this.txn})).length ? false : this)
44
- }),
45
- insert: (async function (collection, query, data) {
46
- await Elabase.update(this.meta, collection, query, { $setOnInsert: data }, {upsert: true})
47
- }),
48
- update: (async function (collection, query, data, rollback) {
49
- let token = { [this.txn]: true }
50
- let idempotent = { [this.txn]: { $exists: rollback ?? false } }
51
- let result = await Elabase.update(this.meta, collection, {...query, ...idempotent}, {...data, $setOnInsert: undefined, $set: {...(data.$set ?? {}), ...token} })
52
- return result.count ? true : (await Elabase.query(this.meta, collection, {...query, ...idempotent})).length
53
- }),
54
- upsert: (async function (collection, query, data, rollback) {
55
- await this.insert(collection, query, data.$setOnInsert)
56
- return await this.update(collection, query, data, rollback)
57
- }),
58
- cleanup: (async function (collection, query) {
59
- await Elabase.update(this.meta, collection, query, { $unset: { [this.txn]: true } })
60
- }),
61
- finish: (async function () {
62
- return await Elabase.update(this.meta, "txns",{_id: this.txn}, {}, {upsert: true})
63
- })
53
+ meta: undefined as Elabase.DipMeta | undefined,
54
+ }
55
+
56
+ const idip = {} as IdempotentDip
57
+
58
+ idip.new = async function (meta: Elabase.DipMeta, txn: string, blank?: {blank: boolean}) {
59
+ state.txn = txn
60
+ state.meta = meta
61
+ return blank ? idip : ((await Elabase.query(state.meta, "txns",{_id: state.txn})).length ? false : idip)
62
+ }
63
+
64
+ idip.insert = async function (collection, query, data) {
65
+ await Elabase.update(state.meta, collection, query, { $setOnInsert: data }, {upsert: true})
66
+ }
67
+
68
+ idip.update = async function (collection, query, data, rollback) {
69
+ let token = { [state.txn]: true }
70
+ let idempotent = { [state.txn]: { $exists: rollback ?? false } }
71
+ let result = await Elabase.update(state.meta, collection, {...query, ...idempotent}, {...data, $setOnInsert: undefined, $set: {...(data.$set ?? {}), ...token} })
72
+ return result.count ? true : (await Elabase.query(state.meta, collection, {...query, ...idempotent})).length
73
+ }
74
+
75
+ idip.upsert = async function (collection, query, data, rollback) {
76
+ await idip.insert(collection, query, data.$setOnInsert)
77
+ return await idip.update(collection, query, data, rollback)
64
78
  }
79
+
80
+ idip.cleanup = async function (collection, query) {
81
+ await Elabase.update(state.meta, collection, query, { $unset: { [state.txn]: true } })
82
+ }
83
+
84
+ idip.finish = async function () {
85
+ return await Elabase.update(state.meta, "txns",{_id: state.txn}, {}, {upsert: true})
86
+ }
87
+
88
+ return idip
65
89
  }
66
90
 
91
+ type DipMessage = { meta: {staff: string; user: string}; txn: string; date: number }
92
+ type IdipCleanup = Record<string, string[]> | ((idip: IdempotentDip) => Promise<void>)
67
93
 
68
- export const idip = async (message, callback, cleanup) => {
94
+ export const idip = async (message: {meta: Elabase.DipMeta, txn: string}, callback: (idip: IdempotentDip) => Promise<void>, cleanup: IdipCleanup) => {
69
95
  if (!callback)
70
96
  throw new Error("Dip.idip() callback argument undefined")
71
97
  if (!cleanup)
72
98
  throw new Error("Dip.idip() cleanup argument undefined")
73
- async function doCleanup(IDip) {
99
+ async function doCleanup(IDip: IdempotentDip) {
74
100
  if (typeof cleanup === 'object') {
75
101
  for (let collection in cleanup)
76
102
  await IDip.cleanup(collection, { _id: {$in: cleanup[collection]} })
@@ -81,7 +107,7 @@ export const idip = async (message, callback, cleanup) => {
81
107
  let IDip = await IdempotentDip().new(message.meta, message.txn)
82
108
  if (!IDip) {
83
109
  IDip = await IdempotentDip().new(message.meta, message.txn, {blank: true})
84
- await doCleanup(IDip)
110
+ await doCleanup(IDip as IdempotentDip)
85
111
  return
86
112
  }
87
113
  await callback(IDip)
@@ -90,7 +116,7 @@ export const idip = async (message, callback, cleanup) => {
90
116
  }
91
117
 
92
118
 
93
- export const insertKeys = (message, meta) => {
119
+ export const insertKeys = (message: DipMessage, meta: Elabase.DipMeta) => {
94
120
  if (!isDipMeta(meta)) throw new Error('Error: Provided meta is not an instance of DipMeta in Dip.insertKeys()')
95
121
  return {
96
122
  "created": message.date, "updated": message.date,
@@ -102,7 +128,7 @@ export const insertKeys = (message, meta) => {
102
128
  ...(meta?.outlet ? {"outlet": meta.outlet} : {}),
103
129
  }
104
130
  }
105
- export const updateKeys = message => {
131
+ export const updateKeys = (message: DipMessage) => {
106
132
  return {
107
133
  "updated": message.date,
108
134
  "updatedBy": message.meta.staff,
package/libs/dipper.ts CHANGED
@@ -2,7 +2,21 @@
2
2
  import axios from 'axios'
3
3
  // import {curly} from 'node-libcurl'
4
4
 
5
- function hashStr(str) {
5
+
6
+ type DipperIdQuery = string | string[] | { $in: string[] }
7
+
8
+ type DipperArg = {
9
+ mode: string
10
+ query?: {
11
+ _id?: DipperIdQuery
12
+ }
13
+ insert?: {
14
+ _id?: DipperIdQuery
15
+ }
16
+ [key: string]: unknown
17
+ }
18
+
19
+ function hashStr(str: string) {
6
20
  let hash = 0;
7
21
  for (let i = 0; i < str.length; i++) {
8
22
  let charCode = str.charCodeAt(i);
@@ -11,7 +25,7 @@ function hashStr(str) {
11
25
  return hash;
12
26
  }
13
27
 
14
- function hash(string, digits) {
28
+ function hash(string: string, digits: number) {
15
29
  digits = digits || 6;
16
30
  var m = Math.pow(10, digits+1) - 1;
17
31
  var phi = Math.pow(10, digits) / 2 - 1;
@@ -21,7 +35,7 @@ function hash(string, digits) {
21
35
  }
22
36
  return n.toString();
23
37
  }
24
- let shards = []
38
+ let shards: string[] = []
25
39
  let shardCount = 20
26
40
 
27
41
  for (let i = 1; i <= shardCount; i++)
@@ -31,13 +45,13 @@ for (let i = 1; i <= shardCount; i++)
31
45
  // function shard(key) {
32
46
  // return hash(key,1) % shardCount
33
47
  // }
34
- function shard(key) {
48
+ function shard(key: string) {
35
49
  return hashStr(key) % shardCount
36
50
  }
37
51
 
38
- export let shard_hits = {}
52
+ export let shard_hits: Record<string, number> = {}
39
53
 
40
- async function postDip(url, arg) {
54
+ async function postDip(url: string | URL, arg: unknown) {
41
55
  return (await axios.post(url, arg)).data
42
56
  // curl
43
57
  // -----
@@ -51,7 +65,7 @@ async function postDip(url, arg) {
51
65
  // return data
52
66
  }
53
67
 
54
- export default async function dipper(arg) {
68
+ export default async function dipper(arg: DipperArg) {
55
69
 
56
70
  let result = []
57
71
 
@@ -66,11 +80,12 @@ export default async function dipper(arg) {
66
80
 
67
81
  } else {
68
82
 
69
- let ids = typeof _id == "object" ? _id.$in : [_id]
83
+ type InList = {$in: string[]}
84
+ let ids = typeof _id == "object" ? (_id as InList).$in : [_id]
70
85
  for (let id of ids) {
71
86
  let key = shard(id)
72
87
  let url = shards[key]
73
- shard_hits[url] = (shard_hits[url] ?? 0) + 1
88
+ shard_hits[url!] = (shard_hits[url!] ?? 0) + 1
74
89
  result.push(await postDip(`http://${url}/execute`, arg))
75
90
  }
76
91
  }
@@ -86,7 +101,7 @@ export default async function dipper(arg) {
86
101
 
87
102
  export const shard_stats = () => {
88
103
  let total: number = (Object.values(shard_hits) as number[]).reduce( (partial: number, value: number) => partial + value, 0)
89
- let result = {}
104
+ let result: Record<string, string> = {}
90
105
  Object.entries(shard_hits).forEach( ([key, value]) => result[key] = ((value as number) * 100 / total).toFixed(2) )
91
106
  return result
92
107
  }
package/libs/elabase.ts CHANGED
@@ -64,7 +64,7 @@ function deepFreeze(obj) {
64
64
  }
65
65
  return obj;
66
66
  }
67
- class DipMeta {
67
+ export class DipMeta {
68
68
  declare company?: string;
69
69
  declare outlet?: string;
70
70