corebasic 1.0.220 → 1.0.222

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.
@@ -36,13 +36,13 @@ export function formatDate(value, format) {
36
36
  // years and months and dates are already deduplicated
37
37
  const separator = '|';
38
38
  const replacements = {
39
- YYYY: _ => years.join(separator),
40
- YY: _ => years.map(y => String(y).slice(-2)).join(separator),
41
- MMMM: _ => months.map(m => MONTH_LONG[m]).join(separator),
42
- MMM: _ => months.map(m => MONTH_SHORT[m]).join(separator),
43
- MM: _ => months.map(m => String(m + 1).padStart(2, "0")).join(separator),
44
- DD: _ => dates.map(d => String(d).padStart(2, "0")).join(separator),
45
- D: _ => dates.join(separator),
39
+ YYYY: () => years.join(separator),
40
+ YY: () => years.map(y => String(y).slice(-2)).join(separator),
41
+ MMMM: () => months.map(m => MONTH_LONG[m]).join(separator),
42
+ MMM: () => months.map(m => MONTH_SHORT[m]).join(separator),
43
+ MM: () => months.map(m => String(m + 1).padStart(2, "0")).join(separator),
44
+ DD: () => dates.map(d => String(d).padStart(2, "0")).join(separator),
45
+ D: () => dates.join(separator),
46
46
  };
47
47
  return format.replace(/YYYY|MMMM|MMM|YY|MM|DD|D/g, token => replacements[token]());
48
48
  }
@@ -466,7 +466,7 @@ let Essentials = {
466
466
  };
