corebasic 1.0.205 → 1.0.208

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.js CHANGED
@@ -2,7 +2,7 @@ import axios from 'axios'
2
2
  import {default as dipper, shard_stats as ShardStats} from './dipper.js'
3
3
  import * as Utils from './utils.js'
4
4
  import * as Cpp from './cpp.js'
5
-
5
+ import {applySuffixPolicy} from './dip/suffix/policy.js'
6
6
 
7
7
 
8
8
 
@@ -74,17 +74,17 @@ export const globalMeta = args => {
74
74
  }
75
75
  export const companyMeta = (company, args) => {
76
76
  if (typeof company !== "string" && !Array.isArray(company))
77
- throw {message: "Error: Invalid company provided in Dip.companyMeta()"}
77
+ throw new Error("Error: Invalid company provided in Dip.companyMeta()")
78
78
  if (!company || (typeof company === "string" && company.trim() === "") || company === "GLOBAL" || (Array.isArray(company) && (!company.length || company.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL")) ))
79
- throw {message: "Error: Invalid company provided in Dip.companyMeta()"}
79
+ throw new Error("Error: Invalid company provided in Dip.companyMeta()")
80
80
 
81
81
  return new DipMeta({...args, outlet: "GLOBAL", company})
82
82
  }
83
83
  export const outletMeta = (outlet, args) => {
84
84
  if (typeof outlet !== "string" && !Array.isArray(outlet))
85
- throw {message: "Error: Invalid outlet provided in Dip.outletMeta()"}
85
+ throw new Error("Error: Invalid outlet provided in Dip.outletMeta()")
86
86
  if (!outlet || (typeof outlet === "string" && outlet.trim() === "") || outlet === "GLOBAL" || (Array.isArray(outlet) && (!outlet.length || outlet.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL")) ))
87
- throw {message: "Error: Invalid outlet provided in Dip.outletMeta()"}
87
+ throw new Error("Error: Invalid outlet provided in Dip.outletMeta()")
88
88
 
89
89
  return new DipMeta({...args, company: "GLOBAL", outlet})
90
90
  }
@@ -92,38 +92,38 @@ export const outletMeta = (outlet, args) => {
92
92
  export const customMeta = (company, outlet, args) => {
93
93
 
94
94
  if (typeof company !== "string" && !Array.isArray(company))
95
- throw {message: "Error: Invalid company provided in Dip.customMeta()"}
95
+ throw new Error("Error: Invalid company provided in Dip.customMeta()")
96
96
  if (typeof outlet !== "string" && !Array.isArray(outlet))
97
- throw {message: "Error: Invalid outlet provided in Dip.customMeta()"}
97
+ throw new Error("Error: Invalid outlet provided in Dip.customMeta()")
98
98
 
99
99
  if (!company || (typeof company === "string" && company.trim() === "") || company === "GLOBAL" || (Array.isArray(company) && (!company.length || company.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL")) ))
100
- throw {message: "Error: Invalid company provided in Dip.customMeta()"}
100
+ throw new Error("Error: Invalid company provided in Dip.customMeta()"}
101
101
  if (!outlet || (typeof outlet === "string" && outlet.trim() === "") || outlet === "GLOBAL" || (Array.isArray(outlet) && (!outlet.length || outlet.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL")) ))
102
- throw {message: "Error: Invalid outlet provided in Dip.customMeta()"}
102
+ throw new Error("Error: Invalid outlet provided in Dip.customMeta()")
103
103
 
104
104
  return new DipMeta({...args, company, outlet})
105
105
  }
106
106
 
107
107
  function validate_collection(collection, fn_name) {
108
108
  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() === "")))) {
109
- throw {message: `Error: Invalid collection ${fn_name}`}
109
+ throw new Error(`Error: Invalid collection ${fn_name}`)
110
110
  }
111
111
  }
112
112
 
113
113
  function validate_meta(meta, fn_name) {
114
114
  if (!meta || typeof meta !== 'object') {
115
- throw {message: `Error: Invalid meta ${fn_name}`}
115
+ throw new Error(`Error: Invalid meta ${fn_name}`)
116
116
  }
117
117
  if ((typeof meta.company === 'string' && meta.company.trim() === "") || (typeof meta.company !== 'string' && !Array.isArray(meta.company)) || (Array.isArray(meta.company) && (!meta.company.length || meta.company.some(item => typeof item !== "string"|| item.trim() === "")))) {
118
- throw {message: `Error: Invalid meta.company ${fn_name}`}
118
+ throw new Error(`Error: Invalid meta.company ${fn_name}`)
119
119
  }
120
120
  if ((typeof meta.outlet === 'string' && meta.outlet.trim() === "") || (typeof meta.outlet !== 'string' && !Array.isArray(meta.outlet)) || (Array.isArray(meta.outlet) && (!meta.outlet.length || meta.outlet.some(item => typeof item !== "string" || item.trim() === "")))) {
121
- throw {message: `Error: Invalid meta.outlet ${fn_name}`}
121
+ throw new Error(`Error: Invalid meta.outlet ${fn_name}`)
122
122
  }
123
123
  if ((meta.suffix !== undefined && typeof meta.suffix !== 'string' && !Array.isArray(meta.suffix)) || (Array.isArray(meta.suffix) && meta.suffix.some(item => typeof item !== "string" || item.trim() === ""))) {
124
- throw {message: `Error: Invalid meta.suffix ${fn_name}`}
124
+ throw new Error(`Error: Invalid meta.suffix ${fn_name}`)
125
125
  } else if (typeof meta.suffix === 'string' && meta.suffix.trim() === "")
126
- throw {message: `Error: Invalid meta.suffix ${fn_name}`}
126
+ throw new Error(`Error: Invalid meta.suffix ${fn_name}`)
127
127
  }
128
128
 
129
129
  function generate_suffix(meta) {
@@ -202,7 +202,7 @@ export const batch = async (callback, arg) => { // Convenience function with aut
202
202
  // Ported
203
203
  export function batchSubmit(batch_id, arg) {
204
204
  if (!batch_id || !batches[batch_id] || !batches[batch_id].length)
205
- throw {message: `Error: Invalid batch in Dip.batchSubmit()`}
205
+ throw new Error(`Error: Invalid batch in Dip.batchSubmit()`)
206
206
  let txns = batches[batch_id]
207
207
  const executor = arg?.executor ?? batches[batch_id].find(txn => txn.executor)?.executor
208
208
  const syncMode = arg?.syncMode ?? batches[batch_id].find(txn => txn.syncMode)?.syncMode
@@ -231,7 +231,7 @@ export const schema = async (name) => {
231
231
  } catch (e) {
232
232
  // Delete the broken promise from cache so a retry can occur later
233
233
  delete SCHEMAS_JSON_PROMISES[name]
234
- throw {message: `Error: Failed to load schema ${name} in Dip`}
234
+ throw new Error(`Error: Failed to load schema ${name} in Dip`)
235
235
  }
236
236
  }
237
237
 
@@ -248,13 +248,20 @@ function init_collections_config() {
248
248
  for (let collection in COLLECTIONS_JSON) {
249
249
  let config = COLLECTIONS_JSON[collection]
250
250
  if (config.suffix !== undefined && (typeof config.suffix !== "object" || Array.isArray(config.suffix)) ) {
251
- throw {message: `Error: Initiating collection configs failed. Invalid suffix in collection: ${collection}`}
251
+ throw new Error(`Error: Initiating collection configs failed. Invalid suffix in collection: ${collection}`)
252
252
  }
253
253
  }
254
254
  }
255
255
  if (COLLECTIONS_JSON)
256
256
  init_collections_config()
257
257
 
258
+ const EXCLUDED_COLLECTIONS_CONFIG = {}
259
+ export function excludeCollectionConfig(collection) {
260
+ EXCLUDED_COLLECTIONS_CONFIG[collection] = true
261
+ }
262
+ export function includeCollectionConfig(collection) {
263
+ delete EXCLUDED_COLLECTIONS_CONFIG[collection]
264
+ }
258
265
 
259
266
  function validate_topology(meta, collection, fn_name) {
260
267
 
@@ -262,15 +269,16 @@ function validate_topology(meta, collection, fn_name) {
262
269
 
263
270
  let config = COLLECTIONS_JSON?.[collection]
264
271
  if (!config) {
265
- console.warn(`Warn: Missing config for collection: ${collection}${fn_name ? ` ${fn_name}` : ''}`)
272
+ if (!EXCLUDED_COLLECTIONS_CONFIG[collection])
273
+ console.warn(`Warn: Missing config for collection: ${collection}${fn_name ? ` ${fn_name}` : ''}`)
266
274
  return new_meta
267
275
  }
268
276
 
269
277
  function check_core_meta(config, meta, suffix) {
270
278
  if (config.company !== meta.company && typeof config.company !== "object")
271
- throw {message: `Error: Incompatible meta.company config for collection: ${collection}${suffix ? ' suffix: ' + suffix : ''}${fn_name ? ` ${fn_name}` : ''}`}
279
+ throw new Error(`Error: Incompatible meta.company config for collection: ${collection}${suffix ? ' suffix: ' + suffix : ''}${fn_name ? ` ${fn_name}` : ''}`)
272
280
  if (config.outlet !== meta.outlet && typeof config.outlet !== "object")
273
- throw {message: `Error: Incompatible meta.outlet config for collection: ${collection}${suffix ? ' suffix: ' + suffix : ''}${fn_name ? ` ${fn_name}` : ''}`}
281
+ throw new Error(`Error: Incompatible meta.outlet config for collection: ${collection}${suffix ? ' suffix: ' + suffix : ''}${fn_name ? ` ${fn_name}` : ''}`)
274
282
  }
275
283
 
276
284
  check_core_meta(config, meta)
@@ -315,7 +323,8 @@ export const insert = async (meta, collection, value, options, extras) => {
315
323
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
316
324
  }
317
325
  arg = Object.assign(arg, extras)
318
- arg.suffix = generate_suffix(meta)
326
+ arg.suffix = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.insert, true, arg)
327
+ arg.suffix = (arg.suffix ?? []).concat(generate_suffix(meta))
319
328
  arg.executor = meta.executor ?? "native"
320
329
  arg = Object.assign({}, topology_meta, arg)
321
330
  if (options?._id) {
@@ -325,7 +334,7 @@ export const insert = async (meta, collection, value, options, extras) => {
325
334
 
326
335
  if (meta.batch) {
327
336
  if (!batches[meta.batch])
328
- throw {message: 'Error: Invalid batch in Dip.insert()'}
337
+ throw new Error('Error: Invalid batch in Dip.insert()')
329
338
  batches[meta.batch].push(arg)
330
339
  return
331
340
  }
@@ -357,12 +366,13 @@ export const query = async (meta, collection, query, options, extras) => {
357
366
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
358
367
  }
359
368
  arg = Object.assign(arg, extras)
360
- arg.suffix = generate_suffix(meta)
369
+ arg.suffix = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.query, false, arg)
370
+ arg.suffix = (arg.suffix ?? []).concat(generate_suffix(meta))
361
371
  arg.executor = meta.executor ?? "native"
362
372
  arg = Object.assign({}, topology_meta, arg)
363
373
  if (meta.batch) {
364
374
  if (!batches[meta.batch])
365
- throw {message: 'Error: Invalid batch in Dip.query()'}
375
+ throw new Error('Error: Invalid batch in Dip.query()')
366
376
  batches[meta.batch].push(arg)
367
377
  return
368
378
  }
@@ -408,12 +418,13 @@ export const update = async (meta, collection, query, update, options, extras) =
408
418
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
409
419
  }
410
420
  arg = Object.assign(arg, extras)
411
- arg.suffix = generate_suffix(meta)
421
+ arg.suffix = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.query, false, arg)
422
+ arg.suffix = (arg.suffix ?? []).concat(generate_suffix(meta))
412
423
  arg.executor = meta.executor ?? "native"
413
424
  arg = Object.assign({}, topology_meta, arg)
414
425
  if (meta.batch) {
415
426
  if (!batches[meta.batch])
416
- throw {message: 'Error: Invalid batch in Dip.update()'}
427
+ throw new Error('Error: Invalid batch in Dip.update()')
417
428
  batches[meta.batch].push(arg)
418
429
  return
419
430
  }
@@ -433,7 +444,7 @@ export const remove = async (meta, collection, query, options, extras) => {
433
444
  validate_collection(collection, 'in Dip.remove()')
434
445
 
435
446
  if (Utils.isEmpty(query._id) && !meta.allowDangerousRemove)
436
- throw { message: "Error: Dip.remove() without _id blocked by default (Dangerous Operation). Set meta.allowDangerousRemove if intentional." }
447
+ throw new Error("Error: Dip.remove() without _id blocked by default (Dangerous Operation). Set meta.allowDangerousRemove if intentional.")
437
448
 
438
449
  validate_meta(meta, 'in Dip.remove()')
439
450
 
@@ -449,12 +460,13 @@ export const remove = async (meta, collection, query, options, extras) => {
449
460
  ...(meta.DIP_DB ? {db: meta.DIP_DB} : {}),
450
461
  }
451
462
  arg = Object.assign(arg, extras)
452
- arg.suffix = generate_suffix(meta)
463
+ arg.suffix = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.query, false, arg)
464
+ arg.suffix = (arg.suffix ?? []).concat(generate_suffix(meta))
453
465
  arg.executor = meta.executor ?? "native"
454
466
  arg = Object.assign({}, topology_meta, arg)
455
467
  if (meta.batch) {
456
468
  if (!batches[meta.batch])
457
- throw {message: 'Error: Invalid batch in Dip.query()'}
469
+ throw new Error('Error: Invalid batch in Dip.query()')
458
470
  batches[meta.batch].push(arg)
459
471
  return
460
472
  }
@@ -551,7 +563,7 @@ function parseBinaryResponse(result) {
551
563
  return {metadata: result.body, content: result.body.items}
552
564
  }
553
565
  if (!contentType.includes("application/dip")) {
554
- throw {message: "Error: Dip unsupported media. Invalid content-type."}
566
+ throw new Error("Error: Dip unsupported media. Invalid content-type.")
555
567
  }
556
568
 
557
569
  const arrayBuffer = result.body
package/libs/features.js CHANGED
@@ -43,13 +43,13 @@ let SERVICE_ADDRESS = process.env.APP_ENDPOINT || 'http://127.0.0.1:3000'
43
43
 
44
44
 
45
45
  export const get = feature => {
46
- const throwError = () => {throw {message: `Feature ${feature} not found in internal or external list during Features.subscribe call`}}
46
+ const throwError = () => {throw new Error(`Feature ${feature} not found in internal or external list during Features.subscribe call`)}
47
47
  let {api, service = SERVICE_ADDRESS, topic} = getFeature(feature) ?? SLYP_FEATURES_LIST[feature] ?? throwError()
48
48
  return {api, service, topic}
49
49
  }
50
50
 
51
51
  export const send = async (meta, feature, data, params) => {
52
- const throwError = () => {throw {message: `Feature ${feature} not found in internal or external list during inter feature call`}}
52
+ const throwError = () => {throw new Error(`Feature ${feature} not found in internal or external list during inter feature call`)}
53
53
  let {api, service = SERVICE_ADDRESS} = getFeature(feature) ?? SLYP_FEATURES_LIST[feature] ?? throwError()
54
54
  let method = getFeatureMethod(api)
55
55
  let url = getFeatureUrl(api)
@@ -58,7 +58,7 @@ export const send = async (meta, feature, data, params) => {
58
58
  for (let key in params)
59
59
  url = url.replace(`:${key}`, params[key])
60
60
  if (url.includes(':'))
61
- throw {feature, when: 'api/params/substitution', message: "Internal Feature Call" }
61
+ throw new Error(`Error: Internal feature call send on feature: ${feature} when api/params/substitution`)
62
62
  }
63
63
 
64
64
  let payload = { ...meta, data, feature, txn: Utils.uid() }
@@ -217,6 +217,9 @@ function registerApi() {
217
217
  }
218
218
 
219
219
  export const start = async (app, url, file) => {
220
+ const globalMeta = Dip.globalMeta()
221
+ Dip.excludeCollectionConfig("users.txns")
222
+ Dip.excludeCollectionConfig("Features.txns")
220
223
  ExpressApp = app
221
224
  PROJECT_ROOT_URL = url
222
225
  features = await Utils.fileToJson(url, file)
@@ -257,9 +260,12 @@ export const start = async (app, url, file) => {
257
260
  topic = topic.replace(/^.*Features./,'')
258
261
  while (true) {
259
262
  try {
260
- await Dip.update(message.meta, `users.txns.${message.user}`, {_id: message.txn}, { $setOnInsert: { user: message.user, feature: message.feature, date: message.date, created: message.date, updated: message.date, status: "Queued" } }, {upsert: true}) // Can always update the status later
263
+ // const iso_date = new Date(message.date).toISOString()
264
+ // // TODO: use $useChunks: [] once support is added in dip insert
265
+ // await Dip.insert(globalMeta, `users.txns`, { _id: `${message.user}_${iso_date}_${message.txn}`, user: message.user, feature: message.feature, date: message.date, created: message.date, updated: message.date, status: "Queued" }, {idempotent: true}) // Can always update the status later
266
+ // TODO: Avoid duplicate processing
261
267
  await features[message.feature].handler(topic, message)
262
- await Dip.insert(message.meta, "Features.txns", {_id: message.txn, status: "Processed"})
268
+ await Dip.insert(globalMeta, "Features.txns", {_id: message.txn, status: "Processed"}, {idempotent: true})
263
269
  break
264
270
  } catch(err) {
265
271
  if (process.env.DEBUG_MODE)
@@ -276,7 +282,7 @@ export const start = async (app, url, file) => {
276
282
  // Transaction status api
277
283
  app.get('/transactions/:id', async (req, res) => { // Front end calls this as a regular feature call. so `req.meta` exists
278
284
  try {
279
- let items = await Dip.query(req.meta, "Features.txns", {_id: req.params.id})
285
+ let items = await Dip.query(globalMeta, "Features.txns", {_id: req.params.id})
280
286
  if (items.length)
281
287
  res.json({ data: { ...items[0], txn: items._id } })
282
288
  else
@@ -285,13 +291,17 @@ export const start = async (app, url, file) => {
285
291
  res.status(500).json({ message: "Failed to retreive data" })
286
292
  }
287
293
  })
288
- app.get('/users/:id/transactions', async (req, res) => {
289
- try {
290
- res.json({ data: await Dip.query(req.meta, `users.txns.${req.params.id}`, {}, { $orderby: { date: -1 } }) })
291
- } catch {
292
- res.status(500).json({ message: "Failed to retreive data" })
293
- }
294
- })
294
+ // app.get('/users/:id/transactions', async (req, res) => {
295
+ // try {
296
+ // const idPrefix = `${req.params.id}_`
297
+ // // TODO: use $useChunks: [] once support is added in dip insert
298
+ // // TODO: remove $orderby: { date: -1 } and remove $orderby: { _id: -1 }
299
+ // // res.json({ data: await Dip.query(globalMeta, `users.txns`, {}, { $rangeFrom: idPrefix, $rangeTo: idPrefix, $rangeDirection: -1, $rangeInclusive: true, $orderby: { date: -1 } }) })
300
+ // res.json({ data: await Dip.query(globalMeta, `users.txns`, {}, { $rangeFrom: idPrefix, $rangeTo: idPrefix, $rangeDirection: -1, $rangeInclusive: true, $orderby: { _id: -1 } }) })
301
+ // } catch {
302
+ // res.status(500).json({ message: "Failed to retreive data" })
303
+ // }
304
+ // })
295
305
 
296
306
  try { await Messaging.start(app) } catch { console.log('Messaging failed to start. Maybe missing redis') }
297
307
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "corebasic",
3
3
  "type": "module",
4
- "version": "1.0.205",
4
+ "version": "1.0.208",
5
5
  "description": "",
6
6
  "main": "index.js",
7
7
  "scripts": {