theprogrammablemind 8.0.0 → 8.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/config.js CHANGED
@@ -2,9 +2,10 @@
2
2
  const { Semantics, normalizeGenerator } = require('./semantics')
3
3
  const { Generators } = require('./generators')
4
4
  const { v4: uuidv4 } = require('uuid')
5
- const client = require('../client')
5
+ const configHelpers = require('./configHelpers')
6
6
  const DigraphInternal = require('./digraph_internal')
7
7
  const helpers = require('./helpers')
8
+ const { InitCalls } = require('./helpers')
8
9
  const { ecatch } = require('./helpers')
9
10
  const runtime = require('../runtime')
10
11
  const _ = require('lodash')
@@ -40,6 +41,9 @@ const initWords = (words) => {
40
41
  }
41
42
 
42
43
  const debugPriority = (priority) => {
44
+ if (global.pauseDebugging) {
45
+ return
46
+ }
43
47
  if (global.entodictonDebugPriority) {
44
48
  if (helpers.subPriority(entodictonDebugPriority, priority)) {
45
49
  debugger // debug hierarchy hit
@@ -48,6 +52,9 @@ const debugPriority = (priority) => {
48
52
  }
49
53
 
50
54
  const debugAssociation = (association) => {
55
+ if (global.pauseDebugging) {
56
+ return
57
+ }
51
58
  if (global.entodictonDebugAssociation) {
52
59
  if (helpers.safeEquals(global.entodictonDebugAssociation, association)) {
53
60
  debugger // debug association hit
@@ -55,7 +62,21 @@ const debugAssociation = (association) => {
55
62
  }
56
63
  }
57
64
 
65
+ const debugWord = (word) => {
66
+ if (global.pauseDebugging) {
67
+ return
68
+ }
69
+ if (global.entodictonDebugWord) {
70
+ if (helpers.safeEquals(global.entodictonDebugWord, word)) {
71
+ debugger // debug word hit
72
+ }
73
+ }
74
+ }
75
+
58
76
  const debugHierarchy = (pair) => {
77
+ if (global.pauseDebugging) {
78
+ return
79
+ }
59
80
  if (global.entodictonDebugHierarchy) {
60
81
  if (helpers.safeEquals(global.entodictonDebugHierarchy, pair)) {
61
82
  debugger // debug hierarchy hit
@@ -64,14 +85,20 @@ const debugHierarchy = (pair) => {
64
85
  }
65
86
 
66
87
  const debugBridge = (bridge) => {
88
+ if (global.pauseDebugging) {
89
+ return
90
+ }
67
91
  if (global.entodictonDebugBridge) {
68
- if (global.entodictonDebugBridge[0] == bridge.id && global.entodictonDebugBridge[1] == bridge.level) {
92
+ if (global.entodictonDebugBridge == bridge.id) {
69
93
  debugger // debug hierarchy hit
70
94
  }
71
95
  }
72
96
  }
73
97
 
74
98
  const debugOperator = (operator) => {
99
+ if (global.pauseDebugging) {
100
+ return
101
+ }
75
102
  if (global.entodictonDebugOperator) {
76
103
  if ((operator.pattern || operator) === global.entodictonDebugOperator) {
77
104
  debugger // debug operator hit
@@ -80,18 +107,29 @@ const debugOperator = (operator) => {
80
107
  }
81
108
 
82
109
  const debugConfigProps = (config) => {
110
+ if (global.pauseDebugging) {
111
+ return
112
+ }
83
113
  if (!config) {
84
114
  return
85
115
  }
86
116
  const checkProps = [
87
117
  { property: 'priorities', check: (v) => debugPriority(v) },
88
118
  { property: 'association', check: (v) => debugAssociation(v) },
119
+ { property: 'words', check: (v) => debugAssociation(v) },
89
120
  { property: 'hierarchy', check: (v) => debugHierarchy(v) },
90
121
  { property: 'operators', check: (v) => debugOperator(v) },
91
122
  { property: 'bridges', check: (v) => debugBridge(v) }
92
123
  ]
93
124
  for (const { property, check } of checkProps) {
94
- if (config[property]) {
125
+ if (property == 'words') {
126
+ if (config[property]) {
127
+ for (const value in config[property].literals) {
128
+ check(value)
129
+ }
130
+ }
131
+ }
132
+ else if (config[property]) {
95
133
  for (const value of config[property]) {
96
134
  check(value)
97
135
  }
@@ -217,6 +255,9 @@ const priority_valid = (cp) => {
217
255
  const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
218
256
  ecatch(`While processing the bridge for ${bridge.id}#${bridge.level}`,
219
257
  () => {
258
+ if (bridge.development && config.isModule) {
259
+ return
260
+ }
220
261
  if (!bridge.bridge) {
221
262
  bridge.bridge = '{ ...next(operator) }'
222
263
  }
@@ -225,7 +266,12 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
225
266
  }
226
267
  if (bridge.children) {
227
268
  for (const child of bridge.children) {
228
- config.addHierarchy(child, bridge.id)
269
+ // config.addHierarchy(child, bridge.id)
270
+ if (child.child) {
271
+ config.addHierarchy(child.child, bridge.id, child.instance)
272
+ } else {
273
+ config.addHierarchy(child, bridge.id)
274
+ }
229
275
  }
230
276
  }
231
277
  if (bridge.operator) {
@@ -233,12 +279,20 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
233
279
  }
234
280
  if (bridge.parents) {
235
281
  for (const parent of bridge.parents) {
236
- config.addHierarchy(bridge.id, parent)
282
+ if (parent.parent) {
283
+ config.addHierarchy(bridge.id, parent.parent, parent.instance)
284
+ } else {
285
+ config.addHierarchy(bridge.id, parent)
286
+ }
237
287
  }
238
288
  }
239
289
  if (bridge.isA) {
240
290
  for (const parent of bridge.isA) {
241
- config.addHierarchy(bridge.id, parent)
291
+ if (parent.parent) {
292
+ config.addHierarchy(bridge.id, parent.parent, parent.instance)
293
+ } else {
294
+ config.addHierarchy(bridge.id, parent)
295
+ }
242
296
  }
243
297
  }
244
298
  if (bridge.before) {
@@ -260,7 +314,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
260
314
  if (bridge.words) {
261
315
  for (let def of bridge.words) {
262
316
  if (typeof def === 'string') {
263
- config.addWordInternal(def, { id: bridge.id, initial: `{ value: "${def}"}` })
317
+ config.addWordInternal(def, { id: bridge.id, initial: `{ value: "${bridge.id}"}` })
264
318
  } else {
265
319
  const word = def.word
266
320
  def = { initial: JSON.stringify(def), id: bridge.id, word }
@@ -301,8 +355,8 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
301
355
  const level = bridge.generatorp.level >= 0 ? bridge.generatorp.level : bridge.level + 1
302
356
 
303
357
  const generator = {
304
- where: bridge.generatorp.where || bridge.where || client.where(4),
305
- match: (args) => bridge.id == args.context.marker && args.context.level == level && args.context.paraphrase && match(args),
358
+ where: bridge.generatorp.where || bridge.where || helpers.where(4),
359
+ match: async (args) => bridge.id == args.context.marker && args.context.level == level && args.context.paraphrase && await match(args),
306
360
  apply: (args) => apply(args),
307
361
  applyWrapped: apply,
308
362
  property: 'generatorp'
@@ -318,8 +372,8 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
318
372
  const apply = typeof bridge.generatorr === 'function' ? bridge.generatorr : bridge.generatorr.apply || bridge.generatorr
319
373
  const level = bridge.generatorr.level >= 0 ? bridge.generatorr.level : bridge.level + 1
320
374
  const generator = {
321
- where: bridge.generatorr.where || bridge.where || client.where(4),
322
- match: (args) => bridge.id == args.context.marker && args.context.level == level && !args.context.paraphrase && (args.context.response || args.context.isResponse) && match(args),
375
+ where: bridge.generatorr.where || bridge.where || helpers.where(4),
376
+ match: async (args) => bridge.id == args.context.marker && args.context.level == level && !args.context.paraphrase && (args.context.response || args.context.isResponse) && await match(args),
323
377
  apply: (args) => apply(args),
324
378
  applyWrapped: apply,
325
379
  property: 'generatorr'
@@ -332,7 +386,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
332
386
  }
333
387
  if (bridge.evaluator) {
334
388
  const semantic = {
335
- where: bridge.evaluator.where || bridge.where || client.where(3),
389
+ where: bridge.evaluator.where || bridge.where || helpers.where(3),
336
390
  match: ({ context }) => bridge.id == context.marker && context.evaluate,
337
391
  apply: (args) => bridge.evaluator(args),
338
392
  applyWrapped: bridge.evaluator,
@@ -346,7 +400,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
346
400
  }
347
401
  if (bridge.semantic) {
348
402
  const semantic = {
349
- where: bridge.semantic.where || bridge.where || client.where(3),
403
+ where: bridge.semantic.where || bridge.where || helpers.where(3),
350
404
  match: ({ context }) => bridge.id == context.marker && !context.evaluate,
351
405
  apply: (args) => bridge.semantic(args),
352
406
  applyWrapped: bridge.semantic,
@@ -404,13 +458,13 @@ if (runtime.process.env.DEBUG_ASSOCIATION) {
404
458
  global.entodictonDebugAssociation = JSON.parse(runtime.process.env.DEBUG_ASSOCIATION)
405
459
  }
406
460
 
461
+ if (runtime.process.env.DEBUG_WORD) {
462
+ global.entodictonDebugWord = runtime.process.env.DEBUG_WORD
463
+ }
464
+
407
465
  if (runtime.process.env.DEBUG_BRIDGE) {
408
- // id/level
409
- global.entodictonDebugBridge = runtime.process.env.DEBUG_BRIDGE.split('/')
410
- if (global.entodictonDebugBridge.length !== 2) {
411
- console.log('Expected DEBUG_BRIDGE to be of the form "id/level"')
412
- process.exit(-1)
413
- }
466
+ // id
467
+ global.entodictonDebugBridge = runtime.process.env.DEBUG_BRIDGE
414
468
  global.entodictonDebugBridge[1] = parseInt(global.entodictonDebugBridge[1])
415
469
  }
416
470
 
@@ -514,7 +568,7 @@ function isLetter (char) {
514
568
  }
515
569
  */
516
570
 
517
- function configDup (config, options) {
571
+ async function configDup (config, options) {
518
572
  if (config instanceof Config) {
519
573
  return config.copy(options)
520
574
  }
@@ -654,9 +708,9 @@ class KM {
654
708
  return true
655
709
  }
656
710
 
657
- copy2 (options) {
711
+ async copy2 (options) {
658
712
  // greg -> add a flag to say don't init the api's
659
- const config = configDup(this._config, options)
713
+ const config = await configDup(this._config, options)
660
714
  const km = new KM({
661
715
  config,
662
716
  getCounter: options.getCounter,
@@ -668,10 +722,10 @@ class KM {
668
722
  return km // copy2()
669
723
  }
670
724
 
671
- copy () {
725
+ async copy () {
672
726
  const km = new KM({
673
727
  name: this._name,
674
- config: configDup(this._config),
728
+ config: await configDup(this._config),
675
729
  // _uuid: uuidv4(),
676
730
  _uuid: this._config.getCounter(this._config._name),
677
731
  getCounter: (name) => this._config.getCounter(name),
@@ -723,12 +777,11 @@ const multiApiImpl = (initializer) => {
723
777
  multiApi: true,
724
778
 
725
779
  // multi functions
726
- add: (config, multiApi, api) => {
780
+ add: async (config, multiApi, api, apiConstructor) => {
727
781
  initializer(config, api)
728
782
  const name = api.getName()
729
783
  multiApi.apis[name] = api
730
- // api.objects = config.get('objects')
731
- // api.config = () => config
784
+ multiApi.apiConstructors[name] = apiConstructor
732
785
  multiApi.current = name
733
786
  },
734
787
 
@@ -751,6 +804,9 @@ const multiApiImpl = (initializer) => {
751
804
  apis: {
752
805
  },
753
806
 
807
+ apiConstructors: {
808
+ },
809
+
754
810
  // api functions
755
811
  api: (multiApi) => multiApi.apis[multiApi.current]
756
812
  })
@@ -761,17 +817,6 @@ class Config {
761
817
  return config_toServer(config)
762
818
  }
763
819
 
764
- base () {
765
- const base = new Config()
766
- for (const km of this.configs.reverse()) {
767
- if (km.isSelf) {
768
- continue
769
- }
770
- base.add(km.config)
771
- }
772
- return base
773
- }
774
-
775
820
  getInfo () {
776
821
  const name = this.name
777
822
  const includes = this.configs.slice(1).map((km) => km.config.name)
@@ -815,6 +860,7 @@ class Config {
815
860
  addArgs: (...args) => this.addArgs(...args),
816
861
  getBridge: (...args) => this.getBridge(...args),
817
862
  fragment: (...args) => this.fragment(...args),
863
+ server: (...args) => this.server(...args),
818
864
  exists: (...args) => this.exists(...args),
819
865
  addAPI: (...args) => this.addAPI(...args)
820
866
  }
@@ -951,23 +997,8 @@ class Config {
951
997
 
952
998
  // value is in response field
953
999
  // TODO maybe generalize out query+evaluate along the lines of set value and set reference
954
- /*
955
- getEvaluator (s, log, context) {
956
- const instance = s({ ...context, evaluate: true })
957
- if (!instance.evalue && !instance.verbatim && !instance.value) {
958
- this.warningNotEvaluated(log, context);
959
- }
960
- if (!instance.evalue) {
961
- instance.evalue = instance.value
962
- instance.edefault = true
963
- }
964
- delete instance.evaluate
965
- instance.instance = true;
966
- return instance
967
- }
968
- */
969
- getEvaluator (s, calls, log, context) {
970
- const instance = s({ ...context, evaluate: true })
1000
+ async getEvaluator (s, calls, log, context) {
1001
+ const instance = await s({ ...context, evaluate: true })
971
1002
  calls.touch(instance)
972
1003
  if (!instance.evalue && !instance.verbatim && !instance.value) {
973
1004
  this.warningNotEvaluated(log, context)
@@ -981,19 +1012,21 @@ class Config {
981
1012
  return instance
982
1013
  }
983
1014
 
984
- fragmentInstantiator (contexts) {
1015
+ fragmentInstantiator (args, contexts) {
985
1016
  return new Object({
986
1017
  contexts: () => contexts,
987
- instantiate: (mappings) => {
1018
+ instantiate: async (mappings) => {
988
1019
  const instantiated = _.cloneDeep(contexts)
989
1020
  // const todo = [...instantiated]
990
1021
  // const todo = [...instantiated]
991
1022
  const todo = _.clone(instantiated)
1023
+ args = {...args}
992
1024
  while (todo.length > 0) {
993
1025
  const context = todo.pop()
1026
+ args.context = context
994
1027
  for (const mapping of mappings) {
995
- if (mapping.match({ context })) {
996
- mapping.apply({ context })
1028
+ if (await mapping.match(args)) {
1029
+ await mapping.apply(args)
997
1030
  }
998
1031
  }
999
1032
  for (const key of Object.keys(context)) {
@@ -1012,11 +1045,21 @@ class Config {
1012
1045
  })
1013
1046
  }
1014
1047
 
1015
- fragment (query) {
1048
+ fragment (args, query) {
1016
1049
  for (const instance of (this.instances || [])) {
1017
1050
  for (const fragment of (instance.fragments || [])) {
1018
1051
  if (fragment.query === query) {
1019
- return this.fragmentInstantiator(fragment.contexts)
1052
+ return this.fragmentInstantiator(args, fragment.contexts)
1053
+ }
1054
+ }
1055
+ for (const fragment of (instance.resultss || [])) {
1056
+ if (fragment.isFragment && fragment.query === query) {
1057
+ return this.fragmentInstantiator(args, fragment.contexts)
1058
+ }
1059
+ }
1060
+ for (const fragment of (this.fragmentsBeingBuilt || [])) {
1061
+ if (fragment.query === query) {
1062
+ return this.fragmentInstantiator(args, fragment.contexts)
1020
1063
  }
1021
1064
  }
1022
1065
  }
@@ -1056,6 +1099,27 @@ class Config {
1056
1099
  } else {
1057
1100
  const config = { ...queryOrConfig }
1058
1101
  delete config.where
1102
+
1103
+ if (config.words && config.words.hierarchy) {
1104
+ config.words.hierarchy = config.words.hierarchy.map( (value) => {
1105
+ value = {...value}
1106
+ delete value.uuid
1107
+ return value
1108
+ })
1109
+ }
1110
+
1111
+ if (config.words && config.words.patterns) {
1112
+ config.words.patterns = config.words.patterns.map( (value) => {
1113
+ value = {...value}
1114
+ value.defs = value.defs.map( (value) => {
1115
+ value = {...value}
1116
+ delete value.uuid
1117
+ return value
1118
+ })
1119
+ return value
1120
+ })
1121
+ }
1122
+
1059
1123
  config.operators = (config.operators || []).map((operator) => {
1060
1124
  if (typeof operator === 'string') {
1061
1125
  return { pattern: operator }
@@ -1083,6 +1147,9 @@ class Config {
1083
1147
  delete bridge.generatorpr
1084
1148
  delete bridge.evaluator
1085
1149
  delete bridge.semantic
1150
+ if (!bridge.bridge) {
1151
+ bridge.bridge = "{ ...next(operator) }"
1152
+ }
1086
1153
  return bridge
1087
1154
  })
1088
1155
  } else {
@@ -1134,8 +1201,24 @@ class Config {
1134
1201
  let startOfChanges
1135
1202
  for (let iq = 0; iq < templateQueries.length; ++iq) {
1136
1203
  if (!helpers.safeEquals(templateQueries[iq], instanceQueries[iq])) {
1137
- sameQueries = false
1138
- startOfChanges = iq
1204
+ // if the current and rest are not queries or fragments then treat as not needing rebuild
1205
+ if (templateQueries.length != instanceQueries.length) {
1206
+ sameQueries = false
1207
+ startOfChanges = iq
1208
+ } else {
1209
+ let hasQueryOrFragment = false
1210
+ for (let rest = iq; rest < templateQueries.length; ++rest) {
1211
+ const value = templateQueries[rest]
1212
+ if (typeof value == 'string' || (value.query && value.isFragment)) {
1213
+ hasQueryOrFragment = true
1214
+ break
1215
+ }
1216
+ }
1217
+ if (hasQueryOrFragment) {
1218
+ sameQueries = false
1219
+ startOfChanges = iq
1220
+ }
1221
+ }
1139
1222
  break;
1140
1223
  }
1141
1224
  }
@@ -1160,7 +1243,9 @@ class Config {
1160
1243
  // console.log("instanceFragments", instanceFragments)
1161
1244
  }
1162
1245
  }
1163
- if (startOfChanges || instance.resultss) {
1246
+ if (startOfChanges) {
1247
+ return { needsRebuild: true, startOfChanges, previousResultss: instance.resultss }
1248
+ } else if (startOfChanges || instance.resultss) {
1164
1249
  return { needsRebuild: !(instance && sameQueries && sameFragments), startOfChanges, previousResultss: instance.resultss }
1165
1250
  } else {
1166
1251
  return { needsRebuild: !(instance && sameQueries && sameFragments) }
@@ -1185,7 +1270,7 @@ class Config {
1185
1270
  }
1186
1271
 
1187
1272
  // loadTemplate
1188
- load (template, instance, options = { rebuild: false, previousResultss: undefined, startOfChanges: undefined }) {
1273
+ async load (rebuildTemplate, template, instance, options = { rebuild: false, previousResultss: undefined, startOfChanges: undefined }) {
1189
1274
  this.validifyTemplate(template)
1190
1275
  instance.template = template
1191
1276
  this.logs.push(`loading template for ${this.name}`)
@@ -1193,7 +1278,7 @@ class Config {
1193
1278
  // TODO fix beforeQuery
1194
1279
  template = { fragments: [], configs: [], ...template }
1195
1280
  template.fragments = template.fragments.concat(this.dynamicFragments)
1196
- client.rebuildTemplate({ config: this, target: this.name, previousResultss: options.previousResultss, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options })
1281
+ await rebuildTemplate({ config: this, target: this.name, previousResultss: options.previousResultss, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options })
1197
1282
  } else {
1198
1283
  // no change
1199
1284
  // this.initInstances.push({ ...instance, name: config.name })
@@ -1218,7 +1303,7 @@ class Config {
1218
1303
  instance.name = this.name
1219
1304
  this.initInstances.push(instance)
1220
1305
  this.instances.push(instance)
1221
- client.loadInstance(this, instance)
1306
+ await configHelpers.loadInstance(this, instance)
1222
1307
  }
1223
1308
  }
1224
1309
  }
@@ -1272,9 +1357,9 @@ class Config {
1272
1357
  }
1273
1358
  }
1274
1359
 
1275
- addHierarchy (child, parent) {
1360
+ addHierarchy (child, parent, instance) {
1276
1361
  if (child && parent || !child || Array.isArray(child) || (typeof child === 'string' && !parent)) {
1277
- this.addHierarchyChildParent(child, parent)
1362
+ this.addHierarchyChildParent(child, parent, instance)
1278
1363
  // this.addHierarchyProperties ({ child, parent })
1279
1364
  } else {
1280
1365
  this.addHierarchyProperties(child)
@@ -1282,26 +1367,32 @@ class Config {
1282
1367
  }
1283
1368
 
1284
1369
  addHierarchyProperties (edge) {
1285
- const { child, parent } = edge
1370
+ const { child, parent, instance } = edge
1286
1371
  if (typeof child !== 'string') {
1287
1372
  throw new Error(`addHierarchy expected child property to be a string. got ${JSON.stringify(child)}`)
1288
1373
  }
1289
1374
  if (typeof parent !== 'string') {
1290
1375
  throw new Error(`addHierarchy expected parent property to be a string. got ${JSON.stringify(parent)}`)
1291
1376
  }
1377
+ if (instance && typeof instance !== 'boolean') {
1378
+ throw new Error(`addHierarchy expected instance property to be a boolean or undefined. got ${JSON.stringify(instance)}`)
1379
+ }
1292
1380
  debugHierarchy([child, parent])
1293
1381
  this.config.hierarchy.push(edge)
1294
1382
  // TODO greg11 this.hierarchy.addEdge(edge)
1295
- this._delta.json.hierarchy.push([child, parent])
1383
+ this._delta.json.hierarchy.push([child, parent, instance || false])
1296
1384
  }
1297
1385
 
1298
- addHierarchyChildParent (child, parent) {
1386
+ addHierarchyChildParent (child, parent, instance) {
1299
1387
  if (typeof child !== 'string') {
1300
1388
  throw new Error(`addHierarchy expected child to be a string. got ${JSON.stringify(child)}`)
1301
1389
  }
1302
1390
  if (typeof parent !== 'string') {
1303
1391
  throw new Error(`addHierarchy expected parent to be a string. got ${JSON.stringify(parent)}`)
1304
1392
  }
1393
+ if (instance && typeof instance !== 'boolean') {
1394
+ throw new Error(`addHierarchy expected instance property to be a boolean or undefined. got ${JSON.stringify(instance)}`)
1395
+ }
1305
1396
  debugHierarchy([child, parent])
1306
1397
  if (this.config.hierarchy.find((element) => {
1307
1398
  const hc = hierarchyCanonical(element)
@@ -1312,9 +1403,9 @@ class Config {
1312
1403
  return
1313
1404
  }
1314
1405
 
1315
- this.config.hierarchy.push([child, parent])
1406
+ this.config.hierarchy.push([child, parent, instance || false])
1316
1407
  // this.hierarchy.addEdge([child, parent])
1317
- this._delta.json.hierarchy.push([child, parent])
1408
+ this._delta.json.hierarchy.push([child, parent, instance || false])
1318
1409
  }
1319
1410
 
1320
1411
  getBridge (id, level) {
@@ -1361,7 +1452,7 @@ class Config {
1361
1452
  }
1362
1453
 
1363
1454
  if (!generator.where) {
1364
- generator.where = client.where(3)
1455
+ generator.where = helpers.where(3)
1365
1456
  }
1366
1457
 
1367
1458
  const generators = this.config.generators
@@ -1384,7 +1475,7 @@ class Config {
1384
1475
  }
1385
1476
 
1386
1477
  if (!semantic.where) {
1387
- semantic.where = client.where(3)
1478
+ semantic.where = helpers.where(3)
1388
1479
  }
1389
1480
 
1390
1481
  const semantics = this.config.semantics
@@ -1458,6 +1549,7 @@ class Config {
1458
1549
  hierarchy: [],
1459
1550
  }
1460
1551
  }
1552
+ debugWord(word)
1461
1553
 
1462
1554
  const literals = this.config.words.literals
1463
1555
  def = Object.assign({}, def, { uuid: uuid || this._uuid })
@@ -1570,16 +1662,20 @@ class Config {
1570
1662
  return params
1571
1663
  }
1572
1664
 
1573
- processContexts (contexts, params) {
1574
- client.processContexts(contexts, this.getParams())
1665
+ async processContext (context) {
1666
+ return await configHelpers.processContext(context, this.getParams())
1575
1667
  }
1576
1668
 
1577
- processContext (context) {
1578
- return client.processContext(context, this.getParams())
1669
+ process (query, options) {
1670
+ return this.clientProcess(this, query, options)
1579
1671
  }
1580
1672
 
1581
- process (query, options) {
1582
- return client.process(this, query, options)
1673
+ query (query, options) {
1674
+ return this.process(query, options)
1675
+ }
1676
+
1677
+ processQuery (query, options) {
1678
+ return this.process(query, options)
1583
1679
  }
1584
1680
 
1585
1681
  initDefaults () {
@@ -1711,8 +1807,25 @@ class Config {
1711
1807
  config.words.hierarchy = hierarchyPrime
1712
1808
  }
1713
1809
 
1810
+ terminate() {
1811
+ this.configs.forEach((km) => {
1812
+ const config = km.config
1813
+ if (!config.terminatorFn) {
1814
+ this.terminatorFn(this)
1815
+ } else {
1816
+ config.terminatorFn(this)
1817
+ }
1818
+ })
1819
+ }
1820
+
1821
+ setTerminator(terminatorFn) {
1822
+ if (terminatorFn) {
1823
+ this.terminatorFn = terminatorFn
1824
+ }
1825
+ }
1826
+
1714
1827
  // configs = [ { config, namespace } ... ]
1715
- constructor (config, module) {
1828
+ constructor (config, module, clientProcess) {
1716
1829
  if (config instanceof Config) {
1717
1830
  throw new Error('Excepted the config argument to be a hash not a Config object')
1718
1831
  }
@@ -1730,6 +1843,7 @@ class Config {
1730
1843
  config.priorities = config.priorities || []
1731
1844
  }
1732
1845
 
1846
+ this.clientProcess = clientProcess
1733
1847
  this.maxDepth = 20 // for generators and semantics
1734
1848
  this.debugLoops = false // for generators and semantics
1735
1849
 
@@ -1755,24 +1869,6 @@ class Config {
1755
1869
  // when running configs any bridges added are marked as transitory so that the associated will ignore those op's
1756
1870
  this.transitoryMode = false
1757
1871
 
1758
- // check for duplicate bridges
1759
- if (config && config.bridges) {
1760
- let duplicated = new Set()
1761
- const seen = new Set()
1762
- for (const bridge of config.bridges) {
1763
- const id = `${bridge.id}/${bridge.level}`
1764
- if (seen.has(id)) {
1765
- duplicated.add(id)
1766
- } else {
1767
- seen.add(id)
1768
- }
1769
- }
1770
- duplicated = Array.from(duplicated)
1771
- if (duplicated.length > 0) {
1772
- throw new Error(`In the KM ${config.name}, the following operators are duplicated in the bridges: ${duplicated}`)
1773
- }
1774
- }
1775
-
1776
1872
  if (config && config.words) {
1777
1873
  initWords(config.words)
1778
1874
  isValidWordDef(config.words)
@@ -1794,6 +1890,7 @@ class Config {
1794
1890
  currentConfig.wasInitialized = true
1795
1891
  }
1796
1892
  }
1893
+ this.terminatorFn = () => {}
1797
1894
  if (config) {
1798
1895
  this.name = config.name
1799
1896
  }
@@ -1821,6 +1918,7 @@ class Config {
1821
1918
  }
1822
1919
  this.get('objects').namespaced[this._uuid] = {}
1823
1920
  this.valid()
1921
+ this.checks()
1824
1922
  debugConfigProps(this.config)
1825
1923
  }
1826
1924
 
@@ -1832,9 +1930,9 @@ class Config {
1832
1930
  this._stop_auto_rebuild = true
1833
1931
  }
1834
1932
 
1835
- restart_auto_rebuild() {
1933
+ async restart_auto_rebuild() {
1836
1934
  this._stop_auto_rebuild = false
1837
- this.rebuild()
1935
+ await this.rebuild()
1838
1936
  }
1839
1937
 
1840
1938
  getAddedArgs (args) {
@@ -1853,8 +1951,8 @@ class Config {
1853
1951
  }
1854
1952
  }
1855
1953
 
1856
- set multiApi (initializer) {
1857
- this.api = multiApiImpl(initializer)
1954
+ async setMultiApi (initializer) {
1955
+ await this.setApi(() => multiApiImpl(initializer))
1858
1956
  }
1859
1957
 
1860
1958
  get multiApi () {
@@ -1902,31 +2000,38 @@ class Config {
1902
2000
  }
1903
2001
  }
1904
2002
 
1905
- addAPI (api) {
2003
+ async addAPI (api) {
2004
+ // console.trace()
2005
+ // throw "addAPI"
1906
2006
  if (this._api && this._api.multiApi) {
1907
- this._api.add(this, this._api, api)
2007
+ await this._api.add(this, this._api, api)
1908
2008
  } else {
1909
2009
  throw new Error('Can only add apis to a multi-api')
1910
2010
  }
1911
2011
  }
1912
2012
 
1913
- set api (value) {
2013
+ async setApi (constructor) {
2014
+ if (typeof constructor !== 'function') {
2015
+ throw new Error(`Expected the argument to be an API constructor for ${this.name}.`)
2016
+ }
2017
+ const value = constructor()
1914
2018
  if (!value.initialize) {
1915
2019
  throw new Error(`Expected the API to have an initialize function for ${this.name}.`)
1916
2020
  }
1917
2021
 
1918
2022
  if (this._api && this._api.multiApi) {
1919
- this._api.add(this, this._api, value)
1920
- } else {
1921
- this._api = _.cloneDeep(value)
1922
- /*
1923
- if (this._api) {
1924
- // this._api.objects = this.config.objects
1925
- // this._api.config = () => this
1926
- // this._api.uuid = this._uuid
2023
+ await this._api.add(this, this._api, value, constructor)
2024
+ const previousApiConstructor = this._apiConstructor
2025
+ this._apiConstructor = (config) => {
2026
+ const api = previousApiConstructor(config)
2027
+ // does this need await?
2028
+ api.add(config, api, constructor(config), constructor)
2029
+ return api
1927
2030
  }
1928
- */
1929
- this.rebuild()
2031
+ } else {
2032
+ this._api = value
2033
+ this._apiConstructor = constructor
2034
+ await this.rebuild()
1930
2035
  }
1931
2036
  }
1932
2037
 
@@ -1946,7 +2051,7 @@ class Config {
1946
2051
  }
1947
2052
 
1948
2053
  // remove all added modules and initialize with the init config
1949
- resetToOne () {
2054
+ async resetToOne () {
1950
2055
  /*
1951
2056
  this.config = _.cloneDeep(this.initConfig)
1952
2057
  this.configs = [this.configs[0]]
@@ -1955,11 +2060,8 @@ class Config {
1955
2060
  */
1956
2061
  this.configs = [this.configs[0]]
1957
2062
  this.defaultConfig()
1958
- if (!this.initializeFn) {
1959
- // TODO move this to the default initializer
1960
- Object.assign(this.config.objects, _.cloneDeep(this.initConfig.objects || {}))
1961
- }
1962
- this.initializeConfigFromConfigs({ others: [], objects: this.config.objects.namespaced, moreNames: [], callInitializers: false })
2063
+ Object.assign(this.config.objects, _.cloneDeep(this.initConfig.objects || {}))
2064
+ await this.initializeConfigFromConfigs({ others: [], objects: this.config.objects.namespaced, moreNames: [], callInitializers: false })
1963
2065
  const map = {}
1964
2066
  for (let i = 0; i < this.configs.length; ++i) {
1965
2067
  map[this.configs[i].uuid] = this.configs[i].uuid
@@ -1981,21 +2083,27 @@ class Config {
1981
2083
  runtime.fs.writeFileSync(fn, JSON.stringify(this.config, 0, 2))
1982
2084
  }
1983
2085
 
1984
- copy (options = { callInitializers: true }) {
1985
- }
1986
-
1987
- copy (options = { callInitializers: true }) {
2086
+ async copy (options = { callInitializers: true }) {
1988
2087
  this.valid()
1989
2088
  const cp = new Config()
1990
2089
  cp.logs = []
1991
2090
  cp.maxDepth = this.maxDepth
1992
2091
  cp.debugLoops = this.debugLoops
1993
2092
  cp.transitoryMode = this.transitoryMode
1994
- cp.configs = this.configs.map((km) => km.copy2(Object.assign({}, options, { getCounter: (name) => cp.getCounter(name), callInitializers: false })))
2093
+ // cp.configs = this.configs.map((km) => await km.copy2(Object.assign({}, options, { getCounter: (name) => cp.getCounter(name), callInitializers: false })))
2094
+ cp.configs = []
2095
+ for (const km of this.configs) {
2096
+ cp.configs.push(await km.copy2(Object.assign({}, options, { getCounter: (name) => cp.getCounter(name), callInitializers: false })))
2097
+ }
1995
2098
  cp._uuid = cp.configs[0]._uuid
1996
2099
  // update uuid here set the uuid in the objects and add error checking
1997
2100
  cp.initializerFn = this.initializerFn
1998
- cp._api = _.cloneDeep(this._api)
2101
+ cp.terminatorFn = this.terminatorFn
2102
+ // cp._api = _.cloneDeep(this._api)
2103
+ if (this._apiConstructor) {
2104
+ cp._api = this._apiConstructor(cp)
2105
+ cp._apiConstructor = this._apiConstructor
2106
+ }
1999
2107
  cp._namespace = this._namespace
2000
2108
  cp._eqClasses = this._eqClasses
2001
2109
  cp.name = this.name
@@ -2007,18 +2115,14 @@ class Config {
2007
2115
  cp.instances = this.instances.slice()
2008
2116
  cp.configCounter = this.configCounter
2009
2117
  cp.testConfig = this.testConfig
2118
+ cp._server = this._server
2010
2119
 
2011
2120
  cp.initConfig = _.cloneDeep(this.initConfig)
2012
2121
  cp.defaultConfig()
2013
2122
  // cp.wasInitialized = false; // since default config GREG
2014
2123
  cp.resetWasInitialized()
2015
- if (!this.initializeFn) {
2016
- // TODO move this to the default initializer
2017
- Object.assign(cp.config.objects, _.cloneDeep(this.initConfig.objects || {}))
2018
- }
2019
- // cp.initializeConfigFromConfigs({ others: [], objects: cp.config.objects.namespaced, moreNames: [], ...options })
2020
- // cp.initializeConfigFromConfigs(Object.assign({ others: [], objects: cp.config.objects.namespaced, moreNames: [] }, { callInitializers: false }))
2021
- cp.initializeConfigFromConfigs(Object.assign({ others: [], objects: cp.config.objects.namespaced, moreNames: [] }, options))
2124
+ Object.assign(cp.config.objects, _.cloneDeep(this.initConfig.objects || {}))
2125
+ await cp.initializeConfigFromConfigs(Object.assign({ others: [], objects: cp.config.objects.namespaced, moreNames: [] }, options))
2022
2126
  const map = {}
2023
2127
  for (let i = 0; i < this.configs.length; ++i) {
2024
2128
  map[this.configs[i].uuid] = cp.configs[i].uuid
@@ -2029,33 +2133,16 @@ class Config {
2029
2133
  // debugger
2030
2134
  }
2031
2135
  if (options.callInitializers) {
2032
- cp.rebuild(options)
2136
+ await cp.rebuild(options) // in copy
2033
2137
  } else {
2034
- // this mess is for duplicate into a KM after resetToOne was called
2035
- /*
2036
- if (cp._api) {
2037
- // cp._api.objects = cp.config.objects
2038
- // cp._api.config = () => (cp instanceof Config) ? cp : cp.config
2039
- // cp._api.uuid = cp._uuid
2040
- }
2041
- */
2042
-
2043
2138
  if (!cp.config.objects) {
2044
2139
  cp.config.objects = { namespaced: {} }
2045
2140
  } else if (!cp.config.objects.namespaced) {
2046
2141
  cp.config.objects.namespaced = {}
2047
2142
  }
2048
2143
  cp.configs.forEach((km) => {
2049
- // const namespace = km.namespace
2050
2144
  cp.config.objects.namespaced[km._uuid] = {}
2051
2145
  })
2052
- /*
2053
- if (cp._uuid == 'concept2') {
2054
- if (!cp.api.objects.defaultTypesForHierarchy) {
2055
- debugger
2056
- }
2057
- }
2058
- */
2059
2146
  }
2060
2147
  cp.valid()
2061
2148
  return cp
@@ -2179,41 +2266,7 @@ class Config {
2179
2266
  }
2180
2267
  }
2181
2268
 
2182
- initializeFromConfigs () {
2183
- // [...this.configs].reverse().forEach(({ config, namespace, uuid }) => {
2184
- [...this.configs].reverse().forEach(({ config, namespace, uuid }) => {
2185
- /*
2186
- let objects = this.get('objects')
2187
- if (namespace) {
2188
- objects = {}
2189
- this.get('objects')['namespaced'][namespace] = objects
2190
- }
2191
- */
2192
- const objects = {}
2193
- if (config instanceof Config) {
2194
- this.get('objects').namespaced[config._uuid] = objects
2195
- /*
2196
- if (config._api) {
2197
- // config._api.objects = objects
2198
- // config._api.config = () => this
2199
- }
2200
- */
2201
- config.initializerFn(setupInitializerFNArgs(this, { testConfig: config, currentConfig: config, objects, namespace, uuid }))
2202
- } else {
2203
- this.get('objects').namespaced[this._uuid] = objects
2204
- /*
2205
- if (config._api) {
2206
- // config._api.objects = objects
2207
- // config._api.config = () => this
2208
- }
2209
- */
2210
- this.initializerFn(setupInitializerFNArgs(this, { testConfig: this, currentConfig: this, objects, namespace, uuid }))
2211
- }
2212
- })
2213
- this.instances.forEach((instance) => client.loadInstance(this, instance))
2214
- }
2215
-
2216
- initialize ({ force = true } = {}) {
2269
+ initialize23 ({ force = true } = {}) {
2217
2270
  if (force || !this.wasInitialized) {
2218
2271
  const objects = this.config.objects.namespaced[this._uuid]
2219
2272
  this.initializerFn(setupInitializerFNArgs(this, { testConfig: this, currentConfig: this, objects, uuid: this._uuid, namespace: '' }))
@@ -2221,7 +2274,7 @@ class Config {
2221
2274
  }
2222
2275
  }
2223
2276
 
2224
- initializer (fn, options = {}) {
2277
+ async initializer (fn, options = {}) {
2225
2278
  if (options) {
2226
2279
  for (const option of Object.keys(options)) {
2227
2280
  const validOptions = []
@@ -2243,8 +2296,7 @@ class Config {
2243
2296
  currentConfig.wasInitialized = true
2244
2297
  global.transitoryMode = transitoryMode
2245
2298
  }
2246
- // this.initializeFromConfigs()
2247
- this.rebuild()
2299
+ await this.rebuild()
2248
2300
  }
2249
2301
 
2250
2302
  nsToString (id) {
@@ -2390,7 +2442,7 @@ class Config {
2390
2442
  }
2391
2443
 
2392
2444
  // rebuild ({ isModule: mainIsModule = false } = {}) {
2393
- rebuild ({ isModule: mainIsModule } = {}) {
2445
+ async rebuild ({ isModule: mainIsModule } = {}) {
2394
2446
  if (this._stop_auto_rebuild) {
2395
2447
  return
2396
2448
  }
@@ -2558,7 +2610,7 @@ class Config {
2558
2610
  }
2559
2611
  const instance = this.instances.find((instance) => instance.name == name)
2560
2612
  if (instance) {
2561
- client.loadInstance(this, instance)
2613
+ await configHelpers.loadInstance(this, instance)
2562
2614
  }
2563
2615
  this.hierarchy.edges = this.config.hierarchy
2564
2616
  }
@@ -2566,7 +2618,7 @@ class Config {
2566
2618
 
2567
2619
  this.hierarchy.edges = this.config.hierarchy
2568
2620
  this.valid()
2569
- this.checkBridges()
2621
+ this.checks()
2570
2622
  }
2571
2623
 
2572
2624
  nameToUUID (name) {
@@ -2578,6 +2630,7 @@ class Config {
2578
2630
  // if undefined namespace applies to first loaded config
2579
2631
  // if list of name then namespace applied only to those configs
2580
2632
  // if true then namespace applies to all loaded configs
2633
+ /*
2581
2634
  namespace (moreNames, others) {
2582
2635
  const config = this.copy()
2583
2636
  if (!Array.isArray(moreNames)) {
@@ -2613,6 +2666,7 @@ class Config {
2613
2666
  config.rebuild()
2614
2667
  return config
2615
2668
  }
2669
+ */
2616
2670
 
2617
2671
  setupNamespace (km) {
2618
2672
  let config = km.config
@@ -2631,7 +2685,7 @@ class Config {
2631
2685
 
2632
2686
  // config.initializerFn({ config: this, objects, namespace })
2633
2687
  // this goes through all the configs and sets up this.config
2634
- initializeConfigFromConfigs ({ others, objects, moreNames, callInitializers = true }) {
2688
+ async initializeConfigFromConfigs ({ others, objects, moreNames, callInitializers = true }) {
2635
2689
  // setup the namespace in the configs
2636
2690
  let first = true
2637
2691
  this.configs.forEach((km) => {
@@ -2780,6 +2834,11 @@ class Config {
2780
2834
  }
2781
2835
  }
2782
2836
 
2837
+ checks () {
2838
+ this.checkOperators()
2839
+ this.checkBridges()
2840
+ }
2841
+
2783
2842
  checkOperators () {
2784
2843
  if (!this.config.operators) {
2785
2844
  return
@@ -2800,53 +2859,19 @@ class Config {
2800
2859
  return
2801
2860
  }
2802
2861
 
2803
- /*
2804
- "namespaces": {
2805
- "634a678b-8d92-4464-bf65-943a82f404d8": {
2806
- "ids": [ "tankConcept" ],
2807
- "namespace": [ "ns1" ]
2808
- },
2809
- console.log('before check', JSON.stringify(this._eqClasses, null, 2))
2810
- */
2811
-
2812
- const errors = []
2813
- /*
2814
- const namespaces = this.config.namespaces
2815
- const nsToIds = {}
2816
- for (const uuid in namespaces) {
2817
- const namespace = namespaces[uuid].namespace
2818
- const ns = namespace.join('#')
2819
- if (!nsToIds[ns]) {
2820
- nsToIds[ns] = new Set()
2821
- }
2822
- const ids = nsToIds[ns]
2823
- for (const id of namespaces[uuid].ids) {
2824
- if (ids.has(id)) {
2825
- if (ns === '') {
2826
- const dups = this.config.bridges.filter( (bridge) => bridge.id == id )
2827
- errors.push(`Id '${id}' is defined more than once in the bridges of the base namespace of the KM ${this.name}, Dups are ${JSON.stringify(dups)}`)
2828
- } else {
2829
- errors.push(`Id '${id}' is defined more than once in the bridges of the ${ns} namespace of the KM ${this.name}`)
2830
- }
2831
- } else {
2832
- ids.add(id)
2833
- }
2834
- }
2835
- }
2836
- */
2837
-
2838
- const keyIsPresent = {}
2862
+ let duplicated = new Set()
2863
+ const seen = new Set()
2839
2864
  for (const bridge of this.config.bridges) {
2840
- const key = `${bridge.id}/${bridge.level} (namespace: ${bridge.uuid})`
2841
- if (keyIsPresent[key]) {
2842
- errors.push(new Error(`Id '${key}' is defined more than once in bridges of the base namespace of the KM ${this.name}`))
2865
+ const id = `${bridge.id}/${bridge.level} (namespace: ${bridge.uuid || this.uuid})`
2866
+ if (seen.has(id)) {
2867
+ duplicated.add(id)
2843
2868
  } else {
2844
- keyIsPresent[key] = key
2869
+ seen.add(id)
2845
2870
  }
2846
2871
  }
2847
-
2848
- if (errors.length > 0) {
2849
- throw errors
2872
+ duplicated = Array.from(duplicated)
2873
+ if (duplicated.length > 0) {
2874
+ throw new Error(`In the KM ${this.name}, the following operators are duplicated in the bridges: ${duplicated}`)
2850
2875
  }
2851
2876
  };
2852
2877
 
@@ -2903,25 +2928,29 @@ class Config {
2903
2928
  }
2904
2929
  }
2905
2930
 
2906
- add (...mores) {
2907
- mores.forEach((km) => {
2908
- if (km === this) {
2909
- throw new Error('Cannot add an object to itself.')
2931
+ async add (...createConfigs) {
2932
+ createConfigs.forEach((createConfig, index) => {
2933
+ if (typeof createConfig !== 'function') {
2934
+ throw new Error(`Expected add argument number ${index+1} to be a function that constructs the config.`)
2910
2935
  }
2911
2936
  })
2912
2937
 
2913
- mores = mores.map((km) => {
2914
- if (!(km instanceof Config)) {
2915
- km = new Config(km)
2938
+ const mores = []
2939
+ for (const createConfig of createConfigs) {
2940
+ const more = await createConfig()
2941
+ if (this.name && this.name == more.name) {
2942
+ throw new Error('Cannot add an object to itself for argument number ${index+1}.')
2916
2943
  }
2917
- return km
2918
- })
2919
-
2920
- mores.forEach((more) => {
2944
+ if (this === more) {
2945
+ throw new Error('Cannot add an object to itself.')
2946
+ }
2947
+ mores.push(more)
2948
+ }
2949
+ for (let more of mores) {
2921
2950
  this.valid()
2922
2951
  more.valid()
2923
2952
  // copy so i don't have to copy later
2924
- more = more.copy()
2953
+ more = await more.copy()
2925
2954
  more.server(this._server, this._key, this._queryParams)
2926
2955
 
2927
2956
  const moreConfigs = more.configs.map((km) => km.name || km.uuid)
@@ -2936,9 +2965,6 @@ class Config {
2936
2965
  const moreKMs1 = [new KM({ config: more, getCounter: (name) => this.getCounter(name), uuid: more.uuid, namespace })]
2937
2966
  const moreKMs2 = more.configs.slice(1).map((km) => {
2938
2967
  return km
2939
- // const cp = km.copy()
2940
- // cp.namespace = namespace
2941
- // return cp;
2942
2968
  })
2943
2969
  const moreKMs = moreKMs1.concat(moreKMs2)
2944
2970
  const eqClass = moreKMs.map((km) => km.uuid)
@@ -2952,7 +2978,7 @@ class Config {
2952
2978
  this.configs.push(moreKM)
2953
2979
  }
2954
2980
  }
2955
- more.resetToOne()
2981
+ await more.resetToOne()
2956
2982
  this.config.eqClasses = this._eqClasses
2957
2983
  // greg
2958
2984
  // setup instances
@@ -2967,8 +2993,8 @@ class Config {
2967
2993
  }
2968
2994
  }
2969
2995
  this.instances = noDups
2970
- })
2971
- this.rebuild()
2996
+ }
2997
+ await this.rebuild() // in add(
2972
2998
  this.valid()
2973
2999
  return this
2974
3000
  }
@@ -3124,7 +3150,7 @@ class Config {
3124
3150
  // assumes this is called in reverse order
3125
3151
  addInternalR (more, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false) {
3126
3152
  if (more instanceof Config) {
3127
- more.initialize({ force: false })
3153
+ more.initialize23({ force: false })
3128
3154
  if (useOldVersion) {
3129
3155
  more = more.config
3130
3156
  } else {