467
467
  function prepareResult(result) {
468
468
  let res = result.content?.length === 1 ? result.content[0].items : result.content; // For raw, this resolves to result.content which is ArrayBuffer
469
- res.metadata = _ => result.metadata;
469
+ res.metadata = () => result.metadata;
470
470
  if (result.metadata.executor === "raw")
471
471
  setRawBatchIterator(res);
472
472
  return res;
@@ -507,7 +507,7 @@ function parseBinaryResponse(result) {
507
507
  }
508
508
  function setRawBatchIterator(arrayBuffer) {
509
509
  arrayBuffer.metadata().items.forEach(batch => {
510
- batch.kv = _ => {
510
+ batch.kv = () => {
511
511
  const batchItem = {
512
512
  count: batch.count,
513
513
  slice: Essentials.sliceArrayBuffer(arrayBuffer, batch.offset, batch.size),
@@ -636,7 +636,7 @@ function getRawKeyValue(arrayBuffer, offset) {
636
636
  // Zero-copy view window bounded strictly to the key bytes
637
637
  let _id = masterView.subarray(offset, offset + keySize);
638
638
  let _id_string;
639
- _id.toText = _ => {
639
+ _id.toText = () => {
640
640
  // Fix: Pass the typed array view itself, NOT the underlying root buffer
641
641
  _id_string = _id_string === undefined ? _id.buffer.slice(_id.byteOffset, _id.byteOffset + _id.byteLength) : _id_string;
642
642
  return bufferToString(_id_string);
@@ -651,7 +651,7 @@ function getRawKeyValue(arrayBuffer, offset) {
651
651
  offset += dataSize;
652
652
  _val = Essentials.sliceArrayBuffer(arrayBuffer, _val.byteOffset, _val.byteLength);
653
653
  // _val = _val.buffer.slice(_val.byteOffset, _val.byteOffset + _val.byteLength);
654
- _val.toText = _ => bufferToString(_val);
654
+ _val.toText = () => bufferToString(_val);
655
655
  return { _id, _val, next: offset };
656
656
  }
657
657
  // Axios usage
@@ -22,7 +22,7 @@ const getFeatureUrl = api => api.split(' ')[1];
22
22
  const getFeature = name => features[name];
23
23
  const DEPLOY_TOKEN_SECRET = process.env.DEPLOY_TOKEN_SECRET || "MY_SECRET_DEPLOY_TOKEN";
24
24
  const SERVICE_ACCESS_TOKEN = jwt.sign({ app: process.env.APP_DEPLOYMENT_NAME }, DEPLOY_TOKEN_SECRET, { expiresIn: '365d' });
25
- const NDCURVE_DEVELOPER_LICENSE_ACCESS_TOKEN = await (async (_) => { if (process.env.NDCURVE_DEVELOPER_SERVICE)
25
+ const NDCURVE_DEVELOPER_LICENSE_ACCESS_TOKEN = await (async () => { if (process.env.NDCURVE_DEVELOPER_SERVICE)
26
26
  try {
27
27
  return (await Utils.fileToJson('file://', '/.ndcurve/developer.license.json')).accessToken?.trim();
28
28
  }
@@ -52,12 +52,14 @@ let appId = Utils.uid();
52
52
  let SERVICE_ADDRESS = process.env.APP_ENDPOINT || 'http://127.0.0.1:3000';
53
53
  export const get = feature => {
54
54
  const throwError = () => { throw new Error(`Feature ${feature} not found in internal or external list during Features.subscribe call`); };
55
- let { api, service = SERVICE_ADDRESS, topic } = getFeature(feature) ?? SLYP_FEATURES_LIST[feature] ?? throwError();
55
+ const baseFeature = getFeature(feature);
56
+ let { api, service = SERVICE_ADDRESS, topic } = baseFeature ? baseFeature : (SLYP_FEATURES_LIST[feature] ?? throwError());
56
57
  return { api, service, topic };
57
58
  };
58
59
  export const send = async (meta, feature, data, params) => {
59
60
  const throwError = () => { throw new Error(`Feature ${feature} not found in internal or external list during inter feature call`); };
60
- let { api, service = SERVICE_ADDRESS } = getFeature(feature) ?? SLYP_FEATURES_LIST[feature] ?? throwError();
61
+ const baseFeature = getFeature(feature);
62
+ let { api, service = SERVICE_ADDRESS } = baseFeature ? baseFeature : (SLYP_FEATURES_LIST[feature] ?? throwError());
61
63
  let method = getFeatureMethod(api);
62
64
  let url = getFeatureUrl(api);
63
65
  if (params || url.includes(':')) {
@@ -75,7 +77,7 @@ export const send = async (meta, feature, data, params) => {
75
77
  let response;
76
78
  let req = { meta, body: payload, params, method };
77
79
  req = JSON.parse(JSON.stringify(req));
78
- let res = { json: payload => response = payload, end: _ => true };
80
+ let res = { json: payload => response = payload, end: () => true };
79
81
  await apiHandler(req, res);
80
82
  return response;
81
83
  }
@@ -92,13 +94,12 @@ let appids = {};
92
94
  async function announce() {
93
95
  let exp_features = {};
94
96
  for (let [key, { api, subscribe }] of Object.entries(features))
95
- exp_features[key] = { api, service: SERVICE_ADDRESS, subscribe };
97
+ exp_features[key] = { api, service: SERVICE_ADDRESS, subscribe, topic: "" };
96
98
  await Messaging.subscribe(`${process.env.REDIS_CHANNEL_PREFIX}_SLYP_FEATURES_LIST`, async (message, channel) => {
97
- let msg = JSON.parse(message);
98
- if (msg.uid !== appId && !appids[msg.uid]) {
99
- appids[msg.uid] = true;
99
+ let { uid, ...msg } = JSON.parse(message);
100
+ if (uid !== appId && !appids[uid]) {
101
+ appids[uid] = true;
100
102
  SLYP_FEATURES_LIST = { ...SLYP_FEATURES_LIST, ...msg };
101
- delete SLYP_FEATURES_LIST.uid;
102
103
  await Messaging.produce(`${process.env.REDIS_CHANNEL_PREFIX}_SLYP_FEATURES_LIST`, JSON.stringify({ ...exp_features, uid: appId }));
103
104
  await subscribe();
104
105
  }
@@ -187,15 +188,15 @@ async function registerHandler(features) {
187
188
  apis[feature.api] = apis[feature.api] ?? {};
188
189
  apis[feature.api][name] = feature;
189
190
  const featureName = name;
190
- name = name.split('.');
191
- let handler = name.pop();
192
- name = `src/${name.join('/')}`;
193
- if (name === 'src/transactions/query')
191
+ const nameParts = name.split('.');
192
+ let handler = nameParts.pop();
193
+ const featurePath = `src/${nameParts.join('/')}`;
194
+ if (featurePath === 'src/transactions/query')
194
195
  continue;
195
196
  if (featureName.startsWith("flows.") && !featureName.startsWith("flows.query.") && !featureName.startsWith("flows.command.") && !featureName.startsWith("flows.designs."))
196
197
  feature.handler = (await import(__rewriteRelativeImportExtension(`${new URL(`src/flows/query.js`, PROJECT_ROOT_URL).toString().replace('file://', '')}`))).FEATURE_HANDLERS[handler];
197
198
  else
198
- feature.handler = (await import(__rewriteRelativeImportExtension(`${new URL(`${name}.js`, PROJECT_ROOT_URL).toString().replace('file://', '')}`)))[handler];
199
+ feature.handler = (await import(__rewriteRelativeImportExtension(`${new URL(`${featurePath}.js`, PROJECT_ROOT_URL).toString().replace('file://', '')}`)))[handler];
199
200
  }
200
201
  }
201
202
  function registerApi() {
@@ -335,7 +336,6 @@ async function subscribe() {
335
336
  catch (_) { }
336
337
  delete subscribed_consumers[key];
337
338
  }
338
- let exp_features = {};
339
339
  for (let key in SLYP_FEATURES_LIST)
340
340
  if (!Utils.isEmpty(SLYP_FEATURES_LIST[key].subscribe)) {
341
341
  subscriptions[key] = SLYP_FEATURES_LIST[key].subscribe;
@@ -125,7 +125,7 @@ export async function hdel(key, subkey) {
125
125
  }
126
126
  // Hydrate
127
127
  export async function hydrate(callback) {
128
- setTimeout(async (_) => {
128
+ setTimeout(async () => {
129
129
  let { user, company, items } = await callback();
130
130
  await publish(user, { event: "RPC_hydrate", data: { company, items }, txn: Utils.uid() });
131
131
  }, 100);
@@ -184,18 +184,18 @@ export function validityToMillisecs(start, validity) {
184
184
  count = parseIntValue(count);
185
185
  period = period.toLowerCase();
186
186
  const timeline = {
187
- year: _ => addYears(now, count),
188
- years: _ => addYears(now, count),
189
- month: _ => addMonths(now, count),
190
- months: _ => addMonths(now, count),
191
- day: _ => now.setDate(now.getDate() + count),
192
- days: _ => now.setDate(now.getDate() + count),
193
- week: _ => now.setDate(now.getDate() + (count * 7)),
194
- weeks: _ => now.setDate(now.getDate() + (count * 7)),
195
- hour: _ => now.setHours(now.getHours() + count),
196
- hours: _ => now.setHours(now.getHours() + count),
197
- minute: _ => now.setMinutes(now.getMinutes() + count),
198
- minutes: _ => now.setMinutes(now.getMinutes() + count),
187
+ year: () => addYears(now, count),
188
+ years: () => addYears(now, count),
189
+ month: () => addMonths(now, count),
190
+ months: () => addMonths(now, count),
191
+ day: () => now.setDate(now.getDate() + count),
192
+ days: () => now.setDate(now.getDate() + count),
193
+ week: () => now.setDate(now.getDate() + (count * 7)),
194
+ weeks: () => now.setDate(now.getDate() + (count * 7)),
195
+ hour: () => now.setHours(now.getHours() + count),
196
+ hours: () => now.setHours(now.getHours() + count),
197
+ minute: () => now.setMinutes(now.getMinutes() + count),
198
+ minutes: () => now.setMinutes(now.getMinutes() + count),
199
199
  };
200
200
  timeline[period]();
201
201
  return now.getTime();
@@ -206,18 +206,18 @@ export function validityToUTCMillisecs(start, validity) {
206
206
  count = parseIntValue(count);
207
207
  period = period.toLowerCase();
208
208
  const timeline = {
209
- year: _ => addUTCYears(now, count),
210
- years: _ => addUTCYears(now, count),
211
- month: _ => addUTCMonths(now, count),
212
- months: _ => addUTCMonths(now, count),
213
- day: _ => now.setUTCDate(now.getUTCDate() + count),
214
- days: _ => now.setUTCDate(now.getUTCDate() + count),
215
- week: _ => now.setUTCDate(now.getUTCDate() + (count * 7)),
216
- weeks: _ => now.setUTCDate(now.getUTCDate() + (count * 7)),
217
- hour: _ => now.setUTCHours(now.getUTCHours() + count),
218
- hours: _ => now.setUTCHours(now.getUTCHours() + count),
219
- minute: _ => now.setUTCMinutes(now.getUTCMinutes() + count),
220
- minutes: _ => now.setUTCMinutes(now.getUTCMinutes() + count),
209
+ year: () => addUTCYears(now, count),
210
+ years: () => addUTCYears(now, count),
211
+ month: () => addUTCMonths(now, count),
212
+ months: () => addUTCMonths(now, count),
213
+ day: () => now.setUTCDate(now.getUTCDate() + count),
214
+ days: () => now.setUTCDate(now.getUTCDate() + count),
215
+ week: () => now.setUTCDate(now.getUTCDate() + (count * 7)),
216
+ weeks: () => now.setUTCDate(now.getUTCDate() + (count * 7)),
217
+ hour: () => now.setUTCHours(now.getUTCHours() + count),
218
+ hours: () => now.setUTCHours(now.getUTCHours() + count),
219
+ minute: () => now.setUTCMinutes(now.getUTCMinutes() + count),
220
+ minutes: () => now.setUTCMinutes(now.getUTCMinutes() + count),
221
221
  };
222
222
  timeline[period]();
223
223
  return now.getTime();
package/libs/features.ts CHANGED
@@ -8,7 +8,26 @@ import axios from 'axios'
8
8
  // @ts-ignore
9
9
  import jwt from 'jsonwebtoken'
10
10
 
11
- let features = {}
11
+ export type Message = unknown
12
+ export type Req = unknown
13
+ export type Res = unknown
14
+ export type Query = (req: Req, res: Res) => Promise<void>
15
+ export type Command = (topic: string, message: Message, req?: Req, res?: Res) => Promise<void>
16
+ type Handler = Query | Command
17
+
18
+
19
+ type RemoteFeatureEntry = {
20
+ api: string
21
+ service: string
22
+ subscribe: string
23
+ topic: string
24
+ headers?: {JWT?: string, service?: boolean, NDCURVE_DEVELOPER_LICENSE_ACCESS_TOKEN?: string}
25
+ }
26
+
27
+ type FeatureEntry = { api: string, topic: string, bypass: boolean, featureless: boolean, subscribe: string, handler: Handler }
28
+
29
+
30
+ let features: Record<string, FeatureEntry> = {}
12
31
  let apis = {}
13
32
 
14
33
  const getFeatureMethod = api => api.split(' ')[0].toLowerCase()
@@ -39,20 +58,22 @@ async function loadLocalFeatures() { // For Local Testing
39
58
  return data
40
59
  }
41
60
 
42
- let SLYP_FEATURES_LIST = await loadLocalFeatures()
61
+ let SLYP_FEATURES_LIST: Record<string, RemoteFeatureEntry> = await loadLocalFeatures()
43
62
  let appId = Utils.uid()
44
63
  let SERVICE_ADDRESS = process.env.APP_ENDPOINT || 'http://127.0.0.1:3000'
45
64
 
46
65
 
47
66
  export const get = feature => {
48
67
  const throwError = () => {throw new Error(`Feature ${feature} not found in internal or external list during Features.subscribe call`)}
49
- let {api, service = SERVICE_ADDRESS, topic} = getFeature(feature) ?? SLYP_FEATURES_LIST[feature] ?? throwError()
68
+ const baseFeature: FeatureEntry = getFeature(feature)
69
+ let {api, service = SERVICE_ADDRESS, topic} = baseFeature ? baseFeature as FeatureEntry & {service: string} : (SLYP_FEATURES_LIST[feature] ?? throwError())
50
70
  return {api, service, topic}
51
71
  }
52
72
 
53
73
  export const send = async (meta, feature, data, params) => {
54
74
  const throwError = () => {throw new Error(`Feature ${feature} not found in internal or external list during inter feature call`)}
55
- let {api, service = SERVICE_ADDRESS} = getFeature(feature) ?? SLYP_FEATURES_LIST[feature] ?? throwError()
75
+ const baseFeature: FeatureEntry = getFeature(feature)
76
+ let {api, service = SERVICE_ADDRESS} = baseFeature ? baseFeature as FeatureEntry & {service: string} : (SLYP_FEATURES_LIST[feature] ?? throwError())
56
77
  let method = getFeatureMethod(api)
57
78
  let url = getFeatureUrl(api)
58
79
 
@@ -90,16 +111,15 @@ export const send = async (meta, feature, data, params) => {
90
111
 
91
112
  let appids = {}
92
113
  async function announce() {
93
- let exp_features = {}
114
+ let exp_features: Record<string, RemoteFeatureEntry> = {}
94
115
  for (let [key, {api,subscribe}] of Object.entries(features))
95
- exp_features[key] = {api, service: SERVICE_ADDRESS, subscribe}
116
+ exp_features[key] = {api, service: SERVICE_ADDRESS, subscribe, topic: ""}
96
117
 
97
118
  await Messaging.subscribe(`${process.env.REDIS_CHANNEL_PREFIX}_SLYP_FEATURES_LIST`, async (message, channel) => {
98
- let msg = JSON.parse(message)
99
- if (msg.uid !== appId && !appids[msg.uid]) {
100
- appids[msg.uid] = true
119
+ let {uid, ...msg} = JSON.parse(message) as Record<string, RemoteFeatureEntry> & {uid: string}
120
+ if (uid !== appId && !appids[uid]) {
121
+ appids[uid] = true
101
122
  SLYP_FEATURES_LIST = {...SLYP_FEATURES_LIST, ...msg}
102
- delete SLYP_FEATURES_LIST.uid
103
123
  await Messaging.produce(`${process.env.REDIS_CHANNEL_PREFIX}_SLYP_FEATURES_LIST`, JSON.stringify({...exp_features, uid: appId }))
104
124
  await subscribe()
105
125
  }
@@ -151,7 +171,7 @@ const apiHandler = async (req, res) => {
151
171
  if (method === "get") {
152
172
  try {
153
173
  req.body = {...req.body, topic}
154
- await feature.handler(req, res)
174
+ await (feature.handler as Query)(req, res)
155
175
  } catch (err) {
156
176
  if (process.env.DEBUG_MODE)
157
177
  console.log('Error: Feature: ', req.body?.feature ?? (featureless ? `Featureless Api:${featureless.api}` : undefined), err)
@@ -159,7 +179,7 @@ const apiHandler = async (req, res) => {
159
179
  }
160
180
  } else if (method !== "get" && feature.bypass) {
161
181
  try {
162
- await feature.handler(topic, prepareMessage(req), req, res)
182
+ await (feature.handler as Command)(topic, prepareMessage(req), req, res)
163
183
  } catch (err) {
164
184
  if (process.env.DEBUG_MODE)
165
185
  console.log('Error: Feature: ', req.body?.feature ?? (featureless ? `Featureless Api:${featureless.api}` : undefined), err)
@@ -194,17 +214,17 @@ async function registerHandler(features) {
194
214
  apis[feature.api][name] = feature
195
215
  const featureName = name
196
216
 
197
- name = name.split('.')
198
- let handler = name.pop()
199
- name = `src/${name.join('/')}`
217
+ const nameParts = name.split('.')
218
+ let handler = nameParts.pop()
219
+ const featurePath = `src/${nameParts.join('/')}`
200
220
 
201
- if (name === 'src/transactions/query')
221
+ if (featurePath === 'src/transactions/query')
202
222
  continue
203
223
 
204
224
  if (featureName.startsWith("flows.") && !featureName.startsWith("flows.query.") && !featureName.startsWith("flows.command.") && !featureName.startsWith("flows.designs."))
205
225
  feature.handler = (await import(`${new URL(`src/flows/query.js`, PROJECT_ROOT_URL).toString().replace('file://', '')}`)).FEATURE_HANDLERS[handler]
206
226
  else
207
- feature.handler = (await import(`${new URL(`${name}.js`, PROJECT_ROOT_URL).toString().replace('file://', '')}`))[handler]
227
+ feature.handler = (await import(`${new URL(`${featurePath}.js`, PROJECT_ROOT_URL).toString().replace('file://', '')}`))[handler]
208
228
  }
209
229
  }
210
230
  function registerApi() {
@@ -266,7 +286,7 @@ export const start = async (app, url, file) => {
266
286
  // // TODO: use $useChunks: [] once support is added in dip insert
267
287
  // 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
268
288
  // TODO: Avoid duplicate processing
269
- await features[message.feature].handler(topic, message)
289
+ await (features[message.feature].handler as Command)(topic, message)
270
290
  await Dip.insert(globalMeta, "Features.txns", {_id: message.txn, status: "Processed"}, {idempotent: true})
271
291
  break
272
292
  } catch(err) {
@@ -348,7 +368,6 @@ async function subscribe() {
348
368
  }
349
369
 
350
370
 
351
- let exp_features = {}
352
371
  for (let key in SLYP_FEATURES_LIST)
353
372
  if (!Utils.isEmpty(SLYP_FEATURES_LIST[key].subscribe)) {
354
373
  subscriptions[key] = SLYP_FEATURES_LIST[key].subscribe
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "corebasic",
3
3
  "type": "module",
4
- "version": "1.0.220",
4
+ "version": "1.0.222",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "./index.ts",