@graffy/link 0.15.15-alpha.1 → 0.15.16
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 +173 -69
- package/index.mjs +170 -70
- package/package.json +3 -2
package/index.cjs
CHANGED
|
@@ -19,82 +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
|
|
27
|
-
if (
|
|
28
|
-
return
|
|
29
|
-
if (node.path) {
|
|
30
|
-
const linkedNode = common.unwrap(rootGraph, node.path);
|
|
31
|
-
if (Array.isArray(linkedNode))
|
|
32
|
-
return linkedNode;
|
|
66
|
+
function getKeyValues(key) {
|
|
67
|
+
if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
|
|
68
|
+
return lookupValues(rootGraph, key.slice(2).split("."));
|
|
33
69
|
}
|
|
34
|
-
|
|
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: {} }];
|
|
35
89
|
}
|
|
36
|
-
function
|
|
90
|
+
function lookupValues(graph, path, vars = {}) {
|
|
37
91
|
const [key, ...rest] = path;
|
|
38
|
-
if (rest.length === 0) {
|
|
39
|
-
const ref = makeRef(def, vars);
|
|
40
|
-
const [range] = common.splitRef(def);
|
|
41
|
-
const node2 = { key, path: common.encodePath(ref), version };
|
|
42
|
-
if (range)
|
|
43
|
-
node2.prefix = true;
|
|
44
|
-
common.merge(graph, [node2]);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
92
|
if (key[0] === "$") {
|
|
48
|
-
|
|
93
|
+
return graph.flatMap((node2) => {
|
|
49
94
|
if (node2.end)
|
|
50
|
-
|
|
95
|
+
return [];
|
|
51
96
|
const newVars = __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: node2.key });
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
return;
|
|
97
|
+
return recurse(node2, rest, newVars);
|
|
98
|
+
});
|
|
55
99
|
}
|
|
56
100
|
let node = graph[common.findFirst(graph, key)];
|
|
57
|
-
if (!node || node.key !== key || node.end)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
delete node.value;
|
|
61
|
-
node.children = [];
|
|
62
|
-
}
|
|
63
|
-
return linkGraphDef(findChildren(node), rest, def, vars, node.version);
|
|
101
|
+
if (!node || node.key !== key || node.end)
|
|
102
|
+
return [];
|
|
103
|
+
return recurse(node, rest, vars);
|
|
64
104
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
return
|
|
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);
|
|
68
114
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
115
|
+
throw Error("link.no_children " + JSON.stringify(node));
|
|
116
|
+
}
|
|
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")
|
|
82
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);
|
|
83
150
|
}
|
|
84
|
-
|
|
85
|
-
|
|
151
|
+
if (typeof key === "object" && key) {
|
|
152
|
+
const result = {};
|
|
153
|
+
for (const prop in key)
|
|
154
|
+
result[prop] = replacePlaceholders(key[prop]);
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
return getValue(key);
|
|
86
158
|
}
|
|
159
|
+
const ref = def.map(replacePlaceholders);
|
|
160
|
+
return ref;
|
|
87
161
|
}
|
|
88
162
|
function prepQueryLinks(rootQuery, defs) {
|
|
89
163
|
return defs.flatMap(({ path, def }) => prepQueryDef(rootQuery, path, def));
|
|
90
164
|
function prepQueryDef(query, path, def, vars = {}, version = 0) {
|
|
91
165
|
var _a;
|
|
92
|
-
|
|
93
|
-
if (rest.length === 0) {
|
|
94
|
-
const ix = common.findFirst(query, key);
|
|
95
|
-
if (((_a = query[ix]) == null ? void 0 : _a.key) !== key)
|
|
96
|
-
return [];
|
|
97
|
-
const [{ children: subQuery }] = query.splice(ix, 1);
|
|
166
|
+
function addDefQuery(subQuery) {
|
|
98
167
|
common.add(rootQuery, getDefQuery(def, vars, version));
|
|
99
168
|
const [range, filter] = common.splitRef(def);
|
|
100
169
|
if (range && subQuery.length) {
|
|
@@ -114,23 +183,34 @@ function prepQueryLinks(rootQuery, defs) {
|
|
|
114
183
|
def: def2
|
|
115
184
|
}));
|
|
116
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
|
+
}
|
|
117
205
|
let used = [];
|
|
118
|
-
if (key[0]
|
|
119
|
-
const node = query[common.findFirst(query, key)];
|
|
120
|
-
if (!node || node.key !== key || !node.children)
|
|
121
|
-
return [];
|
|
122
|
-
used = prepQueryDef(node.children, rest, def, vars, node.version);
|
|
123
|
-
used = prefixKey(used, node.key);
|
|
124
|
-
} else {
|
|
206
|
+
if (key[0] === "$") {
|
|
125
207
|
for (const node of query) {
|
|
126
208
|
if (!common.isBranch(node))
|
|
127
209
|
continue;
|
|
128
210
|
let usedHere;
|
|
129
211
|
if (node.prefix) {
|
|
130
|
-
const pageToString = () => key;
|
|
131
212
|
usedHere = node.children.flatMap((subNode) => {
|
|
132
|
-
const pager = common.decodeArgs(subNode);
|
|
133
|
-
Object.defineProperty(pager, "toString", { value: pageToString });
|
|
213
|
+
const pager = makePager(common.decodeArgs(subNode));
|
|
134
214
|
return prefixKey(prepQueryDef(subNode.children, rest, def, __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: [node.key, pager] }), node.version), key);
|
|
135
215
|
});
|
|
136
216
|
} else {
|
|
@@ -139,6 +219,18 @@ function prepQueryLinks(rootQuery, defs) {
|
|
|
139
219
|
usedHere = prefixKey(usedHere, node.key);
|
|
140
220
|
used = used.concat(usedHere);
|
|
141
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
|
+
}
|
|
142
234
|
}
|
|
143
235
|
return used;
|
|
144
236
|
}
|
|
@@ -168,6 +260,8 @@ function getDefQuery(def, vars, version) {
|
|
|
168
260
|
}
|
|
169
261
|
function prepareDef(def, vars) {
|
|
170
262
|
function getValue(key) {
|
|
263
|
+
if (typeof key !== "string")
|
|
264
|
+
return key;
|
|
171
265
|
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
172
266
|
}
|
|
173
267
|
function replacePlaceholders(key) {
|
|
@@ -185,8 +279,10 @@ function prepareDef(def, vars) {
|
|
|
185
279
|
}
|
|
186
280
|
return getValue(key);
|
|
187
281
|
}
|
|
188
|
-
|
|
282
|
+
const ref = def.flatMap(replacePlaceholders);
|
|
283
|
+
return ref;
|
|
189
284
|
}
|
|
285
|
+
const log = debug__default["default"]("graffy:link");
|
|
190
286
|
var index = (defs) => (store) => {
|
|
191
287
|
const prefix = store.path;
|
|
192
288
|
const defEntries = Object.entries(defs).map(([prop, def]) => ({
|
|
@@ -196,10 +292,18 @@ var index = (defs) => (store) => {
|
|
|
196
292
|
store.on("read", async (query, options, next) => {
|
|
197
293
|
const unwrappedQuery = clone(common.unwrap(query, prefix));
|
|
198
294
|
const usedDefs = prepQueryLinks(unwrappedQuery, defEntries);
|
|
295
|
+
if (!usedDefs.length)
|
|
296
|
+
return next(query, options);
|
|
199
297
|
const result = await next(common.wrap(unwrappedQuery, prefix), options);
|
|
298
|
+
const version = result[0].version;
|
|
200
299
|
const unwrappedResult = common.unwrap(result, prefix);
|
|
201
|
-
|
|
202
|
-
|
|
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);
|
|
203
307
|
});
|
|
204
308
|
};
|
|
205
309
|
function clone(tree) {
|
package/index.mjs
CHANGED
|
@@ -17,83 +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
|
|
26
|
-
if (
|
|
27
|
-
return
|
|
28
|
-
if (node.path) {
|
|
29
|
-
const linkedNode = unwrap(rootGraph, node.path);
|
|
30
|
-
if (Array.isArray(linkedNode))
|
|
31
|
-
return linkedNode;
|
|
61
|
+
function getKeyValues(key) {
|
|
62
|
+
if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
|
|
63
|
+
return lookupValues(rootGraph, key.slice(2).split("."));
|
|
32
64
|
}
|
|
33
|
-
|
|
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: {} }];
|
|
34
84
|
}
|
|
35
|
-
function
|
|
85
|
+
function lookupValues(graph, path, vars = {}) {
|
|
36
86
|
const [key, ...rest] = path;
|
|
37
|
-
if (rest.length === 0) {
|
|
38
|
-
const ref = makeRef(def, vars);
|
|
39
|
-
const [range] = splitRef(def);
|
|
40
|
-
const node2 = { key, path: encodePath(ref), version };
|
|
41
|
-
if (range)
|
|
42
|
-
node2.prefix = true;
|
|
43
|
-
merge(graph, [node2]);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
87
|
if (key[0] === "$") {
|
|
47
|
-
|
|
88
|
+
return graph.flatMap((node2) => {
|
|
48
89
|
if (node2.end)
|
|
49
|
-
|
|
90
|
+
return [];
|
|
50
91
|
const newVars = __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: node2.key });
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
return;
|
|
92
|
+
return recurse(node2, rest, newVars);
|
|
93
|
+
});
|
|
54
94
|
}
|
|
55
95
|
let node = graph[findFirst(graph, key)];
|
|
56
|
-
if (!node || node.key !== key || node.end)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
delete node.value;
|
|
60
|
-
node.children = [];
|
|
61
|
-
}
|
|
62
|
-
return linkGraphDef(findChildren(node), rest, def, vars, node.version);
|
|
96
|
+
if (!node || node.key !== key || node.end)
|
|
97
|
+
return [];
|
|
98
|
+
return recurse(node, rest, vars);
|
|
63
99
|
}
|
|
64
|
-
function
|
|
65
|
-
|
|
66
|
-
return
|
|
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);
|
|
67
109
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
110
|
+
throw Error("link.no_children " + JSON.stringify(node));
|
|
111
|
+
}
|
|
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")
|
|
81
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);
|
|
82
145
|
}
|
|
83
|
-
|
|
84
|
-
|
|
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);
|
|
85
153
|
}
|
|
154
|
+
const ref = def.map(replacePlaceholders);
|
|
155
|
+
return ref;
|
|
86
156
|
}
|
|
87
157
|
function prepQueryLinks(rootQuery, defs) {
|
|
88
158
|
return defs.flatMap(({ path, def }) => prepQueryDef(rootQuery, path, def));
|
|
89
159
|
function prepQueryDef(query, path, def, vars = {}, version = 0) {
|
|
90
160
|
var _a;
|
|
91
|
-
|
|
92
|
-
if (rest.length === 0) {
|
|
93
|
-
const ix = findFirst(query, key);
|
|
94
|
-
if (((_a = query[ix]) == null ? void 0 : _a.key) !== key)
|
|
95
|
-
return [];
|
|
96
|
-
const [{ children: subQuery }] = query.splice(ix, 1);
|
|
161
|
+
function addDefQuery(subQuery) {
|
|
97
162
|
add(rootQuery, getDefQuery(def, vars, version));
|
|
98
163
|
const [range, filter] = splitRef(def);
|
|
99
164
|
if (range && subQuery.length) {
|
|
@@ -113,23 +178,34 @@ function prepQueryLinks(rootQuery, defs) {
|
|
|
113
178
|
def: def2
|
|
114
179
|
}));
|
|
115
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
|
+
}
|
|
116
200
|
let used = [];
|
|
117
|
-
if (key[0]
|
|
118
|
-
const node = query[findFirst(query, key)];
|
|
119
|
-
if (!node || node.key !== key || !node.children)
|
|
120
|
-
return [];
|
|
121
|
-
used = prepQueryDef(node.children, rest, def, vars, node.version);
|
|
122
|
-
used = prefixKey(used, node.key);
|
|
123
|
-
} else {
|
|
201
|
+
if (key[0] === "$") {
|
|
124
202
|
for (const node of query) {
|
|
125
203
|
if (!isBranch(node))
|
|
126
204
|
continue;
|
|
127
205
|
let usedHere;
|
|
128
206
|
if (node.prefix) {
|
|
129
|
-
const pageToString = () => key;
|
|
130
207
|
usedHere = node.children.flatMap((subNode) => {
|
|
131
|
-
const pager = decodeArgs(subNode);
|
|
132
|
-
Object.defineProperty(pager, "toString", { value: pageToString });
|
|
208
|
+
const pager = makePager(decodeArgs(subNode));
|
|
133
209
|
return prefixKey(prepQueryDef(subNode.children, rest, def, __spreadProps(__spreadValues({}, vars), { [key.slice(1)]: [node.key, pager] }), node.version), key);
|
|
134
210
|
});
|
|
135
211
|
} else {
|
|
@@ -138,6 +214,18 @@ function prepQueryLinks(rootQuery, defs) {
|
|
|
138
214
|
usedHere = prefixKey(usedHere, node.key);
|
|
139
215
|
used = used.concat(usedHere);
|
|
140
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
|
+
}
|
|
141
229
|
}
|
|
142
230
|
return used;
|
|
143
231
|
}
|
|
@@ -167,6 +255,8 @@ function getDefQuery(def, vars, version) {
|
|
|
167
255
|
}
|
|
168
256
|
function prepareDef(def, vars) {
|
|
169
257
|
function getValue(key) {
|
|
258
|
+
if (typeof key !== "string")
|
|
259
|
+
return key;
|
|
170
260
|
return key[0] === "$" ? vars[key.slice(1)] : key;
|
|
171
261
|
}
|
|
172
262
|
function replacePlaceholders(key) {
|
|
@@ -184,8 +274,10 @@ function prepareDef(def, vars) {
|
|
|
184
274
|
}
|
|
185
275
|
return getValue(key);
|
|
186
276
|
}
|
|
187
|
-
|
|
277
|
+
const ref = def.flatMap(replacePlaceholders);
|
|
278
|
+
return ref;
|
|
188
279
|
}
|
|
280
|
+
const log = debug("graffy:link");
|
|
189
281
|
var index = (defs) => (store) => {
|
|
190
282
|
const prefix = store.path;
|
|
191
283
|
const defEntries = Object.entries(defs).map(([prop, def]) => ({
|
|
@@ -195,10 +287,18 @@ var index = (defs) => (store) => {
|
|
|
195
287
|
store.on("read", async (query, options, next) => {
|
|
196
288
|
const unwrappedQuery = clone(unwrap(query, prefix));
|
|
197
289
|
const usedDefs = prepQueryLinks(unwrappedQuery, defEntries);
|
|
290
|
+
if (!usedDefs.length)
|
|
291
|
+
return next(query, options);
|
|
198
292
|
const result = await next(wrap(unwrappedQuery, prefix), options);
|
|
293
|
+
const version = result[0].version;
|
|
199
294
|
const unwrappedResult = unwrap(result, prefix);
|
|
200
|
-
|
|
201
|
-
|
|
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);
|
|
202
302
|
});
|
|
203
303
|
};
|
|
204
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.16",
|
|
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.16",
|
|
20
|
+
"debug": "^4.3.2"
|
|
20
21
|
}
|
|
21
22
|
}
|