theprogrammablemind_4wp 7.5.8-beta.68 → 7.5.8-beta.69
Sign up to get free protection for your applications and to get access to all the features.
- package/client.js +60 -41
- package/package.json +1 -1
- package/src/config.js +83 -41
- package/src/project.js +22 -2
package/client.js
CHANGED
@@ -2,6 +2,7 @@ const { Semantics, Semantic } = require('./src/semantics')
|
|
2
2
|
const { Generators, Generator } = require('./src/generators')
|
3
3
|
const DigraphInternal = require('./src/digraph_internal')
|
4
4
|
const Digraph = require('./src/digraph')
|
5
|
+
const { project } = require('./src/project')
|
5
6
|
const fetch = require('node-fetch')
|
6
7
|
const base64 = require('base-64')
|
7
8
|
const deepEqual = require('deep-equal')
|
@@ -22,11 +23,7 @@ const getConfig_getContextCheck = (testConfig) => {
|
|
22
23
|
}
|
23
24
|
|
24
25
|
const pickContext = (testConfig) => (context) => {
|
25
|
-
|
26
|
-
for (let prop of getConfig_getContextCheck(testConfig)) {
|
27
|
-
picked[prop] = context[prop]
|
28
|
-
}
|
29
|
-
return sortJson(picked, { depth: 25 })
|
26
|
+
return project(context, getConfig_getContextCheck(testConfig))
|
30
27
|
}
|
31
28
|
|
32
29
|
const getAsk = (config) => (uuid) => (asks) => {
|
@@ -384,7 +381,7 @@ const setupContexts = (rawContexts) => {
|
|
384
381
|
return contexts
|
385
382
|
}
|
386
383
|
|
387
|
-
const processContextsB = ({ config, hierarchy, semantics, generators, json, isTest, isInstance, query, data, retries, url, commandLineArgs }) => {
|
384
|
+
const processContextsB = ({ config, hierarchy, semantics, generators, json, isTest, isInstance, instance, query, data, retries, url, commandLineArgs }) => {
|
388
385
|
// TODO fix this name to contextsPrime
|
389
386
|
const contextsPrime = []
|
390
387
|
const generatedPrime = []
|
@@ -395,7 +392,7 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
|
|
395
392
|
const contexts = setupContexts(json.contexts)
|
396
393
|
|
397
394
|
const objects = config.get('objects')
|
398
|
-
const args = { objects, isResponse: true, response: json, isTest, isInstance, getObjects: getObjects(objects),
|
395
|
+
const args = { objects, isResponse: true, response: json, isTest, isInstance, getObjects: getObjects(objects), instance }
|
399
396
|
if (!json.logs) {
|
400
397
|
json.logs = []
|
401
398
|
}
|
@@ -406,28 +403,6 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
|
|
406
403
|
config.debugLoops = commandLineArgs && commandLineArgs.debugLoops
|
407
404
|
while (toDo.length > 0) {
|
408
405
|
const context = toDo.shift()
|
409
|
-
/*
|
410
|
-
if (false && query) {
|
411
|
-
if (config.wasChanged()) {
|
412
|
-
// process contexts that overlap
|
413
|
-
overlap = lastRange
|
414
|
-
} else {
|
415
|
-
config.watch()
|
416
|
-
}
|
417
|
-
if (overlap) {
|
418
|
-
if (overlaps(overlap, context)) {
|
419
|
-
// okay
|
420
|
-
query = query.slice(overlap.end+1)
|
421
|
-
data.utterance = query
|
422
|
-
const json = await doWithRetries(retries, url, data)
|
423
|
-
toDo = setupContexts(json.contexts).slice(1) // take off the start context
|
424
|
-
}
|
425
|
-
overlap = undefined
|
426
|
-
}
|
427
|
-
lastRange = context.range
|
428
|
-
}
|
429
|
-
*/
|
430
|
-
|
431
406
|
args.calls.next()
|
432
407
|
let contextPrime = context
|
433
408
|
context.topLevel = true
|
@@ -446,6 +421,9 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
|
|
446
421
|
e.message += `\nThe most called semantic was:\nnotes: ${mostCalled.notes}\nmatch: ${mostCalled.matcher.toString()}\napply: ${mostCalled._apply.toString()}\n`
|
447
422
|
}
|
448
423
|
// contextPrime = semantics.apply(args, { marker: 'error', context, error: e })
|
424
|
+
if (isInstance) {
|
425
|
+
console.log('error', e.error)
|
426
|
+
}
|
449
427
|
contextPrime = semantics.apply(args, { marker: 'error', context, reason: e.reason })
|
450
428
|
}
|
451
429
|
}
|
@@ -605,7 +583,7 @@ const loadInstance = (config, instance) => {
|
|
605
583
|
// config.addInternal(config.template.queries[i], { handleCalculatedProps: true } )
|
606
584
|
config.addInternal(instance.template.queries[i], { addFirst: true, handleCalculatedProps: true } )
|
607
585
|
} else {
|
608
|
-
processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {}, isInstance: `instance${i}
|
586
|
+
processContextsB({ config, hierarchy, json: results/*, generators, semantics */, commandLineArgs: {}, isInstance: `instance${i}`, instance: instance.queries[i] })
|
609
587
|
}
|
610
588
|
}
|
611
589
|
global.transitoryMode = transitoryMode
|
@@ -632,7 +610,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
|
|
632
610
|
|
633
611
|
let { data, /* generators, semantics, */ hierarchy } = setupProcessB({ config, initializer, allowDelta: true })
|
634
612
|
if (commandLineArgs && commandLineArgs.checkForLoop) {
|
635
|
-
data.checkForLoop =
|
613
|
+
data.checkForLoop = commandLineArgs.checkForLoop
|
636
614
|
}
|
637
615
|
if (rebuildingTemplate) {
|
638
616
|
data.errors_ignore_contextual_priorities_non_existant_ops = true
|
@@ -702,6 +680,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
|
|
702
680
|
response.times += json.times
|
703
681
|
response.trace = response.trace.concat(json.trace)
|
704
682
|
response.version = json.version
|
683
|
+
response.explain_priorities = json.explain_priorities
|
705
684
|
|
706
685
|
response.contexts = response.contexts.concat(contextsPrime)
|
707
686
|
response.generated = response.generated.concat(generatedPrime)
|
@@ -1170,6 +1149,12 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
|
|
1170
1149
|
return picked
|
1171
1150
|
}
|
1172
1151
|
|
1152
|
+
if (responses.explain_priorities) {
|
1153
|
+
console.log("Explain Priorities")
|
1154
|
+
for ([inputss, outpus, reason] of responses.explain_priorities) {
|
1155
|
+
console.log(` ${JSON.stringify(inputss)} reason: ${reason}`)
|
1156
|
+
}
|
1157
|
+
}
|
1173
1158
|
const picked = pickEm()
|
1174
1159
|
if (!_.isEmpty(picked)) {
|
1175
1160
|
console.log('--- checked object properties ---')
|
@@ -1438,7 +1423,7 @@ const knowledgeModule = async ({
|
|
1438
1423
|
parser.add_argument('-i', '--info', { action: 'store_true', help: 'Print meta-data for the module' })
|
1439
1424
|
parser.add_argument('-v', '--vimdiff', { action: 'store_true', help: 'For failures run vimdiff' })
|
1440
1425
|
parser.add_argument('-g', '--greg', { action: 'store_true', help: 'Set the server to be localhost so I can debug stuff' })
|
1441
|
-
parser.add_argument('-cl', '--checkForLoop', {
|
1426
|
+
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]]' })
|
1442
1427
|
parser.add_argument('-r', '--retrain', { action: 'store_true', help: 'Get the server to retrain the neural nets' })
|
1443
1428
|
parser.add_argument('-q', '--query', { help: 'Run the specified query' })
|
1444
1429
|
parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
|
@@ -1451,15 +1436,16 @@ const knowledgeModule = async ({
|
|
1451
1436
|
parser.add_argument('-p', '--print', { help: 'Print the specified elements c === config, w === words, b === bridges, o === operators d === objects (d for data), h === hierarchy, g === generators, s === semantics, l === load t=tests ordering p === priorities a == associations j == JSON sent to server. for example --print wb' })
|
1452
1437
|
parser.add_argument('-s', '--save', { action: 'store_true', help: 'When running with the --query flag this will save the current run to the test file. When running without the --query flag all tests will be run and resaved.' })
|
1453
1438
|
parser.add_argument('-sd', '--saveDeveloper', { action: 'store_true', help: 'Same as -s but the query will not show up in the info command.' })
|
1454
|
-
parser.add_argument('-dic', '--debugIncludeConvolutions', { action: 'store_true', help: 'When running with the --debugIncludeConvolutions flag the logs will include convolutions which are somewhat annoying verbose. Default is false' })
|
1455
1439
|
parser.add_argument('-dl', '--debugLoops', { action: 'store_true', help: 'When running with the --debugLoops flag the logs calls to semantics and generators will be immediately written to the console '})
|
1456
1440
|
parser.add_argument('-d', '--debug', { action: 'store_true', help: 'When running with the --debug flag this set the debug flag in the config' })
|
1457
|
-
parser.add_argument('-da', '--debugAssociation', { help: helpDebugAssociation })
|
1458
|
-
parser.add_argument('-dh', '--debugHierarchy', { help: helpDebugHierarchy })
|
1459
|
-
parser.add_argument('-dp', '--debugPriority', { help: helpDebugPriority })
|
1460
|
-
parser.add_argument('-dcp', '--debugContextualPriority', { help: helpDebugContextualPriority })
|
1461
|
-
parser.add_argument('-db', '--debugBridge', { help: helpDebugBridge })
|
1462
|
-
parser.add_argument('-do', '--debugOperator', { help: helpDebugOperator })
|
1441
|
+
parser.add_argument('-da', '--debugAssociation', { action: 'store_true', help: helpDebugAssociation })
|
1442
|
+
parser.add_argument('-dh', '--debugHierarchy', { action: 'store_true', help: helpDebugHierarchy })
|
1443
|
+
parser.add_argument('-dp', '--debugPriority', { action: 'store_true', help: helpDebugPriority })
|
1444
|
+
parser.add_argument('-dcp', '--debugContextualPriority', { action: 'store_true', help: helpDebugContextualPriority })
|
1445
|
+
parser.add_argument('-db', '--debugBridge', { action: 'store_true', help: helpDebugBridge })
|
1446
|
+
parser.add_argument('-do', '--debugOperator', { action: 'store_true', help: helpDebugOperator })
|
1447
|
+
parser.add_argument('-ep', '--explainPriorities', { action: 'store_true', help: "The server will return all priorities including the generated one along with an explanation of there they came from"})
|
1448
|
+
parser.add_argument('-dic', '--debugIncludeConvolutions', { nargs: "?", help: 'When running with the --debugIncludeConvolutions flag the logs will include convolutions which are somewhat annoyingly verbose. Default is false' })
|
1463
1449
|
|
1464
1450
|
const args = parser.parse_args()
|
1465
1451
|
args.count = args.count || 1
|
@@ -1467,7 +1453,35 @@ const knowledgeModule = async ({
|
|
1467
1453
|
if (args.parenthesized) {
|
1468
1454
|
config.parenthesized = true
|
1469
1455
|
}
|
1470
|
-
|
1456
|
+
if (args.checkForLoop) {
|
1457
|
+
try {
|
1458
|
+
args.checkForLoop = JSON.parse(args.checkForLoop)
|
1459
|
+
const isKey = (what) => {
|
1460
|
+
if (!Array.isArray(what)) {
|
1461
|
+
return false
|
1462
|
+
}
|
1463
|
+
if (what.length !== 2) {
|
1464
|
+
return false
|
1465
|
+
}
|
1466
|
+
if (!typeof what[0] == 'string') {
|
1467
|
+
return false
|
1468
|
+
}
|
1469
|
+
if (!typeof what[1] == 'number') {
|
1470
|
+
return false
|
1471
|
+
}
|
1472
|
+
return true
|
1473
|
+
}
|
1474
|
+
if (!Array.isArray(args.checkForLoop) || args.checkForLoop.some((value) => !isKey(value))) {
|
1475
|
+
throw new Error(`Error for the checkForLoop argument. Expected a JSON array of operator keys of the form "[<id>, <level>]"`)
|
1476
|
+
}
|
1477
|
+
} catch( e ) {
|
1478
|
+
throw new Error(`Error parsing JSON of the checkForLoop argument. ${e}`)
|
1479
|
+
}
|
1480
|
+
} else {
|
1481
|
+
if (process.argv.includes('--checkForLoop') || process.argv.includes('-cl')) {
|
1482
|
+
args.checkForLoop = true
|
1483
|
+
}
|
1484
|
+
}
|
1471
1485
|
if (args.debugAssociation) {
|
1472
1486
|
console.log(helpDebugAssociation)
|
1473
1487
|
runtime.process.exit(-1)
|
@@ -1525,7 +1539,12 @@ const knowledgeModule = async ({
|
|
1525
1539
|
if (args.debug) {
|
1526
1540
|
config.config.debug = true
|
1527
1541
|
}
|
1528
|
-
|
1542
|
+
|
1543
|
+
if (args.explainPriorities) {
|
1544
|
+
config.config.explain_priorities = true
|
1545
|
+
}
|
1546
|
+
|
1547
|
+
config.config.debugIncludeConvolutions = args.debugIncludeConvolutions || process.argv.includes('--debugIncludeConvolutions') || process.argv.includes('-dic')
|
1529
1548
|
|
1530
1549
|
if (template) {
|
1531
1550
|
const needsRebuild = config.needsRebuild(template.template, template.instance, options)
|
package/package.json
CHANGED
package/src/config.js
CHANGED
@@ -30,6 +30,72 @@ const config_toServer = (config) => {
|
|
30
30
|
}
|
31
31
|
}
|
32
32
|
|
33
|
+
const debugPriority = (priority) => {
|
34
|
+
if (global.entodictonDebugPriority) {
|
35
|
+
if (helpers.safeEquals(entodictonDebugPriority, priority)) {
|
36
|
+
debugger; // debug hierarchy hit
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
const debugAssociation = (association) => {
|
42
|
+
if (global.entodictonDebugAssociation) {
|
43
|
+
if (helpers.safeEquals(global.entodictonDebugAssociation, association)) {
|
44
|
+
debugger; // debug association hit
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
const debugContextualPriority = (contextual_priority) => {
|
50
|
+
if (global.entodictonDebugContextualPriority) {
|
51
|
+
if (helpers.safeEquals(entodictonDebugContextualPriority, contextual_priorities)) {
|
52
|
+
debugger; // debug hierarchy hit
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
const debugHierarchy = (pair) => {
|
58
|
+
if (global.entodictonDebugHierarchy) {
|
59
|
+
if (helpers.safeEquals(global.entodictonDebugHierarchy, pair)) {
|
60
|
+
debugger; // debug hierarchy hit
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
const debugBridge = (bridge) => {
|
66
|
+
if (global.entodictonDebugBridge) {
|
67
|
+
if (global.entodictonDebugBridge[0] == bridge.id && global.entodictonDebugBridge[1] == bridge.level) {
|
68
|
+
debugger; // debug hierarchy hit
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
const debugOperator = (operator) => {
|
74
|
+
if (global.entodictonDebugOperator) {
|
75
|
+
if ((operator.pattern || operator) === global.entodictonDebugOperator) {
|
76
|
+
debugger; // debug operator hit
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
const debugConfigProps = (config) => {
|
82
|
+
const checkProps = [
|
83
|
+
{ property: 'priorities', check: (v) => debugPriority(v) },
|
84
|
+
{ property: 'association', check: (v) => debugAssociation(v) },
|
85
|
+
{ property: 'contextual_priorities', check: (v) => debugContextualPriority(v) },
|
86
|
+
{ property: 'hierarchy', check: (v) => debugHierarchy(v) },
|
87
|
+
{ property: 'operators', check: (v) => debugOperator(v) },
|
88
|
+
{ property: 'bridges', check: (v) => debugBridge(v) },
|
89
|
+
]
|
90
|
+
for (const { property, check } of checkProps) {
|
91
|
+
if (config[property]) {
|
92
|
+
for (const value of config[property]) {
|
93
|
+
check(value)
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
33
99
|
const validConfigProps = (config) => {
|
34
100
|
const valid = [
|
35
101
|
'hierarchy',
|
@@ -188,7 +254,7 @@ const handleBridgeProps = (config, bridge, addFirst) => {
|
|
188
254
|
if (typeof after == 'string') {
|
189
255
|
after = [after, 0]
|
190
256
|
}
|
191
|
-
config.addPriorities([
|
257
|
+
config.addPriorities([[bridge.id, bridge.level], after])
|
192
258
|
}
|
193
259
|
}
|
194
260
|
if (bridge.after) {
|
@@ -196,7 +262,7 @@ const handleBridgeProps = (config, bridge, addFirst) => {
|
|
196
262
|
if (typeof before == 'string') {
|
197
263
|
before = [before, 0]
|
198
264
|
}
|
199
|
-
config.addPriorities([[bridge.id, bridge.level]
|
265
|
+
config.addPriorities([before, [bridge.id, bridge.level]])
|
200
266
|
}
|
201
267
|
}
|
202
268
|
if (bridge.words) {
|
@@ -1046,6 +1112,9 @@ class Config {
|
|
1046
1112
|
}
|
1047
1113
|
}
|
1048
1114
|
|
1115
|
+
debugConfig() {
|
1116
|
+
}
|
1117
|
+
|
1049
1118
|
addAssociation (association) {
|
1050
1119
|
if (!this.config.associations) {
|
1051
1120
|
this.config.associations = {
|
@@ -1053,25 +1122,18 @@ class Config {
|
|
1053
1122
|
positive: []
|
1054
1123
|
}
|
1055
1124
|
}
|
1056
|
-
|
1057
|
-
if (helpers.safeEquals(global.entodictonDebugAssociation, association)) {
|
1058
|
-
debugger; // debug association hit
|
1059
|
-
}
|
1060
|
-
}
|
1125
|
+
debugAssociation(association)
|
1061
1126
|
this.config.associations.positive.push(association)
|
1062
1127
|
this._delta.json.associations.push({ action: 'add', association })
|
1063
1128
|
}
|
1064
1129
|
|
1065
1130
|
// TODO add more error checking to these like addHierarchy has
|
1131
|
+
// TODO change name from priorities to priority
|
1066
1132
|
addPriorities (priorities) {
|
1067
1133
|
if (!this.config.priorities) {
|
1068
1134
|
this.config.priorities = []
|
1069
1135
|
}
|
1070
|
-
|
1071
|
-
if (helpers.safeEquals(entodictonDebugPriority, priorities)) {
|
1072
|
-
debugger; // debug hierarchy hit
|
1073
|
-
}
|
1074
|
-
}
|
1136
|
+
debugPriority(priorities)
|
1075
1137
|
this.config.priorities.push(priorities)
|
1076
1138
|
this._delta.json.priorities.push({ action: 'add', priorities })
|
1077
1139
|
}
|
@@ -1081,11 +1143,7 @@ class Config {
|
|
1081
1143
|
if (!this.config.contextual_priorities) {
|
1082
1144
|
this.config.contextual_priorities = []
|
1083
1145
|
}
|
1084
|
-
|
1085
|
-
if (helpers.safeEquals(entodictonDebugContextualPriority, contextual_priorities)) {
|
1086
|
-
debugger; // debug hierarchy hit
|
1087
|
-
}
|
1088
|
-
}
|
1146
|
+
debugContextualPriority(contextual_priority)
|
1089
1147
|
contextual_priority_valid(contextual_priority)
|
1090
1148
|
this.config.contextual_priorities.push(contextual_priority)
|
1091
1149
|
const cpServer = contextual_priorities_toServer(contextual_priority)
|
@@ -1109,11 +1167,7 @@ class Config {
|
|
1109
1167
|
if (typeof parent !== 'string') {
|
1110
1168
|
throw new Error(`addHierarchy expected parent property to be a string. got ${JSON.stringify(parent)}`)
|
1111
1169
|
}
|
1112
|
-
|
1113
|
-
if (helpers.safeEquals(entodictonDebugHierarchy, [child, parent])) {
|
1114
|
-
debugger; // debug hierarchy hit
|
1115
|
-
}
|
1116
|
-
}
|
1170
|
+
debugHierarchy([child, parent])
|
1117
1171
|
this.config.hierarchy.push(edge)
|
1118
1172
|
// TODO greg11 this.hierarchy.addEdge(edge)
|
1119
1173
|
this._delta.json.hierarchy.push([child, parent])
|
@@ -1126,13 +1180,7 @@ class Config {
|
|
1126
1180
|
if (typeof parent !== 'string') {
|
1127
1181
|
throw new Error(`addHierarchy expected parent to be a string. got ${JSON.stringify(parent)}`)
|
1128
1182
|
}
|
1129
|
-
|
1130
|
-
if (global.entodictonDebugHierarchy) {
|
1131
|
-
if (helpers.safeEquals(global.entodictonDebugHierarchy, [child, parent])) {
|
1132
|
-
debugger; // debug hierarchy hit
|
1133
|
-
}
|
1134
|
-
}
|
1135
|
-
|
1183
|
+
debugHierarchy([child, parent])
|
1136
1184
|
if (this.config.hierarchy.find( (element) => {
|
1137
1185
|
const hc = hierarchyCanonical(element)
|
1138
1186
|
if (child == hc.child && parent == hc.parent) {
|
@@ -1161,13 +1209,8 @@ class Config {
|
|
1161
1209
|
}
|
1162
1210
|
const bridges = this.config.bridges
|
1163
1211
|
const def = Object.assign({}, bridge, { uuid: uuid || this._uuid })
|
1164
|
-
|
1165
|
-
|
1166
|
-
if (global.entodictonDebugBridge[0] == bridge.id && global.entodictonDebugBridge[1] == bridge.level) {
|
1167
|
-
debugger; // debug hierarchy hit
|
1168
|
-
}
|
1169
|
-
}
|
1170
|
-
|
1212
|
+
|
1213
|
+
debugBridge(bridge)
|
1171
1214
|
if (bridge.allowDups) {
|
1172
1215
|
if (bridges.find( (b) => b.id == bridge.id && b.level == bridge.level && b.bridge == bridge.bridge )) {
|
1173
1216
|
return;
|
@@ -1247,11 +1290,7 @@ class Config {
|
|
1247
1290
|
operator = Object.assign({}, objectOrPattern, { uuid: uuid || this._uuid })
|
1248
1291
|
}
|
1249
1292
|
|
1250
|
-
|
1251
|
-
if (operator.pattern === global.entodictonDebugOperator) {
|
1252
|
-
debugger; // debug operator hit
|
1253
|
-
}
|
1254
|
-
}
|
1293
|
+
debugOperator(operator)
|
1255
1294
|
|
1256
1295
|
if (operator.allowDups) {
|
1257
1296
|
if (operators.find( (o) => o.pattern == operator.pattern )) {
|
@@ -2722,6 +2761,8 @@ class Config {
|
|
2722
2761
|
more = _.cloneDeep(more.initConfig)
|
2723
2762
|
}
|
2724
2763
|
}
|
2764
|
+
debugConfigProps(more)
|
2765
|
+
|
2725
2766
|
if (hcps) {
|
2726
2767
|
handleCalculatedProps(this, more, addFirst)
|
2727
2768
|
applyUUID(more, this._uuid)
|
@@ -2818,6 +2859,7 @@ class Config {
|
|
2818
2859
|
}
|
2819
2860
|
}
|
2820
2861
|
}
|
2862
|
+
|
2821
2863
|
// console.log('key', key, 'XXX')
|
2822
2864
|
// console.log('more', JSON.stringify(more, null, 2))
|
2823
2865
|
if (addFirst) {
|
package/src/project.js
CHANGED
@@ -1,12 +1,32 @@
|
|
1
1
|
|
2
2
|
const project = (object, filter) => {
|
3
|
+
if (!object) {
|
4
|
+
return
|
5
|
+
}
|
6
|
+
|
3
7
|
let projection = {}
|
4
8
|
if (Array.isArray(filter)) {
|
5
9
|
if (Array.isArray(object)) {
|
6
10
|
return object.map( element => project(element, filter) )
|
7
11
|
} else {
|
8
|
-
for (
|
9
|
-
|
12
|
+
for (let properties of filter) {
|
13
|
+
if (typeof properties == 'object') {
|
14
|
+
debugger
|
15
|
+
const subfilterProperty = Object.keys(properties)[0]
|
16
|
+
oldValue = object[subfilterProperty]
|
17
|
+
if (Array.isArray(oldValue)) {
|
18
|
+
projection[subfilterProperty] = oldValue.map((v) => project(v, properties[subfilterProperty]))
|
19
|
+
} else {
|
20
|
+
projection[subfilterProperty] = project(oldValue, properties[subfilterProperty])
|
21
|
+
}
|
22
|
+
} else {
|
23
|
+
if (!Array.isArray(properties)) {
|
24
|
+
properties = [properties]
|
25
|
+
}
|
26
|
+
for (const property of properties) {
|
27
|
+
projection[property] = object[property]
|
28
|
+
}
|
29
|
+
}
|
10
30
|
}
|
11
31
|
}
|
12
32
|
} else if (typeof filter == 'object') {
|