theprogrammablemind 7.5.0-beta.4 → 7.5.0-beta.41

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/client.js CHANGED
@@ -78,7 +78,15 @@ const listable = (hierarchy) => (c, type) => {
78
78
  return false
79
79
  }
80
80
 
81
- const isA = (hierarchy) => (child, parent) => hierarchy.isA(child, parent)
81
+ const isA = (hierarchy) => (child, parent) => {
82
+ if (child.marker) {
83
+ child = child.marker
84
+ }
85
+ if (parent.marker) {
86
+ parent = parent.marker
87
+ }
88
+ return hierarchy.isA(child, parent)
89
+ }
82
90
 
83
91
  const asList = (context) => {
84
92
  if (context.marker === 'list') {
@@ -670,9 +678,12 @@ const runTest = async (config, expected, { verbose, afterTest, testConfig, debug
670
678
  defaultErrorHandler(error)
671
679
  }
672
680
 
673
- const objects = getObjects(config.config.objects)(config.uuid)
681
+ let objects = getObjects(config.config.objects)(config.uuid)
682
+ if (testConfig.testModuleName) {
683
+ objects = getObjects(config.config.objects)(config.getConfigs()[testConfig.testModuleName].uuid)
684
+ }
674
685
  config.beforeQuery({ query: test, isModule: false, objects })
675
- config.resetMotivations()
686
+ // config.resetMotivations()
676
687
  try {
677
688
  const result = await _process(config, test, { errorHandler, isTest: true })
678
689
  result.query = test
@@ -783,7 +794,7 @@ const runTests = async (config, testFile, juicyBits) => {
783
794
  const saveTest = async (testFile, config, test, expected, testConfig, saveDeveloper) => {
784
795
  config.rebuild()
785
796
  const objects = getObjects(config.config.objects)(config.uuid)
786
- config.resetMotivations()
797
+ //config.resetMotivations()
787
798
  config.beforeQuery({ query: test, isModule: false, objects })
788
799
  console.log(test)
789
800
  const result = await _process(config, test, { isTest: true })
@@ -1252,7 +1263,7 @@ const knowledgeModule = async ({
1252
1263
  description: 'Entodicton knowledge module'
1253
1264
  })
1254
1265
 
1255
- parser.add_argument('-tfn', '--testFileName', { help: 'Override the test file for the module when the tests are being run' })
1266
+ parser.add_argument('-tmn', '--testModuleName', { help: 'When running tests instead of using the current modules tests use the specified modules tests' })
1256
1267
  parser.add_argument('-t', '--test', { action: 'store_true', help: 'Run the tests. Create tests by running with the --query + --save flag' })
1257
1268
  parser.add_argument('-tv', '--testVerbose', { action: 'store_true', help: 'Run the tests in verbose mode. Create tests by running with the --query or --loop with the --save flag' })
1258
1269
  parser.add_argument('-tva', '--testAllVerbose', { action: 'store_true', help: 'Run the tests in verbose mode. All the tests will be run instead of stopping at first failure. Create tests by running with the --query or --loop with the --save flag' })
@@ -1267,7 +1278,7 @@ const knowledgeModule = async ({
1267
1278
  parser.add_argument('-q', '--query', { help: 'Run the specified query' })
1268
1279
  parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
1269
1280
  parser.add_argument('-qp ', '--queryParams', { help: 'Query params for the server call' })
1270
- parser.add_argument('-td', '--testDelete', { help: 'Delete the specified query from the tests file.' })
1281
+ parser.add_argument('-dt', '--deleteTest', { help: 'Delete the specified query from the tests file.' })
1271
1282
  parser.add_argument('-c', '--clean', { help: 'Remove data from the test files. a === association' })
1272
1283
  parser.add_argument('-od', '--objectDiff', { action: 'store_true', help: 'When showing the objects use a colour diff' })
1273
1284
  parser.add_argument('-daa', '--dontAddAssociations', { action: 'store_true', help: 'Do not add associations from the tests.' })
@@ -1306,11 +1317,11 @@ const knowledgeModule = async ({
1306
1317
  return
1307
1318
  }
1308
1319
 
1309
- if (args.testDelete) {
1320
+ if (args.deleteTest) {
1310
1321
  let tests = JSON.parse(runtime.fs.readFileSync(testConfig.name))
1311
- tests = tests.filter( (test) => test.query !== args.testDelete );
1322
+ tests = tests.filter( (test) => test.query !== args.deleteTest );
1312
1323
  writeTestFile(testConfig.name, tests)
1313
- console.log(`Remove the test for "${args.testDelete}"`)
1324
+ console.log(`Remove the test for "${args.deleteTest}"`)
1314
1325
  return
1315
1326
  }
1316
1327
 
@@ -1466,7 +1477,15 @@ const knowledgeModule = async ({
1466
1477
  }
1467
1478
  return
1468
1479
  }
1469
- runTests(config, args.testFileName ? `${args.testFileName}.test.json` : test, { debug: args.debug, testConfig: testConfig, verbose: args.testVerbose || args.testAllVerbose, stopAtFirstError: !args.testAllVerbose }).then((results) => {
1480
+ let useTestConfig = testConfig
1481
+ if (args.testModuleName) {
1482
+ useTestConfig = config.getConfigs()[args.testModuleName].getTestConfig()
1483
+ useTestConfig.testModuleName = args.testModuleName
1484
+ test = useTestConfig.name
1485
+
1486
+ }
1487
+ // runTests(config, args.testFileName ? `${args.testFileName}.test.json` : test, { debug: args.debug, testConfig: testConfig, verbose: args.testVerbose || args.testAllVerbose, stopAtFirstError: !args.testAllVerbose }).then((results) => {
1488
+ runTests(config, test, { debug: args.debug, testConfig: useTestConfig, verbose: args.testVerbose || args.testAllVerbose, stopAtFirstError: !args.testAllVerbose }).then((results) => {
1470
1489
  if (results.length > 0 && args.vimdiff) {
1471
1490
  for (const result of results) {
1472
1491
  vimdiff(result.expected, result.actual)
@@ -1515,19 +1534,25 @@ const knowledgeModule = async ({
1515
1534
  if (!headerShown) {
1516
1535
  console.log(' Failure')
1517
1536
  }
1518
- console.log(' expected checked', result.expected.checked)
1519
- console.log(' actual checked ', result.actual.checked)
1537
+ const widths = [4, 18, 72]
1538
+ const lines = new Lines(widths)
1539
+ lines.setElement(1, 1, 'expected checked')
1540
+ lines.setElement(2, 2, JSON.stringify(result.expected.checked, null, 2))
1541
+ lines.log()
1542
+ lines.setElement(1, 1, 'actual checked')
1543
+ lines.setElement(2, 2, JSON.stringify(result.actual.checked, null, 2))
1544
+ lines.log()
1520
1545
  newError = true
1521
1546
  headerShown = true
1522
1547
  }
1523
1548
  }
1524
1549
  }
1525
1550
  if (!headerShown) {
1526
- if (!(testConfig.check && testConfig.check.length > 0)) {
1551
+ if (!(useTestConfig.check && useTestConfig.check.length > 0)) {
1527
1552
  console.log('There are failures due to things other than paraphrases, responses and checked properties being different. They are not shown because you ran -tv or -tva which only shows difference in paraphrase and results. Usually what I do is -s and do a diff to make sure there are no other problems. If the paraphrases or results were different they would have shown here.')
1528
1553
  }
1529
1554
  }
1530
- if (!(testConfig.check && testConfig.check.length > 0)) {
1555
+ if (!(useTestConfig.check && useTestConfig.check.length > 0)) {
1531
1556
  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.')
1532
1557
  // console.log(JSON.stringify(contexts))
1533
1558
  console.log('**************************** ERRORS ************************')
@@ -1589,6 +1614,7 @@ const knowledgeModule = async ({
1589
1614
  }
1590
1615
  } else {
1591
1616
  config.addAssociationsFromTests(config.tests);
1617
+ config.setTestConfig(testConfig)
1592
1618
  //for (let query in config.tests) {
1593
1619
  // config.addAssociations(config.tests[query].associations || []);
1594
1620
  //}
package/lines.js CHANGED
@@ -12,6 +12,9 @@ class Lines {
12
12
  // will wrap to next line within the column
13
13
  setElement (row, column, value) {
14
14
  const values = value.toString().split('\n')
15
+ if (column >= this.widths.length) {
16
+ throw "Column out of range."
17
+ }
15
18
  const width = this.widths[column]
16
19
  let index = 0
17
20
  for (value of values) {
package/package.json CHANGED
@@ -61,6 +61,6 @@
61
61
  "json-stable-stringify": "^1.0.1",
62
62
  "node-fetch": "^2.6.1"
63
63
  },
64
- "version": "7.5.0-beta.4",
64
+ "version": "7.5.0-beta.41",
65
65
  "license": "ISC"
66
66
  }
package/src/config.js CHANGED
@@ -330,6 +330,17 @@ class Config {
330
330
  return `${maybeName}${counter}`
331
331
  }
332
332
 
333
+ setTestConfig(testConfig) {
334
+ if (this.name == 'ui') {
335
+ console.log('ui setting testConfig')
336
+ }
337
+ this.testConfig = testConfig
338
+ }
339
+
340
+ getTestConfig() {
341
+ return this.testConfig
342
+ }
343
+
333
344
  defaultConfig () {
334
345
  this.config = {
335
346
  operators: [], // TODO
@@ -531,9 +542,23 @@ class Config {
531
542
  client.build({ config: this, target: this.name, beforeQuery: () => {}, template, ...options })
532
543
  } else {
533
544
  // no change
534
- this.initInstances.push(instance)
535
- this.instances.push(instance)
536
- client.processInstance(this, instance)
545
+ // this.initInstances.push({ ...instance, name: config.name })
546
+ const isEmpty = ( instance ) => {
547
+ const properties = [
548
+ "queries",
549
+ "resultss",
550
+ "fragments",
551
+ "semantics",
552
+ "associations",
553
+ ]
554
+ return !properties.find( (property) => instance[property].length > 0 )
555
+ }
556
+ if (!isEmpty(instance)) {
557
+ instance.name = this.name
558
+ this.initInstances.push(instance)
559
+ this.instances.push(instance)
560
+ client.processInstance(this, instance)
561
+ }
537
562
  }
538
563
  }
539
564
 
@@ -1090,7 +1115,7 @@ class Config {
1090
1115
  config = _.cloneDeep(config)
1091
1116
  this.config = config
1092
1117
  for (let bridge of this.config.bridges) {
1093
- const valid = [ 'before', 'bridge', 'development', 'evaluator', 'generatorp', 'generatorr', 'generators', 'id', 'inverted', 'isA',
1118
+ const valid = [ 'before', 'bridge', 'development', 'evaluator', 'generatorp', 'generatorr', 'generators', 'id', 'implicit', 'inverted', 'isA', 'children', 'parents',
1094
1119
  'level', 'optional', 'selector', 'semantic', 'words', /Bridge$/, 'localHierarchy' ]
1095
1120
  helpers.validProps(valid, bridge, 'bridge')
1096
1121
  /*
@@ -1101,6 +1126,16 @@ class Config {
1101
1126
  })
1102
1127
  }
1103
1128
  */
1129
+ if (bridge.children) {
1130
+ for (let child of bridge.children) {
1131
+ this.addHierarchy(child, bridge.id)
1132
+ }
1133
+ }
1134
+ if (bridge.parents) {
1135
+ for (let parent of bridge.parents) {
1136
+ this.addHierarchy(bridge.id, parent)
1137
+ }
1138
+ }
1104
1139
  if (bridge.isA) {
1105
1140
  for (let parent of bridge.isA) {
1106
1141
  this.addHierarchy(bridge.id, parent)
@@ -1379,12 +1414,13 @@ class Config {
1379
1414
  cp.name = this.name
1380
1415
  cp.description = this.description
1381
1416
  cp.tests = this.tests
1382
- cp.motivations = this.motivations
1417
+ cp.motivations = [...this.motivations]
1383
1418
  cp.isModule = this.isModule
1384
1419
  cp.loadedForTesting = this.loadedForTesting
1385
1420
  cp.initInstances = this.initInstances.slice()
1386
1421
  cp.instances = this.instances.slice()
1387
1422
  cp.configCounter = this.configCounter
1423
+ cp.testConfig = this.testConfig
1388
1424
 
1389
1425
  cp.initConfig = _.cloneDeep(this.initConfig)
1390
1426
  cp.defaultConfig()
@@ -1511,7 +1547,8 @@ class Config {
1511
1547
  }
1512
1548
 
1513
1549
  initializeFromConfigs () {
1514
- this.configs.forEach(({ config, namespace, uuid }) => {
1550
+ // [...this.configs].reverse().forEach(({ config, namespace, uuid }) => {
1551
+ [...this.configs].reverse().forEach(({ config, namespace, uuid }) => {
1515
1552
  /*
1516
1553
  let objects = this.get('objects')
1517
1554
  if (namespace) {
@@ -1747,6 +1784,7 @@ class Config {
1747
1784
  }
1748
1785
  this.config.objects.namespaced = {}
1749
1786
  this.resetWasInitialized()
1787
+ this.resetMotivations()
1750
1788
 
1751
1789
  // reorder configs base on load ordering
1752
1790
  {
@@ -1762,8 +1800,17 @@ class Config {
1762
1800
  this.configs = [...oconfigs]
1763
1801
  }
1764
1802
 
1803
+ const addInternals = []
1765
1804
  const inits = []
1766
1805
  const initAfterApis = []
1806
+ if (false && this.config.hierarchy.find( (pair) => JSON.stringify(pair) === JSON.stringify(["equipable2","property"]))) {
1807
+ debugger // happened
1808
+ }
1809
+ if (false && this.name == 'countable') {
1810
+ debugger // in rebuild
1811
+ }
1812
+ const reverseIt = true
1813
+ const interleaved = true
1767
1814
  this.configs.forEach((km) => {
1768
1815
  const namespace = km.namespace
1769
1816
  this.config.objects.namespaced[km._uuid] = {}
@@ -1796,7 +1843,12 @@ class Config {
1796
1843
  const args = { isModule, addWord: aw, km: kmFn, hierarchy: this.hierarchy, config, baseConfig: this, currentConfig: config, uuid: config._uuid, objects: namespacedObjects, namespace, api: config.api }
1797
1844
  config.initializerFn(args)
1798
1845
  if (config.initAfterApi) {
1799
- initAfterApis.push({ config, args })
1846
+ // reverse the list
1847
+ initAfterApis.unshift({ config, args })
1848
+ } else {
1849
+ if (interleaved) {
1850
+ initAfterApis.unshift(null)
1851
+ }
1800
1852
  }
1801
1853
  // greg
1802
1854
  if (config._api) {
@@ -1804,27 +1856,112 @@ class Config {
1804
1856
  // reverse the list
1805
1857
  inits.unshift( () => config._api.initialize({ config: this, km: kmFn, api: config._api }) )
1806
1858
  // config._api.initialize({ config, api: config._api })
1859
+ } else {
1860
+ if (interleaved) {
1861
+ inits.unshift(null)
1862
+ }
1807
1863
  }
1808
1864
  config._api.objects = namespacedObjects
1809
1865
  config._api.config = () => this
1810
1866
  config._api.uuid = config._uuid
1867
+ } else {
1868
+ if (interleaved) {
1869
+ inits.unshift(null)
1870
+ }
1811
1871
  }
1812
1872
  config.setUUIDs()
1813
1873
  config.applyNamespace(config.config, namespace, config.uuid)
1814
1874
  if (!isSelf) {
1815
- this.addInternal(config, true, false, false, true)
1875
+ if (!reverseIt) {
1876
+ addInternals.push(config)
1877
+ } else {
1878
+ addInternals.unshift(config)
1879
+ }
1880
+ // this.addInternal(config, true, false, false, true)
1881
+ } else {
1882
+ if (interleaved) {
1883
+ addInternals.unshift(null)
1884
+ }
1816
1885
  }
1817
1886
  km.valid()
1818
1887
  })
1819
- // console.log('inits from config', inits)
1820
- for (const init of inits) {
1821
- init()
1888
+
1889
+ if (addInternals.length !== inits.length || addInternals.length !== initAfterApis.length) {
1890
+ debugger // bug
1822
1891
  }
1823
- for (let init of initAfterApis) {
1824
- // init.args.isAfterApi = true
1825
- init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
1892
+
1893
+ const generators = this.config.generators
1894
+ const semantics = this.config.semantics
1895
+ if (reverseIt) {
1896
+ this.config.generators = []
1897
+ this.config.semantics = []
1826
1898
  }
1827
- this.instances.forEach((instance) => client.processInstance(this, instance))
1899
+
1900
+ if (!interleaved) {
1901
+ for (const config of addInternals) {
1902
+ if (!reverseIt) {
1903
+ this.addInternal(config, true, false, false, true)
1904
+ } else {
1905
+ this.addInternalR(config, true, false, false, true)
1906
+ }
1907
+ }
1908
+ // console.log('inits from config', inits)
1909
+ for (const init of inits) {
1910
+ init()
1911
+ }
1912
+ for (let init of initAfterApis) {
1913
+ // init.args.isAfterApi = true
1914
+ init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
1915
+ }
1916
+ this.instances.forEach((instance) => client.processInstance(this, instance))
1917
+ } else {
1918
+ const base = {
1919
+ operators: this.config.operators,
1920
+ bridges: this.config.bridges,
1921
+ hierarchy: this.config.hierarchy,
1922
+ priorities: this.config.priorities,
1923
+ associations: this.config.associations,
1924
+ words: this.config.words
1925
+ }
1926
+
1927
+ this.config.operators = []
1928
+ this.config.bridges = []
1929
+ this.config.hierarchy = []
1930
+ this.config.priorities = []
1931
+ this.config.associations = { positive: [], negative: [] }
1932
+ this.config.words = {}
1933
+
1934
+ for (let i = 0; i < addInternals.length; ++i) {
1935
+ let name;
1936
+ if (addInternals[i]) {
1937
+ this.addInternalR(addInternals[i], true, false, false, true)
1938
+ name = addInternals[i].name
1939
+ } else{
1940
+ this.addInternalR(base, true, false, false, true)
1941
+ name = this.name
1942
+ }
1943
+ // console.log('name -------------', name)
1944
+ if (inits[i]) {
1945
+ inits[i]()
1946
+ }
1947
+ if (initAfterApis[i]) {
1948
+ const init = initAfterApis[i]
1949
+ init.config.initializerFn({ ...init.args, kms: this.getConfigs(), isAfterApi: true })
1950
+ }
1951
+ const instance = this.instances.find((instance) => instance.name == name)
1952
+ if (instance) {
1953
+ client.processInstance(this, instance)
1954
+ }
1955
+ this.hierarchy.edges = this.config.hierarchy
1956
+ }
1957
+ // this.instances.forEach((instance) => client.processInstance(this, instance))
1958
+ }
1959
+
1960
+ if (reverseIt) {
1961
+ this.config.generators = generators.concat(this.config.generators)
1962
+ this.config.semantics = semantics.concat(this.config.semantics)
1963
+ }
1964
+ this.hierarchy.edges = this.config.hierarchy
1828
1965
  this.valid()
1829
1966
  this.checkBridges()
1830
1967
  }
@@ -2191,6 +2328,13 @@ class Config {
2191
2328
  this.configs.forEach((km) => {
2192
2329
  this.instances = (km._config.instances || this.initInstances.slice()).concat(this.instances)
2193
2330
  })
2331
+ let noDups = []
2332
+ for (let instance of this.instances) {
2333
+ if (!noDups.find( (existing) => existing.name == instance.name )) {
2334
+ noDups.push(instance)
2335
+ }
2336
+ }
2337
+ this.instances = noDups
2194
2338
 
2195
2339
  this.rebuild()
2196
2340
  this.valid()
@@ -2308,6 +2452,128 @@ class Config {
2308
2452
  }
2309
2453
  return this
2310
2454
  }
2455
+
2456
+ // assumes this is called in reverse order
2457
+ addInternalR (more, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false) {
2458
+ if (more instanceof Config) {
2459
+ more.initialize({ force: false })
2460
+ if (useOldVersion) {
2461
+ more = more.config
2462
+ } else {
2463
+ // more = more.initConfig
2464
+ more = _.cloneDeep(more.initConfig)
2465
+ }
2466
+ }
2467
+ for (const key of Object.keys(more)) {
2468
+ const value = more[key]
2469
+ // TODO remove name and description on the config bag
2470
+ const noOverwrite = ['name', 'namespaced']
2471
+ if (!this.config[key]) {
2472
+ if (allowNameToBeNull) {
2473
+ if (noOverwrite.includes(key)) {
2474
+ continue
2475
+ }
2476
+ } else if (this.config[key] && noOverwrite.includes(key)) {
2477
+ continue
2478
+ }
2479
+ this.config[key] = value
2480
+ continue
2481
+ }
2482
+ if (key === 'words') {
2483
+ const configWords = this.config.words
2484
+ const moreWords = more.words
2485
+ for (const word of Object.keys(moreWords)) {
2486
+ if (!configWords[word]) {
2487
+ configWords[word] = []
2488
+ }
2489
+ // configWords[word] = configWords[word].concat(moreWords[word])
2490
+ configWords[word] = moreWords[word].concat(configWords[word])
2491
+ }
2492
+ } else if (key === 'name') {
2493
+ /*
2494
+ if (this.config[key] === '') {
2495
+ this.config[key] = more[key]
2496
+ }
2497
+ */
2498
+ } else if (key === 'namespaces') {
2499
+ if (includeNamespaces) {
2500
+ Object.assign(this.config[key], more[key])
2501
+ }
2502
+ } else if (key === 'debug') {
2503
+ this.config[key] = this.config[key] || more[key]
2504
+ } else if (key === 'description') {
2505
+ // this.config[key] += ' ' + more[key].trim()
2506
+ this.config[key] = more[key].trim() + ' ' + this.config[key]
2507
+ } else if (key === 'objects') {
2508
+ if (!skipObjects) {
2509
+ // namespaced is special
2510
+ const namespaced = this.config.objects.namespaced
2511
+ Object.assign(this.config[key], more[key])
2512
+ this.config.objects.namespaced = namespaced
2513
+ }
2514
+ } else if (key === 'associations') {
2515
+ const configAssociations = this.config.associations
2516
+ const moreAssociations = more.associations
2517
+ if (moreAssociations.positive) {
2518
+ // configAssociations.positive = configAssociations.positive.concat(moreAssociations.positive)
2519
+ configAssociations.positive = moreAssociations.positive.concat(configAssociations.positive)
2520
+ }
2521
+ if (moreAssociations.negative) {
2522
+ // configAssociations.negative = configAssociations.negative.concat(moreAssociations.negative)
2523
+ configAssociations.negative = moreAssociations.negative.concat(configAssociations.negative)
2524
+ }
2525
+ } else if (Array.isArray(value)) {
2526
+ // handle allowDups
2527
+ if (key == 'operators') {
2528
+ // TODO what about other props
2529
+ const isDup = (op1, op2) => op1.pattern == op2.pattern
2530
+ for (const newOne of more[key]) {
2531
+ for (let iOldOne = 0; iOldOne < this.config[key].length; ++iOldOne) {
2532
+ const oldOne = this.config[key][iOldOne];
2533
+ if (isDup(newOne, oldOne)) {
2534
+ if (oldOne.allowDups) {
2535
+ // the old one takes precedence to match what would happen during the original load
2536
+ debugger
2537
+ this.config[key].splice(iOldOne, 1)
2538
+ break;
2539
+ }
2540
+ }
2541
+ }
2542
+ }
2543
+ }
2544
+ if (key == 'bridges') {
2545
+ // TODO what about other props
2546
+ const idDup = (b1, b2) => b1.id == b2.id && b1.level == b2.level && b1.bridge == b2.bridge
2547
+ for (const newOne of more[key]) {
2548
+ for (let iOldOne = 0; iOldOne < this.config[key].length; ++iOldOne) {
2549
+ const oldOne = this.config[key][iOldOne];
2550
+ if (newOne.id == oldOne.id) {
2551
+ if (oldOne.allowDups) {
2552
+ // the old one takes precedence to match what would happen during the original load
2553
+ this.config[key].splice(iOldOne, 1)
2554
+ break;
2555
+ }
2556
+ }
2557
+ }
2558
+ }
2559
+ }
2560
+ // console.log('key', key, 'XXX')
2561
+ // console.log('more', JSON.stringify(more, null, 2))
2562
+ // this.config[key] = this.config[key].concat(more[key])
2563
+ if (key == '2enerators') {
2564
+ debugger
2565
+ }
2566
+ // this.config[key] = this.config[key].concat(more[key])
2567
+ this.config[key] = more[key].concat(this.config[key])
2568
+ } else {
2569
+ if (!(key in this.config)) {
2570
+ throw `Unexpected property in config ${key}`
2571
+ }
2572
+ this.config[key] = more[key]
2573
+ }
2574
+ }
2575
+ return this
2576
+ }
2311
2577
  }
2312
2578
 
2313
2579
  module.exports = {
package/src/digraph.js CHANGED
@@ -28,6 +28,10 @@ class Digraph {
28
28
  return this._edges
29
29
  }
30
30
 
31
+ set edges(edges) {
32
+ this._edges = edges
33
+ }
34
+
31
35
  /*
32
36
  set edges(edges) {
33
37
  this._edges = edges.map( toA )
package/src/generators.js CHANGED
@@ -195,10 +195,12 @@ class Generators {
195
195
  } catch( e ) {
196
196
  // the next if handle this
197
197
  generated = null
198
+ e.retryCall = () => generator.apply(args, objects, g, args.gs, context, hierarchy, config, response, log)
199
+ const help = 'The error has a retryCall property that will recall the function that failed.'
198
200
  if (e.stack && e.message) {
199
- errorMessage = `Error applying generator '${generator.notes}'. Error is ${e.toString()} stack is ${e.stack}. Generator is ${generator.toString()}`
201
+ errorMessage = `Error applying generator '${generator.notes}'. Error is ${e.toString()} stack is ${e.stack}. Generator is ${generator.toString()}. ${help}`
200
202
  } else if (e.error) {
201
- errorMessage = `Error applying generator '${generator.notes}'. Error is ${e.error.join()}. Generator is ${generator.toString()}`
203
+ errorMessage = `Error applying generator '${generator.notes}'. Error is ${e.error.join()}. Generator is ${generator.toString()}. ${help}`
202
204
  } else {
203
205
  errorMessage = e.toString()
204
206
  }
package/src/helpers.js CHANGED
@@ -227,7 +227,7 @@ const validProps = (valids, object, type) => {
227
227
  }
228
228
  }
229
229
  if (!okay) {
230
- throw `Unknown property "${prop}" in the ${type}. Valid properties are ${valid}. The ${type} is ${JSON.stringify(object)}`
230
+ throw `Unknown property "${prop}" in the ${type}. Valid properties are ${valids}. The ${type} is ${JSON.stringify(object)}`
231
231
  }
232
232
  }
233
233
  }
package/src/semantics.js CHANGED
@@ -189,10 +189,12 @@ class Semantics {
189
189
  } catch( e ) {
190
190
  contextPrime = null
191
191
  let errorMessage
192
+ e.retryCall = () => semantic.apply(args, context, s, log, options)
193
+ const help = 'The error has a retryCall property that will recall the function that failed.'
192
194
  if (e.stack && e.message) {
193
- errorMessage = `Error applying semantics '${semantic.notes}'. Error is ${e.toString()} stack is ${e.stack}. Semantic is ${semantic.toString()}`
195
+ errorMessage = `Error applying semantics '${semantic.notes}'. Error is ${e.toString()} stack is ${e.stack}. Semantic is ${semantic.toString()}. ${help}`
194
196
  } else if (e.error) {
195
- errorMessage = `Error applying semantics '${semantic.notes}'. Error is ${e.error.join()}. Semantic is ${semantic.toString()}`
197
+ errorMessage = `Error applying semantics '${semantic.notes}'. Error is ${e.error.join()}. Semantic is ${semantic.toString()}. ${help}`
196
198
  } else {
197
199
  errorMessage = e.toString();
198
200
  }