theprogrammablemind_4wp 8.0.0 → 8.1.0-beta.1

Sign up to get free protection for your applications and to get access to all the features.
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 {