@graffy/link 0.15.14 → 0.15.15
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/index.cjs +189 -58
- package/index.mjs +186 -59
- package/package.json +3 -2
package/index.cjs
CHANGED
|
@@ -19,63 +19,151 @@ var __spreadValues = (a, b) => {
|
|
|
19
19
|
};
|
|
20
20
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
21
|
var common = require("@graffy/common");
|
|
22
|
+
var debug = require("debug");
|
|
23
|
+
function _interopDefaultLegacy(e) {
|
|
24
|
+
return e && typeof e === "object" && "default" in e ? e : { "default": e };
|
|
25
|
+
}
|
|
26
|
+
var debug__default = /* @__PURE__ */ _interopDefaultLegacy(debug);
|
|
22
27
|
function linkGraph(rootGraph, defs) {
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
let version = rootGraph[0].version;
|
|
29
|
+
for (const { path, def } of defs) {
|
|
30
|
+
const braid = def.map(getKeyValues);
|
|
31
|
+
const strands = unbraid(braid);
|
|
32
|
+
const pathReqs = path.filter((key) => key[0] === "$").reduce((acc, key) => {
|
|
33
|
+
acc[key.slice(1)] = true;
|
|
34
|
+
return acc;
|
|
35
|
+
}, {});
|
|
36
|
+
outer:
|
|
37
|
+
for (const { value, vars, reqs } of strands) {
|
|
38
|
+
for (const req in reqs)
|
|
39
|
+
if (!(req in vars))
|
|
40
|
+
continue outer;
|
|
41
|
+
for (const req in pathReqs)
|
|
42
|
+
if (!(req in vars))
|
|
43
|
+
continue outer;
|
|
44
|
+
const realPath = makeRef(path, vars);
|
|
45
|
+
const realRef = makeRef(value, vars);
|
|
46
|
+
const node = { key: realPath.pop(), path: common.encodePath(realRef), version };
|
|
47
|
+
const [range] = common.splitRef(realRef);
|
|
48
|
+
if (range)
|
|
49
|
+
node.prefix = true;
|
|
50
|
+
let target = rootGraph;
|
|
51
|
+
do {
|
|
52
|
+
const key = realPath.shift();
|
|
53
|
+
const nextTarget = target[common.findFirst(target, key)];
|
|
54
|
+
if (!nextTarget || nextTarget.key !== key || nextTarget.end) {
|
|
55
|
+
realPath.unshift(key);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
target = nextTarget.path ? common.unwrap(rootGraph, nextTarget.path) : nextTarget.children;
|
|
59
|
+
} while (target && realPath.length);
|
|
60
|
+
if (!target)
|
|
61
|
+
return;
|
|
62
|
+
common.merge(target, realPath.length ? common.wrap([node], realPath, version) : [node]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
25
65
|
return rootGraph;
|
|
26
|
-
function
|
|
66
|
+
function getKeyValues(key) {
|
|
67
|
+
if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
|
|
68
|
+
return lookupValues(rootGraph, key.slice(2).split("."));
|
|
69
|
+
}
|
|
70
|
+
if (Array.isArray(key)) {
|
|
71
|
+
return unbraid(key.map(getKeyValues));
|
|
72
|
+
}
|
|
73
|
+
if (typeof key === "object" && key) {
|
|
74
|
+
const values = unbraid(Object.values(key).map(getKeyValues));
|
|
75
|
+
const keys = Object.keys(key);
|
|
76
|
+
return values.map(({ value, vars, reqs }) => ({
|
|
77
|
+
value: value.reduce((acc, val, i) => {
|
|
78
|
+
acc[keys[i]] = val;
|
|
79
|
+
return acc;
|
|
80
|
+
}, {}),
|
|
81
|
+
vars,
|
|
82
|
+
reqs
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
if (typeof key === "string" && key[0] === "$") {
|
|
86
|
+
return [{ value: key, vars: {}, reqs: { [key.slice(1)]: true } }];
|
|
87
|
+
}
|
|
88
|
+
return [{ value: key, vars: {}, reqs: {} }];
|
|
89
|
+
}
|
|
90
|
+
function lookupValues(graph, path, vars = {}) {
|
|
27
91
|
const [key, ...rest] = path;
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
node2
|
|
34
|
-
|
|
35
|
-
return;
|
|
92
|
+
if (key[0] === "$") {
|
|
93
|
+
return graph.flatMap((node2) => {
|
|
94
|
+
if (node2.end)
|
|
95
|
+
return [];
|
|
96
|
+
const newVars = __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: node2.key });
|
|
97
|
+
return recurse(node2, rest, newVars);
|
|
98
|
+
});
|
|
36
99
|
}
|
|
37
100
|
let node = graph[common.findFirst(graph, key)];
|
|
38
|
-
if (!node || node.key !== key || node.end)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
101
|
+
if (!node || node.key !== key || node.end)
|
|
102
|
+
return [];
|
|
103
|
+
return recurse(node, rest, vars);
|
|
104
|
+
}
|
|
105
|
+
function recurse(node, path, vars) {
|
|
106
|
+
if (!path.length)
|
|
107
|
+
return [{ value: node.value, vars, reqs: {} }];
|
|
108
|
+
if (node.children)
|
|
109
|
+
return lookupValues(node.children, path, vars);
|
|
110
|
+
if (node.path) {
|
|
111
|
+
const linked = common.unwrap(rootGraph, node.path);
|
|
112
|
+
if (Array.isArray(linked))
|
|
113
|
+
return lookupValues(linked, path, vars);
|
|
46
114
|
}
|
|
47
|
-
|
|
115
|
+
throw Error("link.no_children " + JSON.stringify(node));
|
|
48
116
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
117
|
+
}
|
|
118
|
+
function unbraid(braid) {
|
|
119
|
+
const [options, ...rest] = braid;
|
|
120
|
+
if (!rest.length) {
|
|
121
|
+
return options.map((option) => ({
|
|
122
|
+
value: [option.value],
|
|
123
|
+
vars: option.vars,
|
|
124
|
+
reqs: option.reqs
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
const strands = unbraid(rest);
|
|
128
|
+
return options.flatMap((option) => strands.filter((strand) => isCompatible(option.vars, strand.vars)).map((strand) => ({
|
|
129
|
+
value: [option.value, ...strand.value],
|
|
130
|
+
vars: __spreadValues(__spreadValues({}, option.vars), strand.vars),
|
|
131
|
+
reqs: __spreadValues(__spreadValues({}, option.reqs), strand.reqs)
|
|
132
|
+
})));
|
|
133
|
+
}
|
|
134
|
+
function isCompatible(oVars, sVars) {
|
|
135
|
+
for (const name in oVars) {
|
|
136
|
+
if (name in sVars && oVars[name] !== sVars[name])
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
function makeRef(def, vars) {
|
|
142
|
+
function getValue(key) {
|
|
143
|
+
if (typeof key !== "string")
|
|
63
144
|
return key;
|
|
145
|
+
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
146
|
+
}
|
|
147
|
+
function replacePlaceholders(key) {
|
|
148
|
+
if (Array.isArray(key)) {
|
|
149
|
+
return key.map(replacePlaceholders);
|
|
150
|
+
}
|
|
151
|
+
if (typeof key === "object" && key) {
|
|
152
|
+
const result = {};
|
|
153
|
+
for (const prop in key)
|
|
154
|
+
result[prop] = replacePlaceholders(key[prop]);
|
|
155
|
+
return result;
|
|
64
156
|
}
|
|
65
|
-
|
|
66
|
-
return ref;
|
|
157
|
+
return getValue(key);
|
|
67
158
|
}
|
|
159
|
+
const ref = def.map(replacePlaceholders);
|
|
160
|
+
return ref;
|
|
68
161
|
}
|
|
69
162
|
function prepQueryLinks(rootQuery, defs) {
|
|
70
163
|
return defs.flatMap(({ path, def }) => prepQueryDef(rootQuery, path, def));
|
|
71
164
|
function prepQueryDef(query, path, def, vars = {}, version = 0) {
|
|
72
165
|
var _a;
|
|
73
|
-
|
|
74
|
-
if (rest.length === 0) {
|
|
75
|
-
const ix = common.findFirst(query, key);
|
|
76
|
-
if (((_a = query[ix]) == null ? void 0 : _a.key) !== key)
|
|
77
|
-
return [];
|
|
78
|
-
const [{ children: subQuery }] = query.splice(ix, 1);
|
|
166
|
+
function addDefQuery(subQuery) {
|
|
79
167
|
common.add(rootQuery, getDefQuery(def, vars, version));
|
|
80
168
|
const [range, filter] = common.splitRef(def);
|
|
81
169
|
if (range && subQuery.length) {
|
|
@@ -95,23 +183,54 @@ function prepQueryLinks(rootQuery, defs) {
|
|
|
95
183
|
def: def2
|
|
96
184
|
}));
|
|
97
185
|
}
|
|
186
|
+
function makePager(pager) {
|
|
187
|
+
Object.defineProperty(pager, "toString", { value: () => key });
|
|
188
|
+
return pager;
|
|
189
|
+
}
|
|
190
|
+
const [key, ...rest] = path;
|
|
191
|
+
if (rest.length === 0) {
|
|
192
|
+
if (key[0] === "$") {
|
|
193
|
+
return query.splice(0).flatMap((node) => {
|
|
194
|
+
vars[key.slice(1)] = makePager(common.decodeArgs(node));
|
|
195
|
+
return addDefQuery(node.children);
|
|
196
|
+
});
|
|
197
|
+
} else {
|
|
198
|
+
const ix = common.findFirst(query, key);
|
|
199
|
+
if (((_a = query[ix]) == null ? void 0 : _a.key) !== key)
|
|
200
|
+
return [];
|
|
201
|
+
const [{ children: subQuery }] = query.splice(ix, 1);
|
|
202
|
+
return addDefQuery(subQuery);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
98
205
|
let used = [];
|
|
99
|
-
if (key[0]
|
|
100
|
-
const node = query[common.findFirst(query, key)];
|
|
101
|
-
if (!node || node.key !== key || !node.children)
|
|
102
|
-
return [];
|
|
103
|
-
used = prepQueryDef(node.children, rest, def, vars, node.version);
|
|
104
|
-
used = prefixKey(used, node.key);
|
|
105
|
-
} else {
|
|
206
|
+
if (key[0] === "$") {
|
|
106
207
|
for (const node of query) {
|
|
107
208
|
if (!common.isBranch(node))
|
|
108
209
|
continue;
|
|
109
|
-
let usedHere
|
|
110
|
-
|
|
111
|
-
|
|
210
|
+
let usedHere;
|
|
211
|
+
if (node.prefix) {
|
|
212
|
+
usedHere = node.children.flatMap((subNode) => {
|
|
213
|
+
const pager = makePager(common.decodeArgs(subNode));
|
|
214
|
+
return prefixKey(prepQueryDef(subNode.children, rest, def, __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: [node.key, pager] }), node.version), key);
|
|
215
|
+
});
|
|
216
|
+
} else {
|
|
217
|
+
usedHere = prepQueryDef(node.children, rest, def, __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: node.key }), node.version);
|
|
218
|
+
}
|
|
112
219
|
usedHere = prefixKey(usedHere, node.key);
|
|
113
220
|
used = used.concat(usedHere);
|
|
114
221
|
}
|
|
222
|
+
} else {
|
|
223
|
+
const node = query[common.findFirst(query, key)];
|
|
224
|
+
if (!node || node.key !== key || !node.children)
|
|
225
|
+
return [];
|
|
226
|
+
used = prepQueryDef(node.children, rest, def, vars, node.version);
|
|
227
|
+
used = prefixKey(used, node.key);
|
|
228
|
+
}
|
|
229
|
+
for (let i = 0; i < query.length; i++) {
|
|
230
|
+
if (query[i].children && query[i].children.length === 0) {
|
|
231
|
+
query.splice(i, 1);
|
|
232
|
+
i--;
|
|
233
|
+
}
|
|
115
234
|
}
|
|
116
235
|
return used;
|
|
117
236
|
}
|
|
@@ -121,7 +240,7 @@ function getDefQuery(def, vars, version) {
|
|
|
121
240
|
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
122
241
|
}
|
|
123
242
|
function getPath(template) {
|
|
124
|
-
return template.split(".").
|
|
243
|
+
return template.split(".").flatMap(getValue);
|
|
125
244
|
}
|
|
126
245
|
const defQuery = [];
|
|
127
246
|
function addDefQueries(key) {
|
|
@@ -141,14 +260,16 @@ function getDefQuery(def, vars, version) {
|
|
|
141
260
|
}
|
|
142
261
|
function prepareDef(def, vars) {
|
|
143
262
|
function getValue(key) {
|
|
263
|
+
if (typeof key !== "string")
|
|
264
|
+
return key;
|
|
144
265
|
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
145
266
|
}
|
|
146
267
|
function replacePlaceholders(key) {
|
|
147
268
|
if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
|
|
148
|
-
return "$$" + key.slice(2).split(".").
|
|
269
|
+
return "$$" + key.slice(2).split(".").flatMap(getValue).join(".");
|
|
149
270
|
}
|
|
150
271
|
if (Array.isArray(key)) {
|
|
151
|
-
return key.
|
|
272
|
+
return key.flatMap(replacePlaceholders);
|
|
152
273
|
}
|
|
153
274
|
if (typeof key === "object" && key) {
|
|
154
275
|
const result = {};
|
|
@@ -158,8 +279,10 @@ function prepareDef(def, vars) {
|
|
|
158
279
|
}
|
|
159
280
|
return getValue(key);
|
|
160
281
|
}
|
|
161
|
-
|
|
282
|
+
const ref = def.flatMap(replacePlaceholders);
|
|
283
|
+
return ref;
|
|
162
284
|
}
|
|
285
|
+
const log = debug__default["default"]("graffy:link");
|
|
163
286
|
var index = (defs) => (store) => {
|
|
164
287
|
const prefix = store.path;
|
|
165
288
|
const defEntries = Object.entries(defs).map(([prop, def]) => ({
|
|
@@ -169,10 +292,18 @@ var index = (defs) => (store) => {
|
|
|
169
292
|
store.on("read", async (query, options, next) => {
|
|
170
293
|
const unwrappedQuery = clone(common.unwrap(query, prefix));
|
|
171
294
|
const usedDefs = prepQueryLinks(unwrappedQuery, defEntries);
|
|
295
|
+
if (!usedDefs.length)
|
|
296
|
+
return next(query, options);
|
|
172
297
|
const result = await next(common.wrap(unwrappedQuery, prefix), options);
|
|
298
|
+
const version = result[0].version;
|
|
173
299
|
const unwrappedResult = common.unwrap(result, prefix);
|
|
174
|
-
|
|
175
|
-
|
|
300
|
+
common.add(unwrappedQuery, common.unwrap(query, prefix));
|
|
301
|
+
log("finalizing", prefix, unwrappedQuery);
|
|
302
|
+
const finalizedResult = common.finalize(unwrappedResult, unwrappedQuery, version);
|
|
303
|
+
log("beforeAddingLinks", prefix, finalizedResult);
|
|
304
|
+
linkGraph(finalizedResult, usedDefs);
|
|
305
|
+
log("afterAddingLinks", prefix, finalizedResult);
|
|
306
|
+
return common.wrap(finalizedResult, prefix, version);
|
|
176
307
|
});
|
|
177
308
|
};
|
|
178
309
|
function clone(tree) {
|
package/index.mjs
CHANGED
|
@@ -17,64 +17,148 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
return a;
|
|
18
18
|
};
|
|
19
19
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
-
import {
|
|
20
|
+
import { encodePath, splitRef, findFirst, unwrap, merge, wrap, decodeArgs, isBranch, add, wrapValue, finalize } from "@graffy/common";
|
|
21
|
+
import debug from "debug";
|
|
21
22
|
function linkGraph(rootGraph, defs) {
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
let version = rootGraph[0].version;
|
|
24
|
+
for (const { path, def } of defs) {
|
|
25
|
+
const braid = def.map(getKeyValues);
|
|
26
|
+
const strands = unbraid(braid);
|
|
27
|
+
const pathReqs = path.filter((key) => key[0] === "$").reduce((acc, key) => {
|
|
28
|
+
acc[key.slice(1)] = true;
|
|
29
|
+
return acc;
|
|
30
|
+
}, {});
|
|
31
|
+
outer:
|
|
32
|
+
for (const { value, vars, reqs } of strands) {
|
|
33
|
+
for (const req in reqs)
|
|
34
|
+
if (!(req in vars))
|
|
35
|
+
continue outer;
|
|
36
|
+
for (const req in pathReqs)
|
|
37
|
+
if (!(req in vars))
|
|
38
|
+
continue outer;
|
|
39
|
+
const realPath = makeRef(path, vars);
|
|
40
|
+
const realRef = makeRef(value, vars);
|
|
41
|
+
const node = { key: realPath.pop(), path: encodePath(realRef), version };
|
|
42
|
+
const [range] = splitRef(realRef);
|
|
43
|
+
if (range)
|
|
44
|
+
node.prefix = true;
|
|
45
|
+
let target = rootGraph;
|
|
46
|
+
do {
|
|
47
|
+
const key = realPath.shift();
|
|
48
|
+
const nextTarget = target[findFirst(target, key)];
|
|
49
|
+
if (!nextTarget || nextTarget.key !== key || nextTarget.end) {
|
|
50
|
+
realPath.unshift(key);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
target = nextTarget.path ? unwrap(rootGraph, nextTarget.path) : nextTarget.children;
|
|
54
|
+
} while (target && realPath.length);
|
|
55
|
+
if (!target)
|
|
56
|
+
return;
|
|
57
|
+
merge(target, realPath.length ? wrap([node], realPath, version) : [node]);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
24
60
|
return rootGraph;
|
|
25
|
-
function
|
|
61
|
+
function getKeyValues(key) {
|
|
62
|
+
if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
|
|
63
|
+
return lookupValues(rootGraph, key.slice(2).split("."));
|
|
64
|
+
}
|
|
65
|
+
if (Array.isArray(key)) {
|
|
66
|
+
return unbraid(key.map(getKeyValues));
|
|
67
|
+
}
|
|
68
|
+
if (typeof key === "object" && key) {
|
|
69
|
+
const values = unbraid(Object.values(key).map(getKeyValues));
|
|
70
|
+
const keys = Object.keys(key);
|
|
71
|
+
return values.map(({ value, vars, reqs }) => ({
|
|
72
|
+
value: value.reduce((acc, val, i) => {
|
|
73
|
+
acc[keys[i]] = val;
|
|
74
|
+
return acc;
|
|
75
|
+
}, {}),
|
|
76
|
+
vars,
|
|
77
|
+
reqs
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
if (typeof key === "string" && key[0] === "$") {
|
|
81
|
+
return [{ value: key, vars: {}, reqs: { [key.slice(1)]: true } }];
|
|
82
|
+
}
|
|
83
|
+
return [{ value: key, vars: {}, reqs: {} }];
|
|
84
|
+
}
|
|
85
|
+
function lookupValues(graph, path, vars = {}) {
|
|
26
86
|
const [key, ...rest] = path;
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
node2
|
|
33
|
-
|
|
34
|
-
return;
|
|
87
|
+
if (key[0] === "$") {
|
|
88
|
+
return graph.flatMap((node2) => {
|
|
89
|
+
if (node2.end)
|
|
90
|
+
return [];
|
|
91
|
+
const newVars = __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: node2.key });
|
|
92
|
+
return recurse(node2, rest, newVars);
|
|
93
|
+
});
|
|
35
94
|
}
|
|
36
95
|
let node = graph[findFirst(graph, key)];
|
|
37
|
-
if (!node || node.key !== key || node.end)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
96
|
+
if (!node || node.key !== key || node.end)
|
|
97
|
+
return [];
|
|
98
|
+
return recurse(node, rest, vars);
|
|
99
|
+
}
|
|
100
|
+
function recurse(node, path, vars) {
|
|
101
|
+
if (!path.length)
|
|
102
|
+
return [{ value: node.value, vars, reqs: {} }];
|
|
103
|
+
if (node.children)
|
|
104
|
+
return lookupValues(node.children, path, vars);
|
|
105
|
+
if (node.path) {
|
|
106
|
+
const linked = unwrap(rootGraph, node.path);
|
|
107
|
+
if (Array.isArray(linked))
|
|
108
|
+
return lookupValues(linked, path, vars);
|
|
45
109
|
}
|
|
46
|
-
|
|
110
|
+
throw Error("link.no_children " + JSON.stringify(node));
|
|
47
111
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
112
|
+
}
|
|
113
|
+
function unbraid(braid) {
|
|
114
|
+
const [options, ...rest] = braid;
|
|
115
|
+
if (!rest.length) {
|
|
116
|
+
return options.map((option) => ({
|
|
117
|
+
value: [option.value],
|
|
118
|
+
vars: option.vars,
|
|
119
|
+
reqs: option.reqs
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
const strands = unbraid(rest);
|
|
123
|
+
return options.flatMap((option) => strands.filter((strand) => isCompatible(option.vars, strand.vars)).map((strand) => ({
|
|
124
|
+
value: [option.value, ...strand.value],
|
|
125
|
+
vars: __spreadValues(__spreadValues({}, option.vars), strand.vars),
|
|
126
|
+
reqs: __spreadValues(__spreadValues({}, option.reqs), strand.reqs)
|
|
127
|
+
})));
|
|
128
|
+
}
|
|
129
|
+
function isCompatible(oVars, sVars) {
|
|
130
|
+
for (const name in oVars) {
|
|
131
|
+
if (name in sVars && oVars[name] !== sVars[name])
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
function makeRef(def, vars) {
|
|
137
|
+
function getValue(key) {
|
|
138
|
+
if (typeof key !== "string")
|
|
62
139
|
return key;
|
|
140
|
+
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
141
|
+
}
|
|
142
|
+
function replacePlaceholders(key) {
|
|
143
|
+
if (Array.isArray(key)) {
|
|
144
|
+
return key.map(replacePlaceholders);
|
|
63
145
|
}
|
|
64
|
-
|
|
65
|
-
|
|
146
|
+
if (typeof key === "object" && key) {
|
|
147
|
+
const result = {};
|
|
148
|
+
for (const prop in key)
|
|
149
|
+
result[prop] = replacePlaceholders(key[prop]);
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
return getValue(key);
|
|
66
153
|
}
|
|
154
|
+
const ref = def.map(replacePlaceholders);
|
|
155
|
+
return ref;
|
|
67
156
|
}
|
|
68
157
|
function prepQueryLinks(rootQuery, defs) {
|
|
69
158
|
return defs.flatMap(({ path, def }) => prepQueryDef(rootQuery, path, def));
|
|
70
159
|
function prepQueryDef(query, path, def, vars = {}, version = 0) {
|
|
71
160
|
var _a;
|
|
72
|
-
|
|
73
|
-
if (rest.length === 0) {
|
|
74
|
-
const ix = findFirst(query, key);
|
|
75
|
-
if (((_a = query[ix]) == null ? void 0 : _a.key) !== key)
|
|
76
|
-
return [];
|
|
77
|
-
const [{ children: subQuery }] = query.splice(ix, 1);
|
|
161
|
+
function addDefQuery(subQuery) {
|
|
78
162
|
add(rootQuery, getDefQuery(def, vars, version));
|
|
79
163
|
const [range, filter] = splitRef(def);
|
|
80
164
|
if (range && subQuery.length) {
|
|
@@ -94,23 +178,54 @@ function prepQueryLinks(rootQuery, defs) {
|
|
|
94
178
|
def: def2
|
|
95
179
|
}));
|
|
96
180
|
}
|
|
181
|
+
function makePager(pager) {
|
|
182
|
+
Object.defineProperty(pager, "toString", { value: () => key });
|
|
183
|
+
return pager;
|
|
184
|
+
}
|
|
185
|
+
const [key, ...rest] = path;
|
|
186
|
+
if (rest.length === 0) {
|
|
187
|
+
if (key[0] === "$") {
|
|
188
|
+
return query.splice(0).flatMap((node) => {
|
|
189
|
+
vars[key.slice(1)] = makePager(decodeArgs(node));
|
|
190
|
+
return addDefQuery(node.children);
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
const ix = findFirst(query, key);
|
|
194
|
+
if (((_a = query[ix]) == null ? void 0 : _a.key) !== key)
|
|
195
|
+
return [];
|
|
196
|
+
const [{ children: subQuery }] = query.splice(ix, 1);
|
|
197
|
+
return addDefQuery(subQuery);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
97
200
|
let used = [];
|
|
98
|
-
if (key[0]
|
|
99
|
-
const node = query[findFirst(query, key)];
|
|
100
|
-
if (!node || node.key !== key || !node.children)
|
|
101
|
-
return [];
|
|
102
|
-
used = prepQueryDef(node.children, rest, def, vars, node.version);
|
|
103
|
-
used = prefixKey(used, node.key);
|
|
104
|
-
} else {
|
|
201
|
+
if (key[0] === "$") {
|
|
105
202
|
for (const node of query) {
|
|
106
203
|
if (!isBranch(node))
|
|
107
204
|
continue;
|
|
108
|
-
let usedHere
|
|
109
|
-
|
|
110
|
-
|
|
205
|
+
let usedHere;
|
|
206
|
+
if (node.prefix) {
|
|
207
|
+
usedHere = node.children.flatMap((subNode) => {
|
|
208
|
+
const pager = makePager(decodeArgs(subNode));
|
|
209
|
+
return prefixKey(prepQueryDef(subNode.children, rest, def, __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: [node.key, pager] }), node.version), key);
|
|
210
|
+
});
|
|
211
|
+
} else {
|
|
212
|
+
usedHere = prepQueryDef(node.children, rest, def, __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: node.key }), node.version);
|
|
213
|
+
}
|
|
111
214
|
usedHere = prefixKey(usedHere, node.key);
|
|
112
215
|
used = used.concat(usedHere);
|
|
113
216
|
}
|
|
217
|
+
} else {
|
|
218
|
+
const node = query[findFirst(query, key)];
|
|
219
|
+
if (!node || node.key !== key || !node.children)
|
|
220
|
+
return [];
|
|
221
|
+
used = prepQueryDef(node.children, rest, def, vars, node.version);
|
|
222
|
+
used = prefixKey(used, node.key);
|
|
223
|
+
}
|
|
224
|
+
for (let i = 0; i < query.length; i++) {
|
|
225
|
+
if (query[i].children && query[i].children.length === 0) {
|
|
226
|
+
query.splice(i, 1);
|
|
227
|
+
i--;
|
|
228
|
+
}
|
|
114
229
|
}
|
|
115
230
|
return used;
|
|
116
231
|
}
|
|
@@ -120,7 +235,7 @@ function getDefQuery(def, vars, version) {
|
|
|
120
235
|
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
121
236
|
}
|
|
122
237
|
function getPath(template) {
|
|
123
|
-
return template.split(".").
|
|
238
|
+
return template.split(".").flatMap(getValue);
|
|
124
239
|
}
|
|
125
240
|
const defQuery = [];
|
|
126
241
|
function addDefQueries(key) {
|
|
@@ -140,14 +255,16 @@ function getDefQuery(def, vars, version) {
|
|
|
140
255
|
}
|
|
141
256
|
function prepareDef(def, vars) {
|
|
142
257
|
function getValue(key) {
|
|
258
|
+
if (typeof key !== "string")
|
|
259
|
+
return key;
|
|
143
260
|
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
144
261
|
}
|
|
145
262
|
function replacePlaceholders(key) {
|
|
146
263
|
if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
|
|
147
|
-
return "$$" + key.slice(2).split(".").
|
|
264
|
+
return "$$" + key.slice(2).split(".").flatMap(getValue).join(".");
|
|
148
265
|
}
|
|
149
266
|
if (Array.isArray(key)) {
|
|
150
|
-
return key.
|
|
267
|
+
return key.flatMap(replacePlaceholders);
|
|
151
268
|
}
|
|
152
269
|
if (typeof key === "object" && key) {
|
|
153
270
|
const result = {};
|
|
@@ -157,8 +274,10 @@ function prepareDef(def, vars) {
|
|
|
157
274
|
}
|
|
158
275
|
return getValue(key);
|
|
159
276
|
}
|
|
160
|
-
|
|
277
|
+
const ref = def.flatMap(replacePlaceholders);
|
|
278
|
+
return ref;
|
|
161
279
|
}
|
|
280
|
+
const log = debug("graffy:link");
|
|
162
281
|
var index = (defs) => (store) => {
|
|
163
282
|
const prefix = store.path;
|
|
164
283
|
const defEntries = Object.entries(defs).map(([prop, def]) => ({
|
|
@@ -168,10 +287,18 @@ var index = (defs) => (store) => {
|
|
|
168
287
|
store.on("read", async (query, options, next) => {
|
|
169
288
|
const unwrappedQuery = clone(unwrap(query, prefix));
|
|
170
289
|
const usedDefs = prepQueryLinks(unwrappedQuery, defEntries);
|
|
290
|
+
if (!usedDefs.length)
|
|
291
|
+
return next(query, options);
|
|
171
292
|
const result = await next(wrap(unwrappedQuery, prefix), options);
|
|
293
|
+
const version = result[0].version;
|
|
172
294
|
const unwrappedResult = unwrap(result, prefix);
|
|
173
|
-
|
|
174
|
-
|
|
295
|
+
add(unwrappedQuery, unwrap(query, prefix));
|
|
296
|
+
log("finalizing", prefix, unwrappedQuery);
|
|
297
|
+
const finalizedResult = finalize(unwrappedResult, unwrappedQuery, version);
|
|
298
|
+
log("beforeAddingLinks", prefix, finalizedResult);
|
|
299
|
+
linkGraph(finalizedResult, usedDefs);
|
|
300
|
+
log("afterAddingLinks", prefix, finalizedResult);
|
|
301
|
+
return wrap(finalizedResult, prefix, version);
|
|
175
302
|
});
|
|
176
303
|
};
|
|
177
304
|
function clone(tree) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graffy/link",
|
|
3
3
|
"description": "Graffy module for constructing links using an intuitive, declarative notation.",
|
|
4
4
|
"author": "aravind (https://github.com/aravindet)",
|
|
5
|
-
"version": "0.15.
|
|
5
|
+
"version": "0.15.15",
|
|
6
6
|
"main": "./index.cjs",
|
|
7
7
|
"exports": {
|
|
8
8
|
"import": "./index.mjs",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"license": "Apache-2.0",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@graffy/common": "0.15.
|
|
19
|
+
"@graffy/common": "0.15.15",
|
|
20
|
+
"debug": "^4.3.2"
|
|
20
21
|
}
|
|
21
22
|
}
|