theprogrammablemind_4wp 7.7.0 → 7.8.0

Sign up to get free protection for your applications and to get access to all the features.
package/client.js CHANGED
@@ -30,18 +30,29 @@ const pickObjects = (testConfig, objects) => {
30
30
  return project(objects, getConfig_getObjectsCheck(testConfig))
31
31
  }
32
32
 
33
+ // move ask to the KM's since verbatim is called
33
34
  const getAsk = (config) => (uuid) => (asks) => {
34
35
  for (let ask of asks) {
36
+ let oneShot = true // default
37
+ if (ask.oneShot === false) {
38
+ oneShot = false
39
+ }
35
40
  config.addSemantic({
36
41
  uuid,
37
- oneShot: true,
42
+ oneShot,
38
43
  match: (args) => ask.matchr(args),
39
44
  apply: (args) => ask.applyr(args)
40
45
  })
41
46
  }
47
+ let oneShot = true
48
+ for (let ask of asks) {
49
+ if (ask.oneShot === false) {
50
+ oneShot = false
51
+ }
52
+ }
42
53
  config.addSemantic({
43
54
  uuid,
44
- oneShot: true,
55
+ oneShot,
45
56
  match: ({context}) => context.marker == 'controlEnd' || context.marker == 'controlBetween',
46
57
  apply: (args) => {
47
58
  for (let ask of asks) {
@@ -57,14 +68,18 @@ const getAsk = (config) => (uuid) => (asks) => {
57
68
  }
58
69
  if (matchq(args)) {
59
70
  // args.context.motivationKeep = true
71
+ args.verbatim(applyq(args))
72
+ /*
60
73
  args.context.verbatim = applyq(args)
61
74
  args.context.isResponse = true;
62
75
  delete args.context.controlRemove;
76
+ */
63
77
  args.context.controlKeepMotivation = true;
64
78
  break
65
79
  }
66
80
  }
67
- }
81
+ args.context.cascade = true
82
+ }
68
83
  })
69
84
  }
70
85
 
@@ -169,6 +184,7 @@ const setupArgs = (args, config, logs, hierarchy) => {
169
184
  apis: getAPIs(uuid)
170
185
  }
171
186
  }
187
+ Object.assign(args, args.getUUIDScoped(this.uuid))
172
188
  args.breakOnSemantics = false
173
189
  args.theDebugger = {
174
190
  breakOnSemantics: (value) => args.breakOnSemantics = value
@@ -179,11 +195,23 @@ const setupArgs = (args, config, logs, hierarchy) => {
179
195
  args.log = (message) => logs.push(message)
180
196
 
181
197
  args.addAssumedScoped = (args, assumed) => {
198
+ const addAssumed = (args, ...moreAssumed) => {
199
+ return { ...args, assumed: Object.assign({}, (args.assumed || {}), ...moreAssumed) }
200
+ }
201
+
182
202
  args.s = (c) => config.getSemantics(logs).apply(args, c)
183
- args.g = (c) => config.getGenerators(logs).apply(args, c)
184
- args.gp = (c) => config.getGenerators(logs).apply({...args, assumed: {paraphrase: true, isResponse: false, response: false}}, c, {paraphrase: true, isResponse: false, response: false})
185
- args.gr = (c) => config.getGenerators(logs).apply({...args, assumed: {paraphrase: false, isResponse: true}}, { ...c, paraphrase: false, isResponse: true })
186
- args.e = (c) => config.getEvaluator(args.s, args.calls, logs, c)
203
+ args.g = (c, a = {}) => {
204
+ return config.getGenerators(logs).apply(addAssumed(args, a), c, a)
205
+ }
206
+ args.gp = (c, a = {}) => {
207
+ return config.getGenerators(logs).apply(addAssumed(args, a, {paraphrase: true, isResponse: false, response: false}), c, {paraphrase: true, isResponse: false, response: false})
208
+ }
209
+ args.gr = (c, a = {}) => {
210
+ return config.getGenerators(logs).apply(addAssumed(args, a, {paraphrase: false, isResponse: true}), { ...c, paraphrase: false, isResponse: true })
211
+ }
212
+ args.e = (c) => {
213
+ return config.getEvaluator(args.s, args.calls, logs, c)
214
+ }
187
215
  args.gs = gs(args.g)
188
216
  args.gsp = gs(args.gp)
189
217
  args.gsr = gs(args.gr)
@@ -467,8 +495,6 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
467
495
  }
468
496
  // assumed = { paraphrase: true, response: false };
469
497
  assumed = { paraphrase: true, isResponse: false, response: false };
470
- // args.g = (c) => config.getGenerators(json.logs).apply({...args, assumed}, c, assumed)
471
- // args.gs = gs(args.g)
472
498
  if (generateParenthesized) {
473
499
  config.parenthesized = false
474
500
  }
@@ -479,8 +505,6 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
479
505
  paraphrasesParenthesized = config.getGenerators(json.logs).apply({...args, assumed}, contextPrime, assumed)
480
506
  config.parenthesized = false
481
507
  }
482
- // args.g = (c) => config.getGenerators(json.logs).apply(args, c)
483
- // args.gs = gs(args.g)
484
508
  contextsPrime.push(contextPrime)
485
509
  generatedPrime.push(generated)
486
510
  paraphrasesPrime.push(paraphrases)
@@ -613,11 +637,25 @@ const loadInstance = (config, instance) => {
613
637
  // config.addInternal(results, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false)
614
638
  // config.addInternal(config.template.queries[i], { handleCalculatedProps: true } )
615
639
  config.addInternal(instance.template.queries[i], { addFirst: true, handleCalculatedProps: true } )
640
+ } else if (results.apply) {
641
+ const objects = config.get('objects')
642
+ const args = { objects, getObjects: getObjects(objects) }
643
+ if (instance.queries) {
644
+ args.isInstance = `instance${i}`
645
+ args.instance = instance.queries[i]
646
+ }
647
+ setupArgs(args, config, config.logs, hierarchy)
648
+ results.apply(args)
616
649
  } else {
617
650
  if (results.skipSemantics) {
618
651
  config.config.skipSemantics = results.skipSemantics
619
652
  }
620
- processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {}, isInstance: `instance${i}`, instance: instance.queries[i] })
653
+ const args = { config, hierarchy, json: results, commandLineArgs: {} }
654
+ if (instance.queries) {
655
+ args.isInstance = `instance${i}`
656
+ args.instance = instance.queries[i]
657
+ }
658
+ processContextsB(args)
621
659
  if (results.skipSemantics) {
622
660
  config.config.skipSemantics = null
623
661
  }
