theprogrammablemind_4wp 9.6.0 → 9.6.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client.js CHANGED
@@ -292,7 +292,9 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
292
292
  if (rebuildingTemplate) {
293
293
  data.errors_ignore_contextual_priorities_non_existant_ops = true
294
294
  }
295
- let queries = query.split('\\n')
295
+
296
+ // '\\n' from tests of '\n' from users. the former is because newline is not a valid json character so the testfile has it encoded
297
+ let queries = query.split(/\\n|\n/)
296
298
  const summaries = [] // for error
297
299
  try {
298
300
  const response = {
@@ -796,6 +798,8 @@ const defaultErrorHandler = async (error) => {
796
798
  if (typeof runtime.process.exit === 'function' && doErrorExit) {
797
799
  runtime.process.exit(-1)
798
800
  }
801
+
802
+ error.config = null // otherwise it dumps to much on the console
799
803
 
800
804
  throw error
801
805
  }
@@ -1184,10 +1188,7 @@ const checkTemplate = (template) => {
1184
1188
  if (!template) {
1185
1189
  return
1186
1190
  }
1187
- if (template.checks) {
1188
- throw new Error("The 'checks' property should be in the 'test' property not the 'template' property")
1189
- }
1190
- validProps(['fragments', 'configs'], template.template, 'template.template')
1191
+ validProps(['fragments', 'configs'], template, 'template.template')
1191
1192
  }
1192
1193
 
1193
1194
  const checkTest = (testConfig) => {
@@ -1221,9 +1222,11 @@ const knowledgeModuleImpl = async ({
1221
1222
  demo,
1222
1223
  test,
1223
1224
  template,
1225
+ instance, // instance file
1224
1226
  errorHandler = defaultErrorHandler,
1225
1227
  process: processResults = defaultProcess,
1226
1228
  stopAtFirstFailure = true,
1229
+ demoInitializer,
1227
1230
  ...rest
1228
1231
  } = {}) => {
1229
1232
  const unknownArgs = Object.keys(rest)
@@ -1273,13 +1276,13 @@ const knowledgeModuleImpl = async ({
1273
1276
  config.stop_auto_rebuild()
1274
1277
  await config.add(...(includes || []))
1275
1278
  if (api) {
1276
- config.setApi(api)
1279
+ await config.setApi(api)
1277
1280
  }
1278
1281
  if (multiApiInitializer) {
1279
1282
  await config.setMultiApi(multiApiInitializer)
1280
1283
  }
1281
1284
  if (initializer) {
1282
- config.initializer(initializer)
1285
+ await config.initializer(initializer)
1283
1286
  }
1284
1287
  await config.restart_auto_rebuild()
1285
1288
  return config
@@ -1308,7 +1311,7 @@ const knowledgeModuleImpl = async ({
1308
1311
  const helpDebugPriority = 'In order to get a debug break when a specific set of priorities is created set set DEBUG_PRIORITY environment variable to the JSON of the priorities that you want to break on. For example DEBUG_PRIORITY=\'[["verb", 0], ["article", 0]]\''
1309
1312
  const helpDebugContextualPriority = 'In order to get a debug break when a specific set of contextual priorities is created set set DEBUG_CONTEXTUAL_PRIORITY environment variable to the JSON of the priorities that you want to break on. For example DEBUG_CONTEXTUAL_PRIORITY=\'{ context: [["verb", 0], ["article", 0], select: 1}\''
1310
1313
  const helpDebugBridge = 'In order to get a debug break when a specific bridge is created set the DEBUG_BRIDGE environment variable to id to break on. For example DEBUG_BRIDGE=\'car\''
1311
- const helpDebugOperator = 'In order to get a debug break when a specific hierarcy is created set the DEBUG_OPERATOR environment variable to debug any config loaded. For example DEBUG_OPERATOR=\'([operator] ([arg]))\''
1314
+ const helpDebugOperator = 'In order to get a debug break when a specific hierarchy is created set the DEBUG_OPERATOR environment variable to debug any config loaded. For example DEBUG_OPERATOR=\'([operator] ([arg]))\''
1312
1315
 
1313
1316
  parser.add_argument('-tmn', '--testModuleName', { help: 'When running tests instead of using the current modules tests use the specified modules tests' })
1314
1317
  parser.add_argument('-t', '--test', { action: 'store_true', help: 'Run the tests. Create tests by running with the --query + --save flag' })
@@ -1377,6 +1380,10 @@ const knowledgeModuleImpl = async ({
1377
1380
  }
1378
1381
  config = await createConfig(true, configStruct.name)
1379
1382
 
1383
+ if (demoInitializer) {
1384
+ await config.setDemoInitializer(demoInitializer)
1385
+ }
1386
+
1380
1387
  // dont debug the load of the KM's if rebuild template is on since we want to debug the template rebuild not the load
1381
1388
  if (args.rebuildTemplate) {
1382
1389
  global.pauseDebugging = true
@@ -1459,7 +1466,7 @@ const knowledgeModuleImpl = async ({
1459
1466
  let tests = JSON.parse(runtime.fs.readFileSync(testConfig.name))
1460
1467
  tests = tests.filter((test) => test.query !== args.deleteTest)
1461
1468
  writeTestFile(testConfig.name, tests)
1462
- console.log(`Remove the test for "${args.deleteTest}"`)
1469
+ console.log(`Delete the test for "${args.deleteTest}"`)
1463
1470
  return
1464
1471
  }
1465
1472
 
@@ -1636,10 +1643,10 @@ const knowledgeModuleImpl = async ({
1636
1643
  let needsRebuild
1637
1644
  if (args.rebuildTemplate && !args.rebuildTemplateFull) {
1638
1645
  // get the startOfChanges for the partial rebuild
1639
- needsRebuild = config.needsRebuild(template.template, template.instance, { ...options, rebuild: false })
1646
+ needsRebuild = config.needsRebuild(template, instance, { ...options, rebuild: false })
1640
1647
  } else {
1641
1648
  // do a check or full rebuild
1642
- needsRebuild = config.needsRebuild(template.template, template.instance, options)
1649
+ needsRebuild = config.needsRebuild(template, instance, options)
1643
1650
  }
1644
1651
 
1645
1652
  if (needsRebuild.needsRebuild) {
@@ -1655,7 +1662,7 @@ const knowledgeModuleImpl = async ({
1655
1662
  config.config.rebuild = true
1656
1663
  }
1657
1664
  try {
1658
- await config.load(rebuildTemplate, template.template, template.instance, { rebuild: needsRebuild.needsRebuild || options.rebuild, previousResultss: needsRebuild.previousResultss, startOfChanges: needsRebuild.startOfChanges })
1665
+ await config.load(rebuildTemplate, template, instance, { rebuild: needsRebuild.needsRebuild || options.rebuild, previousResultss: needsRebuild.previousResultss, startOfChanges: needsRebuild.startOfChanges })
1659
1666
  config.fixtures()
1660
1667
  } catch (e) {
1661
1668
  console.error(`Error loading template for ${config.name}. ${e.error ? e.error : e}${e.stack ? e.stack : ''}`)
@@ -1977,8 +1984,8 @@ const knowledgeModuleImpl = async ({
1977
1984
  } else {
1978
1985
  const initConfig = async (config) => {
1979
1986
  if (template) {
1980
- if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess }).needsRebuild) {
1981
- config.needsRebuild(template.template, template.instance, { isModule: !isProcess })
1987
+ if (config.needsRebuild(template, instance, { isModule: !isProcess }).needsRebuild) {
1988
+ config.needsRebuild(template, instance, { isModule: !isProcess })
1982
1989
  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.`
1983
1990
  throw new Error(error)
1984
1991
  }
@@ -1993,7 +2000,7 @@ const knowledgeModuleImpl = async ({
1993
2000
  }
1994
2001
  if (template) {
1995
2002
  try {
1996
- await config.load(rebuildTemplate, template.template, template.instance)
2003
+ await config.load(rebuildTemplate, template, instance)
1997
2004
  } catch (e) {
1998
2005
  errorHandler(e)
1999
2006
  }
@@ -2013,6 +2020,9 @@ const knowledgeModuleImpl = async ({
2013
2020
  }
2014
2021
  const config = await createConfig(rootIsProcess, testingModuleName)
2015
2022
  await initConfig(config)
2023
+ if (demoInitializer) {
2024
+ config.setDemoInitializer(demoInitializer)
2025
+ }
2016
2026
  // config.rebuild({ isModule: true })
2017
2027
  createConfig.cached = config
2018
2028
  return createConfig.cached
package/package.json CHANGED
@@ -4,6 +4,7 @@
4
4
  "@typescript-eslint/eslint-plugin": "^4.28.4",
5
5
  "@typescript-eslint/parser": "^4.28.4",
6
6
  "argparse": "^2.0.1",
7
+ "baseline-browser-mapping": "^2.9.19",
7
8
  "eslint": "^7.32.0",
8
9
  "eslint-config-standard": "^16.0.3",
9
10
  "eslint-plugin-import": "^2.23.4",
@@ -72,6 +73,6 @@
72
73
  "scriptjs": "^2.5.9",
73
74
  "uuid": "^8.3.2"
74
75
  },
75
- "version": "9.6.0",
76
+ "version": "9.6.1-beta.0",
76
77
  "license": "UNLICENSED"
77
78
  }
package/src/config.js CHANGED
@@ -338,6 +338,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
338
338
 
339
339
  // done in setTestConfig
340
340
  if (bridge.check) {
341
+ /*
341
342
  if (!config.testConfig) {
342
343
  config.testConfig = {}
343
344
  }
@@ -347,6 +348,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
347
348
  if (!config.testConfig?.checks?.context) {
348
349
  config.testConfig.checks.context = []
349
350
  }
351
+ */
350
352
  config.contextChecksFromBridges.push({
351
353
  'bridge.id': bridge.id,
352
354
  'bridge.check': bridge.check,
@@ -405,9 +407,15 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
405
407
  if (bridge.generatorp) {
406
408
  const match = bridge.generatorp.match || (() => true)
407
409
  const apply = typeof bridge.generatorp === 'function' ? bridge.generatorp : bridge.generatorp.apply || bridge.generatorp
408
- let level = bridge.generatorp.level >= 0 ? bridge.generatorp.level : bridge.level + 1
409
- if (!bridge.bridge) {
410
- level = 0
410
+
411
+ let level
412
+ if (bridge.generatorp.level >= 0) {
413
+ level = bridge.generatorp.level
414
+ } else {
415
+ level = bridge.level + 1
416
+ if (!bridge.bridge ) {
417
+ level = 0
418
+ }
411
419
  }
412
420
 
413
421
  const generator = {
@@ -427,11 +435,25 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
427
435
  if (bridge.generatorr) {
428
436
  const match = bridge.generatorr.match || (() => true)
429
437
  const apply = typeof bridge.generatorr === 'function' ? bridge.generatorr : bridge.generatorr.apply || bridge.generatorr
430
- const level = bridge.generatorr.level >= 0 ? bridge.generatorr.level : bridge.level + 1
438
+ // const level = bridge.generatorr.level >= 0 ? bridge.generatorr.level : bridge.level + 1
439
+ let level
440
+ if (bridge.generatorr.level >= 0) {
441
+ level = bridge.generatorr.level
442
+ } else {
443
+ level = bridge.level + 1
444
+ if (!bridge.bridge ) {
445
+ level = 0
446
+ }
447
+ }
431
448
  const generator = {
432
449
  where: bridge.generatorr.where || bridge.where || helpers.where(4),
433
450
  // match: async (args) => bridge.id === args.context.marker && args.context.level === level && !args.context.paraphrase && (args.context.response || args.context.isResponse) && await match(args),
434
- match: async (args) => args.isA(args.context.marker, bridge.id) && args.context.level === level && !args.context.paraphrase && (args.context.response || args.context.isResponse) && await match(args),
451
+ match: async (args) => {
452
+ if (bridge.callId == args.callId) {
453
+ debugger
454
+ }
455
+ return args.isA(args.context.marker, bridge.id) && args.context.level === level && !args.context.paraphrase && (args.context.response != null || args.context.isResponse) && await match(args)
456
+ },
435
457
  apply: (args) => apply(args),
436
458
  applyWrapped: apply,
437
459
  property: 'generatorr'
@@ -523,6 +545,7 @@ const handleCalculatedProps = (baseConfig, moreConfig, { addFirst, uuid } = {})
523
545
  'associations',
524
546
  'before',
525
547
  'bridge',
548
+ 'callId',
526
549
  'check',
527
550
  'children',
528
551
  'conditional',
@@ -536,6 +559,7 @@ const handleCalculatedProps = (baseConfig, moreConfig, { addFirst, uuid } = {})
536
559
  'generatorr',
537
560
  'generators',
538
561
  'id',
562
+ 'init',
539
563
  'inverted',
540
564
  'isA',
541
565
  'level',
@@ -553,7 +577,8 @@ const handleCalculatedProps = (baseConfig, moreConfig, { addFirst, uuid } = {})
553
577
  'skipable',
554
578
  'uuid',
555
579
  'where',
556
- 'words', /Bridge$/,
580
+ 'words',
581
+ /Bridge$/,
557
582
  ]
558
583
  helpers.validProps(valid, bridge, 'bridge')
559
584
  handleBridgeProps(baseConfig, bridge, { addFirst, uuid })
@@ -1093,19 +1118,6 @@ class Config {
1093
1118
  this.testConfig.checks.context = []
1094
1119
  }
1095
1120
  this.testConfig.checks.context = this.contextChecksFromBridges.concat(this.testConfig.checks.context)
1096
- /*
1097
- const currentTestConfig = testConfig // add bridge has added check.context's
1098
-
1099
- if (!this.testConfig.checks) {
1100
- debugger
1101
- // this.testConfig.checks =
1102
- }
1103
-
1104
- // set during bridge setup
1105
- if (currentTestConfig.checks?.context) {
1106
- this.testConfig.checks.context = currentTestConfig.checks.context.concat(this.testConfig.checks.context)
1107
- }
1108
- */
1109
1121
  }
1110
1122
 
1111
1123
  getTestConfig () {
@@ -1223,10 +1235,10 @@ class Config {
1223
1235
  async getEvaluator (s, calls, log, context, args) {
1224
1236
  const instance = await s({ ...args, ...context, evaluate: true })
1225
1237
  calls.touch(instance)
1226
- if (!instance.evalue && !instance.verbatim && !instance.value) {
1238
+ if (instance.evalue == null && !instance.verbatim && !instance.value) {
1227
1239
  this.warningNotEvaluated(log, context)
1228
1240
  }
1229
- if (!instance.evalue) {
1241
+ if (instance.evalue == null) {
1230
1242
  instance.evalue = instance.value
1231
1243
  instance.edefault = true
1232
1244
  }
@@ -2139,6 +2151,11 @@ class Config {
2139
2151
  }
2140
2152
  }
2141
2153
 
2154
+ async setDemoInitializer(demoInitializer) {
2155
+ this.demoInitializer = demoInitializer
2156
+ // await this.demoInitializer(this)
2157
+ }
2158
+
2142
2159
  // configs = [ { config, namespace } ... ]
2143
2160
  constructor (config, module, clientProcess, apiKMs, rootIsProcess, testingModuleName) {
2144
2161
  if (config instanceof Config) {
@@ -2162,6 +2179,7 @@ class Config {
2162
2179
  config.priorities = config.priorities || []
2163
2180
  }
2164
2181
 
2182
+ this.demoInitializer = null
2165
2183
  this.contextChecksFromBridges = []
2166
2184
 
2167
2185
  this._enable = []
@@ -2275,7 +2293,7 @@ class Config {
2275
2293
 
2276
2294
  async restart_auto_rebuild () {
2277
2295
  this._stop_auto_rebuild = false
2278
- await this.rebuild()
2296
+ return await this.rebuild()
2279
2297
  }
2280
2298
 
2281
2299
  getAddedArgs (args) {
@@ -2478,6 +2496,7 @@ class Config {
2478
2496
  this.valid()
2479
2497
  const cp = new Config()
2480
2498
  cp.logs = []
2499
+ cp.demoInitializer = this.demoInitializer
2481
2500
  cp.maxDepth = this.maxDepth
2482
2501
  cp.debugLoops = this.debugLoops
2483
2502
  cp.transitoryMode = this.transitoryMode
@@ -2552,6 +2571,11 @@ class Config {
2552
2571
  cp.config.objects.namespaced[km._uuid] = {}
2553
2572
  })
2554
2573
  }
2574
+
2575
+ if (cp.demoInitializer) {
2576
+ await cp.demoInitializer(cp)
2577
+ }
2578
+
2555
2579
  cp.valid()
2556
2580
  return cp
2557
2581
  }
@@ -2854,7 +2878,11 @@ class Config {
2854
2878
  let defaults = () => []
2855
2879
  if (this.loadOrdering) {
2856
2880
  for (const name of this.loadOrdering) {
2857
- const checks = this.kms[name].testConfig?.checks?.context || []
2881
+ const config = this.kms[name]
2882
+ let checks = config.testConfig?.checks?.context || []
2883
+ if (config.contextChecksFromBridges) {
2884
+ checks = config.contextChecksFromBridges.concat(checks)
2885
+ }
2858
2886
  const oldDefaults = defaults
2859
2887
  for (const check of checks) {
2860
2888
  if (!check.match) {
@@ -3076,6 +3104,15 @@ class Config {
3076
3104
  this.removeDevelopmentElements(this.config)
3077
3105
  }
3078
3106
 
3107
+ if (this.testConfig?.testModuleName) {
3108
+ const km = this.km(this.testConfig.testModuleName)
3109
+ if (km.demoInitializer) {
3110
+ await km.demoInitializer(km)
3111
+ }
3112
+ } else if (this.demoInitializer) {
3113
+ await this.demoInitializer(this)
3114
+ }
3115
+
3079
3116
  this.valid()
3080
3117
  this.checks()
3081
3118
  }
@@ -3461,7 +3498,8 @@ class Config {
3461
3498
  }
3462
3499
 
3463
3500
  // TODO get rid of useOldVersion arg
3464
- addInternal (more, { uuid, km, addFirst = false, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false, handleCalculatedProps: hcps = false } = {}) {
3501
+ addInternal (more,
3502
+ { uuid, km, addFirst = false, useOldVersion = true, skipObjects = false, includeNamespaces = true, allowNameToBeNull = false, handleCalculatedProps: hcps = false } = {}) {
3465
3503
  validConfigProps(more)
3466
3504
  if (more instanceof Config) {
3467
3505
  more.initialize({ force: false })
@@ -86,6 +86,28 @@ const cleanAssign = (dest, ...srcs) => {
86
86
  Object.assign(dest, ...srcs)
87
87
  }
88
88
 
89
+ class ContextHierarchy {
90
+ constructor(contexts = []) {
91
+ this.contexts = [...contexts]
92
+ }
93
+
94
+ push(context) {
95
+ this.contexts.push(context)
96
+ }
97
+
98
+ pop() {
99
+ this.contexts.pop()
100
+ }
101
+
102
+ under(marker) {
103
+ for (let i = this.contexts.length - 1; i >= 0; --i) {
104
+ if (this.contexts[i].marker == marker) {
105
+ return true
106
+ }
107
+ }
108
+ }
109
+ }
110
+
89
111
  const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
90
112
  if (!args.objects) {
91
113
  args.objects = config.get('objects')
@@ -105,6 +127,7 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
105
127
  if (global.theprogrammablemind && global.theprogrammablemind.loadForTesting) {
106
128
  args.calls = new InitCalls(Object.keys(global.theprogrammablemind.loadForTesting)[0])
107
129
  }
130
+ args.contextHierarchy = new ContextHierarchy()
108
131
  args.cleanAssign = cleanAssign
109
132
  args.km = (name) => config.getConfig(name)
110
133
  args.api = (name) => config.getConfig(name).api
@@ -151,12 +174,22 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
151
174
  // debugger
152
175
  // }
153
176
  const { assumed = {}, options = {} } = rest
177
+ // have it default to paraphrase
178
+ if (['number', 'string', 'boolean'].includes(typeof c)) {
179
+ return `${c}`
180
+ }
181
+ if (false && !(assumed.isResponse && assumed.response)) {
182
+ assumed.paraphrase = true
183
+ }
154
184
  return config.getGenerators(logs).apply(addAssumed(args, assumed), c, assumed, options)
155
185
  }
156
186
  args.gp = (c, rest = {}) => {
157
187
  // if (JSON.stringify(rest) !== '{}' && !(rest.assumed || rest.options)) {
158
188
  // debugger
159
189
  // }
190
+ if (['number', 'string', 'boolean'].includes(typeof c)) {
191
+ return `${c}`
192
+ }
160
193
  const { assumed = {}, options = {} } = rest
161
194
  return config.getGenerators(logs).apply(addAssumed(args, assumed, { paraphrase: true, isResponse: false, response: false }), c, { paraphrase: true, isResponse: false, response: false }, options)
162
195
  }
@@ -164,6 +197,9 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
164
197
  // if (JSON.stringify(rest) !== '{}' && !(rest.assumed || rest.options)) {
165
198
  // debugger
166
199
  // }
200
+ if (['number', 'string', 'boolean'].includes(typeof c)) {
201
+ return `${c}`
202
+ }
167
203
  const { assumed = {}, options = {} } = rest
168
204
  return config.getGenerators(logs).apply(addAssumed(args, assumed, { paraphrase: false, isResponse: true }), { ...c, paraphrase: false, isResponse: true }, options)
169
205
  }
package/src/debug.js CHANGED
@@ -51,6 +51,7 @@ const counter = (name, { breakAt = [], debugBreak = true, tag = '' } = {}) => {
51
51
  hit(name)
52
52
  return true
53
53
  }
54
+ return counters[name]
54
55
  }
55
56
 
56
57
  const get = (name) => {
package/src/digraph.js CHANGED
@@ -80,6 +80,9 @@ class Digraph {
80
80
  */
81
81
 
82
82
  acdcs (s, from, to) {
83
+ if (!s) {
84
+ return new Set()
85
+ }
83
86
  const todo = [s]
84
87
  const seen = new Set([s])
85
88
  const acdcs = new Set([])
package/src/fragments.js CHANGED
@@ -1,6 +1,18 @@
1
1
  const _ = require('lodash')
2
2
  const helpers = require('./helpers')
3
3
 
4
+ function pathEquals (p1, p2) {
5
+ if (p1.length !== p2.length) {
6
+ return false
7
+ }
8
+ for (let i = 0; i < p1.length; ++i) {
9
+ if (p1[i] !== p2[i]) {
10
+ return false
11
+ }
12
+ }
13
+ return true
14
+ }
15
+
4
16
  function fragmentInstantiator (args, contexts) {
5
17
  return new Object({
6
18
  contexts: () => {
@@ -10,6 +22,7 @@ function fragmentInstantiator (args, contexts) {
10
22
  const instantiated = _.cloneDeep(contexts)
11
23
  const todo = [{ context: instantiated, path: [] }]
12
24
  args = { ...args }
25
+ args.pathEquals = pathEquals
13
26
  while (todo.length > 0) {
14
27
  const { context, path } = todo.pop()
15
28
  args.context = context
package/src/helpers.js CHANGED
@@ -1,6 +1,31 @@
1
1
  const deepEqual = require('deep-equal')
2
2
  const stringify = require('json-stable-stringify')
3
3
 
4
+ function watchProperty(obj, propName) {
5
+ let value = obj[propName];
6
+
7
+ Object.defineProperty(obj, propName, {
8
+ get() {
9
+ return value;
10
+ },
11
+ set(newValue) {
12
+ console.log(`%c${propName} changed →`, 'color: #e83', newValue);
13
+ debugger; // ← Chrome/Firefox will pause here automatically
14
+ value = newValue;
15
+ },
16
+ configurable: true // allows us to delete/restore later if needed
17
+ });
18
+ }
19
+
20
+ function assignAssumed(object, assumed) {
21
+ for (const key in assumed) {
22
+ if (object[key] == null) {
23
+ object[key] = assumed[key]
24
+ }
25
+ }
26
+ return object
27
+ }
28
+
4
29
  function where (goUp = 2) {
5
30
  const e = new Error()
6
31
  const regexForm1 = /\((.*):(\d+):(\d+)\)$/
@@ -567,4 +592,6 @@ module.exports = {
567
592
  suggestAssociationsFixFromSummaries,
568
593
  getByPath,
569
594
  setByPath,
595
+ assignAssumed,
596
+ watchProperty,
570
597
  }
package/src/project2.js CHANGED
@@ -11,7 +11,7 @@ function areFirstNEqual(arr1, arr2, n) {
11
11
  }
12
12
 
13
13
  function project(source, filters, path=[]) {
14
- if (['string', 'number'].includes(typeof source)) {
14
+ if (['boolean', 'string', 'number'].includes(typeof source)) {
15
15
  return source
16
16
  }
17
17
  if (Array.isArray(source)) {
@@ -63,7 +63,9 @@ function project(source, filters, path=[]) {
63
63
  properties.forEach(prop => {
64
64
  if (prop.path && (prop.path.length === path.length + 1) && areFirstNEqual(path, prop.path, path.length) && source.hasOwnProperty(prop.path[path.length])) {
65
65
  const endProp = prop.path[path.length]
66
- if (Array.isArray(source[endProp])) {
66
+ if (['boolean', 'string', 'number'].includes(typeof source[endProp])) {
67
+ result[endProp] = source[endProp]
68
+ } else if (Array.isArray(source[endProp])) {
67
69
  result[endProp] = []
68
70
  for (const key in source[endProp]) {
69
71
  result[endProp].push(project(source[endProp][key], filters, [...path, endProp, key]))
package/src/semantics.js CHANGED
@@ -156,11 +156,21 @@ class Semantics {
156
156
  }
157
157
 
158
158
  async applyToContext (args, context, options) {
159
+ args.contextHierarchy.push(context)
160
+ try {
161
+ return await this.applyToContextHelper(args, context, options)
162
+ } finally {
163
+ args.contextHierarchy.pop()
164
+ }
165
+ }
166
+
167
+ async applyToContextHelper (args, context, options) {
159
168
  // let context_prime = {}
160
169
  if (!(context instanceof Array || context instanceof Object)) {
161
170
  return context
162
171
  }
163
172
  args = { ...args }
173
+
164
174
  const config = args.config
165
175
  const debug = config.getDebug()
166
176
  let contextPrime = Object.assign({}, context)