@@ -1183,8 +1221,8 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
1183
1221
 
1184
1222
  if (responses.explain_priorities) {
1185
1223
  console.log("Explain Priorities")
1186
- for ([inputss, outpus, reason] of responses.explain_priorities) {
1187
- console.log(` ${JSON.stringify(inputss)} reason: ${reason}`)
1224
+ for ([inputs, output, reason] of responses.explain_priorities) {
1225
+ console.log(` inputs: ${JSON.stringify(inputs)} output: ${JSON.stringify(output)} reason: ${reason}`)
1188
1226
  }
1189
1227
  }
1190
1228
  const objects = config.get('objects').namespaced[config.uuid]
@@ -1241,7 +1279,7 @@ const defaultProcess = ({ config, errorHandler }) => async (promise) => {
1241
1279
  }
1242
1280
 
1243
1281
  // builtTemplate saveInstance
1244
- const rebuildTemplate = async ({ config, target, template, errorHandler = defaultErrorHandler }) => {
1282
+ const rebuildTemplate = async ({ config, target, previousResultss, startOfChanges, template, errorHandler = defaultErrorHandler }) => {
1245
1283
  const accumulators = {
1246
1284
  resultss: [],
1247
1285
  fragments: [],
@@ -1254,7 +1292,7 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1254
1292
  finish()
1255
1293
  return
1256
1294
  }
1257
- const { property, hierarchy, query: queryOrExtraConfig, initializer, skipSemantics } = queries.shift()
1295
+ const { property, hierarchy, query: queryOrExtraConfig, previousResults, initializer, skipSemantics } = queries.shift()
1258
1296
  // queries are strings or { query: "blah", development: true/false }
1259
1297
  if (typeof queryOrExtraConfig === 'string' || queryOrExtraConfig.query) {
1260
1298
  let query = queryOrExtraConfig;
@@ -1276,17 +1314,26 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1276
1314
  }
1277
1315
  }
1278
1316
  try {
1279
- const results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
1317
+ let results
1318
+ let prMessage = ''
1319
+ if (previousResults && previousResults.query == query.query) {
1320
+ results = previousResults
1321
+ prMessage = ' Using previous results. use -rtf for a hard rebuild of everything on the server side.'
1322
+ loadInstance(config, { resultss: [results] })
1323
+ } else {
1324
+ results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
1325
+ }
1280
1326
  if (config.config.debug) {
1281
1327
  // TODO pass in the error handler like the other ones
1282
1328
  defaultInnerProcess(config, defaultErrorHandler, results)
1283
1329
  }
1284
1330
  if (results.contexts.length > 1) {
1285
1331
  console.log(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
1332
+ throw new Error(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
1286
1333
  } else if (results.paraphrases[0] != query.query) {
1287
- console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}".`)
1334
+ console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}".${prMessage}`)
1288
1335
  } else {
1289
- console.log(`query ${query.query}`)
1336
+ console.log(`query "${query.query}".${prMessage}`)
1290
1337
  }
1291
1338
  global.transitoryMode = transitoryMode
1292
1339
  config.config.skipSemantics = null
@@ -1303,19 +1350,32 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1303
1350
  config.config.skipSemantics = null
1304
1351
  errorHandler(error)
1305
1352
  }
1353
+ } else if (typeof queryOrExtraConfig == 'function') {
1354
+ console.log('calling initialize function')
1355
+ const initFunction = queryOrExtraConfig
1356
+ const objects = config.get('objects')
1357
+ const args = { objects, getObjects: getObjects(objects) }
1358
+ setupArgs(args, config, config.logs, hierarchy)
1359
+ initFunction(args)
1360
+ accumulators[property].push({ apply: queryOrExtraConfig })
1361
+ await looper(queries)
1306
1362
  } else {
1307
1363
  // extra config is def from a time like operators or bridges or words etc
1308
1364
  // it will just get added to the config
1309
1365
  const extraConfig = queryOrExtraConfig
1310
1366
  console.log('config', extraConfig)
1311
- try {
1312
- config.addInternal(_.cloneDeep(extraConfig), { handleCalculatedProps: true } )
1313
- } catch ( e ) {
1314
- const where = extraConfig.where ? ` ${extraConfig.where}` : ''
1315
- throw new Error(`Error processing extra config${where}: ${e.stack}}`)
1367
+ if (extraConfig.stop) {
1368
+ await looper([])
1369
+ } else {
1370
+ try {
1371
+ config.addInternal(_.cloneDeep(extraConfig), { handleCalculatedProps: true } )
1372
+ } catch ( e ) {
1373
+ const where = extraConfig.where ? ` ${extraConfig.where}` : ''
1374
+ throw new Error(`Error processing extra config${where}: ${e.stack}}`)
1375
+ }
1376
+ accumulators[property].push({ extraConfig: true, ...extraConfig })
1377
+ await looper(queries)
1316
1378
  }
1317
- accumulators[property].push({ extraConfig: true, ...extraConfig })
1318
- await looper(queries)
1319
1379
  }
1320
1380
  }
1321
1381
 
@@ -1331,8 +1391,11 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1331
1391
  const stabilizeOutput = (template) => {
1332
1392
  stabilizeAssociations(template.associations)
1333
1393
  const stabilize = (results) => {
1334
- for (let result of results) {
1335
- if (result.extraConfig) {
1394
+ for (let i = 0; i < results.length; ++i) {
1395
+ const result = results[i]
1396
+ if (result.apply) {
1397
+ result.apply = result.apply.toString()
1398
+ } else if (result.extraConfig) {
1336
1399
  } else {
1337
1400
  delete result.load_cache_time
1338
1401
  delete result.times
@@ -1370,7 +1433,13 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
1370
1433
  }
1371
1434
  let todo = []
1372
1435
  todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false || query.skipSemantics } }))
1373
- todo = todo.concat((template.queries || []).map((query) => { return { property: 'resultss', query, skipSemantics: false || query.skipSemantics} }))
1436
+ todo = todo.concat((template.queries || []).map((query, index) => {
1437
+ let pr
1438
+ if (index < startOfChanges) {
1439
+ pr = previousResultss[index]
1440
+ }
1441
+ return { property: 'resultss', query, previousResults: pr, skipSemantics: false || query.skipSemantics}
1442
+ }))
1374
1443
  todo = todo.concat((template.fragments || []).map((query) => { return Object.assign({}, toProperties(query), { property: 'fragments', skipSemantics: false }) }))
1375
1444
  todo = todo.concat((template.semantics || []).map((definition) => { return { property: 'semantics', query: `${definition.from}\n${definition.to}`, skipSemantics: true } }))
1376
1445
  await looper(Object.assign([], todo))
@@ -1398,7 +1467,7 @@ const checkTest = (testConfig) => {
1398
1467
  }
1399
1468
  }
1400
1469
 
1401
- const knowledgeModule = async ({
1470
+ const knowledgeModuleImpl = async ({
1402
1471
  module: moduleFromJSFile,
1403
1472
  description,
1404
1473
  section,
@@ -1485,13 +1554,14 @@ const knowledgeModule = async ({
1485
1554
  parser.add_argument('-tnp', '--testNoParenthesized', { action: 'store_true', help: 'Don\' check parenthesized differences for the tests' })
1486
1555
  parser.add_argument('-n', '--count', { help: 'Number of times to run the tests. Default is one. Use this to check for flakey test. If possible the system will print out a message with the word "hint" suggesting how to fix the problem' })
1487
1556
  // parser.add_argument('-b', '--build', { help: 'Specify the template file name of the form <kmName>. There should be a file called <baseKmName>.<kmName>.template.json with the queries to run. For example { queries: [...] }. The template file will be run and generate an instantiation called <baseKmName>.<kmName>.instance.json and a file called <kmName>.js that will load the template file (this is file generated only if not already existing) and a test file called <KmName>.tests.json. This can then be loaded into an instance of the current knowledge module to setup initial conditions.' })
1488
- parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild' })
1557
+ parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild. Using optimization where if the query/config has not changed it will use the previous value. One there is a change all subsequence query/configs will be run.' })
1558
+ parser.add_argument('-rtf', '--rebuildTemplateFull', { action: 'store_true', help: 'Force a template rebuild. Skip the optimization' })
1489
1559
  parser.add_argument('-l', '--loop', { action: 'store_true', help: 'Run a loop so that multiply queries may be run' })
1490
1560
  parser.add_argument('-i', '--info', { action: 'store_true', help: 'Print meta-data for the module' })
1491
1561
  parser.add_argument('-v', '--vimdiff', { action: 'store_true', help: 'For failures run vimdiff' })
1492
1562
  parser.add_argument('-g', '--greg', { action: 'store_true', help: 'Set the server to be localhost so I can debug stuff' })
1493
1563
  parser.add_argument('-cl', '--checkForLoop', { nargs: "?", help: 'Check for loops in the priorities, Optional argument is list of operator keys to consider. For example [["banana", 0], ["food", 1]]' })
1494
- parser.add_argument('-r', '--retrain', { action: 'store_true', help: 'Get the server to retrain the neural nets' })
1564
+ parser.add_argument('-r', '--reset', { action: 'store_true', help: 'Get the server to bypass the cache and rebuild everything' })
1495
1565
  parser.add_argument('-q', '--query', { help: 'Run the specified query' })
1496
1566
  parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
1497
1567
  parser.add_argument('-qp ', '--queryParams', { help: 'Query params for the server call' })
@@ -1516,6 +1586,10 @@ const knowledgeModule = async ({
1516
1586
  const args = parser.parse_args()
1517
1587
  args.count = args.count || 1
1518
1588
 
1589
+ if (args.rebuildTemplateFull) {
1590
+ args.rebuildTemplate = true
1591
+ }
1592
+
1519
1593
  if (args.parenthesized) {
1520
1594
  config.parenthesized = true
1521
1595
  }
@@ -1606,6 +1680,10 @@ const knowledgeModule = async ({
1606
1680
  config.config.debug = true
1607
1681
  }
1608
1682
 
1683
+ if (args.reset) {
1684
+ config.config.skip_cache = true
1685
+ }
1686
+
1609
1687
  if (args.explainPriorities) {
1610
1688
  config.config.explain_priorities = true
1611
1689
  }
@@ -1706,17 +1784,33 @@ const knowledgeModule = async ({
1706
1784
  checkTemplate(template)
1707
1785
 
1708
1786
  if (template) {
1709
- const needsRebuild = config.needsRebuild(template.template, template.instance, options)
1710
- if (needsRebuild) {
1787
+ let needsRebuild
1788
+ if (args.rebuildTemplate && !args.rebuildTemplateFull) {
1789
+ // get the startOfChanges for the partial rebuild
1790
+ needsRebuild = config.needsRebuild(template.template, template.instance, { ...options, rebuild: false })
1791
+ } else {
1792
+ // do a check or full rebuild
1793
+ needsRebuild = config.needsRebuild(template.template, template.instance, options)
1794
+ }
1795
+
1796
+ if (needsRebuild.needsRebuild) {
1797
+ if (needsRebuild.previousResultss) {
1798
+ console.log("Rebuild using the optimization to use previous results until a change is hit. For a full rebuild use -rtf")
1799
+ }
1711
1800
  console.log(`This module "${config.name}" needs rebuilding all other arguments will be ignored. Try again after the template is rebuilt.`)
1712
1801
  options.rebuild = true
1713
1802
  config.config.rebuild = true
1714
1803
  }
1715
- config.load(template.template, template.instance, { rebuild: needsRebuild })
1804
+ try {
1805
+ config.load(template.template, template.instance, { rebuild: needsRebuild.needsRebuild || options.rebuild, previousResultss: needsRebuild.previousResultss, startOfChanges: needsRebuild.startOfChanges })
1806
+ } catch( e ) {
1807
+ console.error(`Error loading template for ${config.name}. ${e.error ? e.error : e}${e.stack ? e.stack : ''}`)
1808
+ runtime.process.exit(-1)
1809
+ }
1716
1810
  if (!args.query) {
1717
1811
  printConfig()
1718
1812
  }
1719
- if (needsRebuild) {
1813
+ if (needsRebuild.needsRebuild) {
1720
1814
  return
1721
1815
  }
1722
1816
  }
@@ -1792,14 +1886,14 @@ const knowledgeModule = async ({
1792
1886
  console.log(` actual ${label} `, actual)
1793
1887
  newError = true
1794
1888
  headerShown = true
1889
+ if (args.vimdiff) {
1890
+ vimdiff(result.actual.paraphrasesParenthesized, result.expected.paraphrasesParenthesized)
1891
+ }
1795
1892
  }
1796
1893
  }
1797
1894
  show('paraphrases', result.expected.paraphrases, result.actual.paraphrases)
1798
1895
  if (!args.testNoParenthesized) {
1799
1896
  show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
1800
- if (args.vimdiff) {
1801
- vimdiff(result.actual.paraphrasesParenthesized, result.expected.paraphrasesParenthesized)
1802
- }
1803
1897
  }
1804
1898
  /*
1805
1899
  }
@@ -1832,10 +1926,10 @@ const knowledgeModule = async ({
1832
1926
  }
1833
1927
  const widths = [4, 18, 72]
1834
1928
  const lines = new Lines(widths)
1835
- lines.setElement(1, 1, 'expected checked')
1929
+ lines.setElement(1, 1, 'expected checked objects')
1836
1930
  lines.setElement(2, 2, JSON.stringify(result.expected.checked, null, 2))
1837
1931
  lines.log()
1838
- lines.setElement(1, 1, 'actual checked')
1932
+ lines.setElement(1, 1, 'actual checked objects')
1839
1933
  lines.setElement(2, 2, JSON.stringify(result.actual.checked, null, 2))
1840
1934
  lines.log()
1841
1935
  if (args.vimdiff) {
@@ -1850,10 +1944,10 @@ const knowledgeModule = async ({
1850
1944
  }
1851
1945
  const widths = [4, 18, 72]
1852
1946
  const lines = new Lines(widths)
1853
- lines.setElement(1, 1, 'expected checkedContexts', true)
1947
+ lines.setElement(1, 1, 'expected checked contexts', true)
1854
1948
  lines.setElement(2, 2, JSON.stringify(result.expected.checkedContexts, null, 2))
1855
1949
  lines.log()
1856
- lines.setElement(1, 1, 'actual checkedContexts', true)
1950
+ lines.setElement(1, 1, 'actual checked contexts', true)
1857
1951
  lines.setElement(2, 2, JSON.stringify(result.actual.checkedContexts, null, 2))
1858
1952
  lines.log()
1859
1953
  if (args.vimdiff) {
@@ -1879,7 +1973,7 @@ const knowledgeModule = async ({
1879
1973
  if (!(useTestConfig.check && useTestConfig.check.length > 0)) {
1880
1974
  console.log('use -v arg to write files expected.json and actual.json in the current directory for detailed comparison. Or do -s and then git diff the changes.')
1881
1975
  // console.log(JSON.stringify(contexts))
1882
- console.log('**************************** ERRORS ************************')
1976
+ console.log('**************************** THERE WERE ERRORS ************************')
1883
1977
  }
1884
1978
  }
1885
1979
  }
@@ -1965,7 +2059,7 @@ const knowledgeModule = async ({
1965
2059
  }
1966
2060
 
1967
2061
  if (template) {
1968
- if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess })) {
2062
+ if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess }).needsRebuild) {
1969
2063
  const error = `This module "${config.name}" cannot be used because the instance file needs rebuilding. Run on the command line with no arguments or the -rt argument to rebuild.`
1970
2064
  throw new Error(error)
1971
2065
  }
@@ -1985,7 +2079,6 @@ const knowledgeModule = async ({
1985
2079
  }
1986
2080
  moduleFromJSFile.exports = createConfigExport
1987
2081
  }
1988
-
1989
2082
  }
1990
2083
 
1991
2084
  /*
@@ -2033,6 +2126,10 @@ function w(func) {
2033
2126
  return func
2034
2127
  }
2035
2128
 
2129
+ const knowledgeModule = async (...args) => {
2130
+ await knowledgeModuleImpl(...args).catch((e) => console.error(e))
2131
+ }
2132
+
2036
2133
  module.exports = {
2037
2134
  process: _process,
2038
2135
  where,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "devDependencies": {
3
3
  "eslint-plugin-import": "^2.23.4",
4
- "jest": "^26.6.3",
4
+ "jest": "^29.7.0",
5
5
  "@typescript-eslint/parser": "^4.28.4",
6
6
  "@typescript-eslint/eslint-plugin": "^4.28.4",
7
7
  "eslint-plugin-node": "^11.1.0",
@@ -12,6 +12,7 @@
12
12
  "scripts": {
13
13
  "to:debug": "node inspect node_modules/.bin/jest --runInBand -t NEO23",
14
14
  "test:debug": "node inspect node_modules/.bin/jest --runInBand --config ./jest.config.json",
15
+ "td": "node inspect node_modules/.bin/jest --runInBand --config ./jest.config.json",
15
16
  "tod": "node inspect node_modules/.bin/jest --runInBand -t NEO23",
16
17
  "lint:fix": "eslint \"**/*.js\" --fix",
17
18
  "lint": "eslint \"**/*.js\"",
@@ -64,6 +65,6 @@
64
65
  "json-stable-stringify": "^1.0.1",
65
66
  "node-fetch": "^2.6.1"
66
67
  },
67
- "version": "7.7.0",
68
+ "version": "7.8.0",
68
69
  "license": "ISC"
69
70
  }
package/src/config.js CHANGED
@@ -27,7 +27,7 @@ const config_toServer = (config) => {
27
27
 
28
28
  const debugPriority = (priority) => {
29
29
  if (global.entodictonDebugPriority) {
30
- if (helpers.safeEquals(entodictonDebugPriority, priority)) {
30
+ if (helpers.subPriority(entodictonDebugPriority, priority)) {
31
31
  debugger; // debug hierarchy hit
32
32
  }
33
33
  }
@@ -965,7 +965,7 @@ class Config {
965
965
  }
966
966
 
967
967
  // { rebuild: false, isModule: false }
968
- needsRebuild(template, instance, options) {
968
+ needsRebuild (template, instance, options) {
969
969
  if (options.rebuild) {
970
970
  return true
971
971
  }
@@ -983,6 +983,18 @@ class Config {
983
983
  if (typeof queryOrConfig == 'string') {
984
984
  const query = queryOrConfig
985
985
  return query
986
+ } else if (typeof queryOrConfig == 'function') {
987
+ if (options.isModule) {
988
+ return { apply: 'function in the browser has webpack rewrites so can not be compared' }
989
+ } else {
990
+ return { apply: queryOrConfig.toString() }
991
+ }
992
+ } else if (queryOrConfig.apply) {
993
+ if (options.isModule) {
994
+ return { apply: 'function in the browser has webpack rewrites so can not be compared' }
995
+ } else {
996
+ return { apply: queryOrConfig.apply }
997
+ }
986
998
  } else {
987
999
  const config = { ...queryOrConfig }
988
1000
  delete config.where
@@ -1058,7 +1070,27 @@ class Config {
1058
1070
  return elements.map( toCanonicalQuery )
1059
1071
  }
1060
1072
 
1061
- const sameQueries = helpers.safeEquals(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), toCanonicalQueries(instance.queries || []))
1073
+ const templateQueries = toCanonicalQueries(template.queries || []).map(helpers.updateQueries)
1074
+ const instanceQueries = toCanonicalQueries(instance.queries || [])
1075
+ let sameQueries = true
1076
+ let startOfChanges;
1077
+ for (let iq = 0; iq < templateQueries.length; ++iq) {
1078
+ if (!helpers.safeEquals(templateQueries[iq], instanceQueries[iq])) {
1079
+ sameQueries = false
1080
+ startOfChanges = iq
1081
+ }
1082
+ }
1083
+
1084
+ if (startOfChanges) {
1085
+ console.log('templateQueries[startOfChanges]', templateQueries[startOfChanges]);
1086
+ console.log('instanceQueries[startOfChanges]', instanceQueries[startOfChanges]);
1087
+ }
1088
+
1089
+ // things were deleted case
1090
+ if (templateQueries.length < instanceQueries.length) {
1091
+ startOfChanges = instanceQueries.length
1092
+ }
1093
+ // const sameQueries = helpers.safeEquals(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), toCanonicalQueries(instance.queries || []))
1062
1094
 
1063
1095
  const debug = false
1064
1096
  if (debug) {
@@ -1067,16 +1099,20 @@ class Config {
1067
1099
  debugger
1068
1100
  debugger
1069
1101
  }
1070
- console.log("instance", instance)
1102
+ // console.log("instance", instance)
1071
1103
  console.log("sameQueries", sameQueries)
1072
1104
  console.log("sameFragments", sameFragments)
1073
- console.log("templateFragments", templateFragments)
1074
- console.log("instanceFragments", instanceFragments)
1075
- console.log('template.queries', JSON.stringify(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), null, 2))
1076
- console.log("instance.queries", JSON.stringify(toCanonicalQueries(instance.queries || []), null, 2))
1105
+ // console.log("templateFragments", templateFragments)
1106
+ // console.log("instanceFragments", instanceFragments)
1107
+ // console.log('template.queries', JSON.stringify(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), null, 2))
1108
+ // console.log("instance.queries", JSON.stringify(toCanonicalQueries(instance.queries || []), null, 2))
1077
1109
  }
1078
1110
  }
1079
- return !(instance && sameQueries && sameFragments)
1111
+ if (startOfChanges || instance.resultss) {
1112
+ return { needsRebuild: !(instance && sameQueries && sameFragments), startOfChanges, previousResultss: instance.resultss }
1113
+ } else {
1114
+ return { needsRebuild: !(instance && sameQueries && sameFragments) }
1115
+ }
1080
1116
  }
1081
1117
 
1082
1118
  validifyTemplate (template) {
@@ -1097,7 +1133,7 @@ class Config {
1097
1133
  }
1098
1134
 
1099
1135
  // loadTemplate
1100
- load (template, instance, options = { rebuild: false } ) {
1136
+ load (template, instance, options = { rebuild: false, previousResultss: undefined, startOfChanges: undefined } ) {
1101
1137
  this.validifyTemplate(template)
1102
1138
  instance.template = template
1103
1139
  this.logs.push(`loading template for ${this.name}`)
@@ -1105,7 +1141,7 @@ class Config {
1105
1141
  // TODO fix beforeQuery
1106
1142
  template = { fragments: [], queries: [], ...template }
1107
1143
  template.fragments = template.fragments.concat(this.dynamicFragments)
1108
- client.rebuildTemplate({ config: this, target: this.name, beforeQuery: () => {}, template, ...options })
1144
+ client.rebuildTemplate({ config: this, target: this.name, previousResultss: options.previousResultss, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options })
1109
1145
  } else {
1110
1146
  // no change
1111
1147
  // this.initInstances.push({ ...instance, name: config.name })
@@ -1120,6 +1156,13 @@ class Config {
1120
1156
  return !properties.find( (property) => instance[property] && instance[property].length > 0 )
1121
1157
  }
1122
1158
  if (!isEmpty(instance)) {
1159
+ // fix up apply functions
1160
+ for (let i = 0; i < instance.resultss.length; ++i) {
1161
+ const result = instance.resultss[i]
1162
+ if (result.apply) {
1163
+ result.apply = template.queries[i]
1164
+ }
1165
+ }
1123
1166
  instance.name = this.name
1124
1167
  this.initInstances.push(instance)
1125
1168
  this.instances.push(instance)
@@ -2219,8 +2262,6 @@ class Config {
2219
2262
  const addInternals = []
2220
2263
  const inits = []
2221
2264
  const initAfterApis = []
2222
- const reverseIt = true
2223
- const interleaved = true
2224
2265
  this.configs.forEach((km) => {
2225
2266
  const namespace = km.namespace
2226
2267
  this.config.objects.namespaced[km._uuid] = {}
@@ -2286,58 +2327,30 @@ class Config {
2286
2327
  inits.unshift( () => config._api.initialize({ config: this, km: kmFn, ...args, api: config._api }) )
2287
2328
  // config._api.initialize({ config, api: config._api })
2288
2329
  } else {
2289
- if (interleaved) {
2290
- inits.unshift(null)
2291
- }
2330
+ inits.unshift(null)
2292
2331
  }
2293
2332
  // config._api.objects = namespacedObjects
2294
2333
  // config._api.config = () => this
2295
2334
  // config._api.uuid = config._uuid
2296
2335
  } else {
2297
- if (interleaved) {
2298
- inits.unshift(null)
2299
- }
2336
+ inits.unshift(null)
2300
2337
  }
2301
2338
  config.setUUIDs()
2302
2339
  config.applyNamespace(config.config, namespace, config.uuid)
2303
2340
  if (!isSelf) {
2304
- if (!reverseIt) {
2305
- addInternals.push(config)
2306
- } else {
2307
- addInternals.unshift(config)
2308
- }
2341
+ addInternals.unshift(config)
2309
2342
  } else {
2310
- if (interleaved) {
2311
- addInternals.unshift(null)
2312
- }
2343
+ addInternals.unshift(null)
2313
2344
  }
2314
2345
  km.valid()
2315
2346
  })
2316
2347
 
2317
2348
  const generators = this.config.generators
2318
2349
  const semantics = this.config.semantics
2319
- if (reverseIt) {
2320
- this.config.generators = []
2321
- this.config.semantics = []
2322
- }
2350
+ this.config.generators = []
2351
+ this.config.semantics = []
2323
2352
 
2324
- if (!interleaved) {
2325
- for (const config of addInternals) {
2326
- if (!reverseIt) {
2327
- this.addInternal(config, { includeNamespace: false, allowNameToBeNull: true })
2328
- } else {
2329
- this.addInternalR(config, true, false, false, true)
2330
- }
2331
- }
2332
- // console.log('inits from config', inits)
2333
- for (const init of inits) {
2334
- init()
2335
- }
2336
- for (let init of initAfterApis) {
2337
- init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
2338
- }
2339
- this.instances.forEach((instance) => client.loadInstance(this, instance))
2340
- } else {
2353
+ {
2341
2354
  const base = {
2342
2355
  operators: this.config.operators,
2343
2356
  bridges: this.config.bridges,
@@ -2353,13 +2366,16 @@ class Config {
2353
2366
  this.config.priorities = []
2354
2367
  this.config.associations = { positive: [], negative: [] }
2355
2368
  this.config.words = {}
2356
-
2369
+
2357
2370
  for (let i = 0; i < addInternals.length; ++i) {
2358
2371
  let name;
2359
2372
  if (addInternals[i]) {
2360
2373
  this.addInternalR(addInternals[i], true, false, false, true)
2361
2374
  name = addInternals[i].name
2362
2375
  } else{
2376
+ // the ones defined in config must come after the ones in the templates
2377
+ this.config.generators = generators.concat(this.config.generators)
2378
+ this.config.semantics = semantics.concat(this.config.semantics)
2363
2379
  this.addInternalR(base, true, false, false, true)
2364
2380
  name = this.name
2365
2381
  }
@@ -2380,10 +2396,6 @@ class Config {
2380
2396
  }
2381
2397
  }
2382
2398
 
2383
- if (reverseIt) {
2384
- this.config.generators = generators.concat(this.config.generators)
2385
- this.config.semantics = semantics.concat(this.config.semantics)
2386
- }
2387
2399
  this.hierarchy.edges = this.config.hierarchy
2388
2400
  this.valid()
2389
2401
  this.checkBridges()
package/src/generators.js CHANGED
@@ -169,7 +169,7 @@ class Generators {
169
169
  // assumed - properties added to context before the generators are called. For setting paraphrase property
170
170
  apply (args, context, assumed = {}, options = {}) {
171
171
  if (Array.isArray(context)) {
172
- return new Error("Expected a context not an array")
172
+ throw new Error("Expected a context not an array")
173
173
  }
174
174
  if (typeof context !== 'object') {
175
175
  return String(context)
@@ -179,7 +179,6 @@ class Generators {
179
179
  const objects = args.objects
180
180
  const hierarchy = args.hierarchy
181
181
  const response = args.response
182
-
183
182
 
184
183
  // args = { ...args, ...args.getAssumedScoped(assumed) }
185
184
  args.addAssumedScoped(args, assumed)
package/src/helpers.js CHANGED
@@ -272,6 +272,8 @@ const mapInPlace = (list, fn) => {
272
272
  const updateQueries = (queryOrConfig) => {
273
273
  if (typeof queryOrConfig == 'string' || queryOrConfig.query) {
274
274
  return queryOrConfig
275
+ } else if (typeof queryOrConfig == 'function') {
276
+ return { apply: queryOrConfig.toString() }
275
277
  } else {
276
278
  const config = queryOrConfig
277
279
  return functionsToStrings(config)
@@ -334,6 +336,45 @@ const ecatch = (where, call) => {
334
336
  }
335
337
  }
336
338
 
339
+ const equalKey = (key1, key2) => {
340
+ return key1[0] == key2[0] && key1[1] == key2[1]
341
+ }
342
+
343
+ // matches for { context: ..., [ordered], choose: ... } exactely OR
344
+ // [ <id1>, <id2> ] - where id1 is chosen
345
+ const subPriority = (sub, sup) => {
346
+ if (Array.isArray(sub)) {
347
+ const subChoosen = sub[0]
348
+ const subOther = sub[1]
349
+ const hasChoosen = sup.choose.find( (index) => equalKey(sup.context[index], subChoosen)) != undefined
350
+ const hasOtherChosen = sup.choose.find( (index) => equalKey(sup.context[index], subOther)) != undefined
351
+ const hasOther = sup.context.find( (other) => equalKey(other, subOther) ) !== undefined
352
+ return !!(hasChoosen && hasOther) && !hasOtherChosen
353
+ }
354
+
355
+ if (!safeEquals([...sub.choose].sort(), [...sup.choose].sort())) {
356
+ return false
357
+ }
358
+
359
+ const choose = (priority) => {
360
+ const chosen = []
361
+ for (const i of priority.choose) {
362
+ chosen.push(priority.context[i])
363
+ }
364
+ return chosen
365
+ }
366
+ const chosen1 = choose(sub)
367
+ const chosen2 = choose(sup)
368
+ const sameId = (id1, id2) => id1[0] == id2[0] && id1[1] == id2[1]
369
+ // same length so only need one way
370
+ const missing1 = chosen1.find( (id1) => !chosen2.find( (id2) => sameId(id1, id2)) )
371
+ if (missing1) {
372
+ return false
373
+ }
374
+
375
+ return true
376
+ }
377
+
337
378
  module.exports = {
338
379
  ecatch,
339
380
  functionsToStrings,
@@ -354,5 +395,6 @@ module.exports = {
354
395
  isCompound,
355
396
  InitCalls,
356
397
  hashCode,
357
- sortJson
398
+ sortJson,
399
+ subPriority,
358
400
  }
package/src/project.js CHANGED
@@ -16,6 +16,9 @@ const project = (object, filter) => {
16
16
  return object.map( element => project(element, filter) )
17
17
  } else {
18
18
  for (let properties of filter) {
19
+ if (typeof properties == 'function') {
20
+ properties = properties(object)
21
+ }
19
22
  if (typeof properties == 'object') {
20
23
  if (properties.propertyLists) {
21
24
  for (const propertyList in properties.propertyLists) {