@graffy/link 0.15.20 → 0.15.21-alpha.3

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.
Files changed (3) hide show
  1. package/index.cjs +56 -60
  2. package/index.mjs +57 -61
  3. package/package.json +2 -2
package/index.cjs CHANGED
@@ -27,65 +27,54 @@ var debug__default = /* @__PURE__ */ _interopDefaultLegacy(debug);
27
27
  function linkGraph(rootGraph, defs) {
28
28
  let version = rootGraph[0].version;
29
29
  for (const { path, def } of defs) {
30
- const braid = def.map(getKeyValues);
30
+ const braid = def.map(getChoices);
31
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
- }
32
+ for (const { value, vars } of strands) {
33
+ const realPath = makeRef(path, vars);
34
+ const realRef = makeRef(value, vars);
35
+ const node = { key: realPath.pop(), path: common.encodePath(realRef), version };
36
+ const [range] = common.splitRef(realRef);
37
+ if (range)
38
+ node.prefix = true;
39
+ let target = rootGraph;
40
+ do {
41
+ const key = realPath.shift();
42
+ const nextTarget = target[common.findFirst(target, key)];
43
+ if (!nextTarget || nextTarget.key !== key || nextTarget.end) {
44
+ realPath.unshift(key);
45
+ break;
46
+ }
47
+ target = nextTarget.path ? common.unwrap(rootGraph, nextTarget.path) : nextTarget.children;
48
+ } while (target && realPath.length);
49
+ if (!target)
50
+ return;
51
+ common.merge(target, realPath.length ? common.wrap([node], realPath, version) : [node]);
52
+ }
64
53
  }
65
54
  return rootGraph;
66
- function getKeyValues(key) {
55
+ function getChoices(key) {
67
56
  if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
68
57
  return lookupValues(rootGraph, key.slice(2).split("."));
69
58
  }
70
59
  if (Array.isArray(key)) {
71
- return unbraid(key.map(getKeyValues));
60
+ return unbraid(key.map(getChoices));
72
61
  }
73
62
  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;
63
+ const [range = {}, filter = {}] = common.splitArgs(key);
64
+ const entries = unbraid(Object.entries(filter).flat().map(getChoices));
65
+ return entries.map(({ value, vars }) => ({
66
+ value: __spreadValues(__spreadValues({}, range), Object.fromEntries(value.reduce((acc, item, i) => {
67
+ if (i % 2) {
68
+ acc[acc.length - 1].push(item);
69
+ } else {
70
+ acc.push([item]);
71
+ }
79
72
  return acc;
80
- }, {}),
81
- vars,
82
- reqs
73
+ }, []))),
74
+ vars
83
75
  }));
84
76
  }
85
- if (typeof key === "string" && key[0] === "$") {
86
- return [{ value: key, vars: {}, reqs: { [key.slice(1)]: true } }];
87
- }
88
- return [{ value: key, vars: {}, reqs: {} }];
77
+ return [{ value: key, vars: {} }];
89
78
  }
90
79
  function lookupValues(graph, path, vars = {}) {
91
80
  const [key, ...rest] = path;
@@ -104,7 +93,7 @@ function linkGraph(rootGraph, defs) {
104
93
  }
105
94
  function recurse(node, path, vars) {
106
95
  if (!path.length)
107
- return [{ value: node.value, vars, reqs: {} }];
96
+ return [{ value: node.value, vars }];
108
97
  if (node.children)
109
98
  return lookupValues(node.children, path, vars);
110
99
  if (node.path) {
@@ -116,19 +105,19 @@ function linkGraph(rootGraph, defs) {
116
105
  }
117
106
  }
118
107
  function unbraid(braid) {
108
+ if (!braid.length)
109
+ return [];
119
110
  const [options, ...rest] = braid;
120
111
  if (!rest.length) {
121
112
  return options.map((option) => ({
122
113
  value: [option.value],
123
- vars: option.vars,
124
- reqs: option.reqs
114
+ vars: option.vars
125
115
  }));
126
116
  }
127
117
  const strands = unbraid(rest);
128
118
  return options.flatMap((option) => strands.filter((strand) => isCompatible(option.vars, strand.vars)).map((strand) => ({
129
119
  value: [option.value, ...strand.value],
130
- vars: __spreadValues(__spreadValues({}, option.vars), strand.vars),
131
- reqs: __spreadValues(__spreadValues({}, option.reqs), strand.reqs)
120
+ vars: __spreadValues(__spreadValues({}, option.vars), strand.vars)
132
121
  })));
133
122
  }
134
123
  function isCompatible(oVars, sVars) {
@@ -142,7 +131,7 @@ function makeRef(def, vars) {
142
131
  function getValue(key) {
143
132
  if (typeof key !== "string")
144
133
  return key;
145
- return key[0] === "$" ? vars[key.slice(1)] : key;
134
+ return key[0] === "$" && key.slice(1) in vars ? vars[key.slice(1)] : key;
146
135
  }
147
136
  function replacePlaceholders(key) {
148
137
  if (Array.isArray(key)) {
@@ -150,8 +139,9 @@ function makeRef(def, vars) {
150
139
  }
151
140
  if (typeof key === "object" && key) {
152
141
  const result = {};
153
- for (const prop in key)
154
- result[prop] = replacePlaceholders(key[prop]);
142
+ for (const prop in key) {
143
+ result[replacePlaceholders(prop)] = replacePlaceholders(key[prop]);
144
+ }
155
145
  return result;
156
146
  }
157
147
  return getValue(key);
@@ -168,9 +158,12 @@ function prepQueryLinks(rootQuery, defs) {
168
158
  const [range, filter] = common.splitRef(def);
169
159
  if (range && subQuery.length) {
170
160
  return subQuery.map((node) => {
161
+ if (!node.prefix && !node.end) {
162
+ throw Error("link.range_expected: " + path.concat(node.key).join("."));
163
+ }
171
164
  return {
172
165
  path: path.concat(node.key),
173
- def: prepareDef(def.slice(0, -1).concat(__spreadValues(__spreadValues(__spreadValues({}, filter), common.decodeArgs(node)), range)), vars)
166
+ def: prepareDef(def.slice(0, -1).concat(__spreadValues(__spreadValues(__spreadValues({}, filter), node.prefix ? common.decodeArgs(node) : {}), range)), vars)
174
167
  };
175
168
  });
176
169
  } else {
@@ -251,8 +244,10 @@ function getDefQuery(def, vars, version) {
251
244
  key.map(addDefQueries);
252
245
  }
253
246
  if (typeof key === "object" && key) {
254
- for (const prop in key)
247
+ for (const prop in key) {
248
+ addDefQueries(prop);
255
249
  addDefQueries(key[prop]);
250
+ }
256
251
  }
257
252
  }
258
253
  def.map(addDefQueries);
@@ -262,7 +257,7 @@ function prepareDef(def, vars) {
262
257
  function getValue(key) {
263
258
  if (typeof key !== "string")
264
259
  return key;
265
- return key[0] === "$" ? vars[key.slice(1)] : key;
260
+ return key[0] === "$" && key.slice(1) in vars ? vars[key.slice(1)] : key;
266
261
  }
267
262
  function replacePlaceholders(key) {
268
263
  if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
@@ -273,8 +268,9 @@ function prepareDef(def, vars) {
273
268
  }
274
269
  if (typeof key === "object" && key) {
275
270
  const result = {};
276
- for (const prop in key)
277
- result[prop] = replacePlaceholders(key[prop]);
271
+ for (const prop in key) {
272
+ result[replacePlaceholders(prop)] = replacePlaceholders(key[prop]);
273
+ }
278
274
  return result;
279
275
  }
280
276
  return getValue(key);
package/index.mjs CHANGED
@@ -17,70 +17,59 @@ var __spreadValues = (a, b) => {
17
17
  return a;
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- import { encodePath, splitRef, findFirst, unwrap, merge, wrap, decodeArgs, isBranch, add, wrapValue, finalize } from "@graffy/common";
20
+ import { encodePath, splitRef, findFirst, unwrap, merge, wrap, splitArgs, decodeArgs, isBranch, add, wrapValue, finalize } from "@graffy/common";
21
21
  import debug from "debug";
22
22
  function linkGraph(rootGraph, defs) {
23
23
  let version = rootGraph[0].version;
24
24
  for (const { path, def } of defs) {
25
- const braid = def.map(getKeyValues);
25
+ const braid = def.map(getChoices);
26
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
- }
27
+ for (const { value, vars } of strands) {
28
+ const realPath = makeRef(path, vars);
29
+ const realRef = makeRef(value, vars);
30
+ const node = { key: realPath.pop(), path: encodePath(realRef), version };
31
+ const [range] = splitRef(realRef);
32
+ if (range)
33
+ node.prefix = true;
34
+ let target = rootGraph;
35
+ do {
36
+ const key = realPath.shift();
37
+ const nextTarget = target[findFirst(target, key)];
38
+ if (!nextTarget || nextTarget.key !== key || nextTarget.end) {
39
+ realPath.unshift(key);
40
+ break;
41
+ }
42
+ target = nextTarget.path ? unwrap(rootGraph, nextTarget.path) : nextTarget.children;
43
+ } while (target && realPath.length);
44
+ if (!target)
45
+ return;
46
+ merge(target, realPath.length ? wrap([node], realPath, version) : [node]);
47
+ }
59
48
  }
60
49
  return rootGraph;
61
- function getKeyValues(key) {
50
+ function getChoices(key) {
62
51
  if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
63
52
  return lookupValues(rootGraph, key.slice(2).split("."));
64
53
  }
65
54
  if (Array.isArray(key)) {
66
- return unbraid(key.map(getKeyValues));
55
+ return unbraid(key.map(getChoices));
67
56
  }
68
57
  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;
58
+ const [range = {}, filter = {}] = splitArgs(key);
59
+ const entries = unbraid(Object.entries(filter).flat().map(getChoices));
60
+ return entries.map(({ value, vars }) => ({
61
+ value: __spreadValues(__spreadValues({}, range), Object.fromEntries(value.reduce((acc, item, i) => {
62
+ if (i % 2) {
63
+ acc[acc.length - 1].push(item);
64
+ } else {
65
+ acc.push([item]);
66
+ }
74
67
  return acc;
75
- }, {}),
76
- vars,
77
- reqs
68
+ }, []))),
69
+ vars
78
70
  }));
79
71
  }
80
- if (typeof key === "string" && key[0] === "$") {
81
- return [{ value: key, vars: {}, reqs: { [key.slice(1)]: true } }];
82
- }
83
- return [{ value: key, vars: {}, reqs: {} }];
72
+ return [{ value: key, vars: {} }];
84
73
  }
85
74
  function lookupValues(graph, path, vars = {}) {
86
75
  const [key, ...rest] = path;
@@ -99,7 +88,7 @@ function linkGraph(rootGraph, defs) {
99
88
  }
100
89
  function recurse(node, path, vars) {
101
90
  if (!path.length)
102
- return [{ value: node.value, vars, reqs: {} }];
91
+ return [{ value: node.value, vars }];
103
92
  if (node.children)
104
93
  return lookupValues(node.children, path, vars);
105
94
  if (node.path) {
@@ -111,19 +100,19 @@ function linkGraph(rootGraph, defs) {
111
100
  }
112
101
  }
113
102
  function unbraid(braid) {
103
+ if (!braid.length)
104
+ return [];
114
105
  const [options, ...rest] = braid;
115
106
  if (!rest.length) {
116
107
  return options.map((option) => ({
117
108
  value: [option.value],
118
- vars: option.vars,
119
- reqs: option.reqs
109
+ vars: option.vars
120
110
  }));
121
111
  }
122
112
  const strands = unbraid(rest);
123
113
  return options.flatMap((option) => strands.filter((strand) => isCompatible(option.vars, strand.vars)).map((strand) => ({
124
114
  value: [option.value, ...strand.value],
125
- vars: __spreadValues(__spreadValues({}, option.vars), strand.vars),
126
- reqs: __spreadValues(__spreadValues({}, option.reqs), strand.reqs)
115
+ vars: __spreadValues(__spreadValues({}, option.vars), strand.vars)
127
116
  })));
128
117
  }
129
118
  function isCompatible(oVars, sVars) {
@@ -137,7 +126,7 @@ function makeRef(def, vars) {
137
126
  function getValue(key) {
138
127
  if (typeof key !== "string")
139
128
  return key;
140
- return key[0] === "$" ? vars[key.slice(1)] : key;
129
+ return key[0] === "$" && key.slice(1) in vars ? vars[key.slice(1)] : key;
141
130
  }
142
131
  function replacePlaceholders(key) {
143
132
  if (Array.isArray(key)) {
@@ -145,8 +134,9 @@ function makeRef(def, vars) {
145
134
  }
146
135
  if (typeof key === "object" && key) {
147
136
  const result = {};
148
- for (const prop in key)
149
- result[prop] = replacePlaceholders(key[prop]);
137
+ for (const prop in key) {
138
+ result[replacePlaceholders(prop)] = replacePlaceholders(key[prop]);
139
+ }
150
140
  return result;
151
141
  }
152
142
  return getValue(key);
@@ -163,9 +153,12 @@ function prepQueryLinks(rootQuery, defs) {
163
153
  const [range, filter] = splitRef(def);
164
154
  if (range && subQuery.length) {
165
155
  return subQuery.map((node) => {
156
+ if (!node.prefix && !node.end) {
157
+ throw Error("link.range_expected: " + path.concat(node.key).join("."));
158
+ }
166
159
  return {
167
160
  path: path.concat(node.key),
168
- def: prepareDef(def.slice(0, -1).concat(__spreadValues(__spreadValues(__spreadValues({}, filter), decodeArgs(node)), range)), vars)
161
+ def: prepareDef(def.slice(0, -1).concat(__spreadValues(__spreadValues(__spreadValues({}, filter), node.prefix ? decodeArgs(node) : {}), range)), vars)
169
162
  };
170
163
  });
171
164
  } else {
@@ -246,8 +239,10 @@ function getDefQuery(def, vars, version) {
246
239
  key.map(addDefQueries);
247
240
  }
248
241
  if (typeof key === "object" && key) {
249
- for (const prop in key)
242
+ for (const prop in key) {
243
+ addDefQueries(prop);
250
244
  addDefQueries(key[prop]);
245
+ }
251
246
  }
252
247
  }
253
248
  def.map(addDefQueries);
@@ -257,7 +252,7 @@ function prepareDef(def, vars) {
257
252
  function getValue(key) {
258
253
  if (typeof key !== "string")
259
254
  return key;
260
- return key[0] === "$" ? vars[key.slice(1)] : key;
255
+ return key[0] === "$" && key.slice(1) in vars ? vars[key.slice(1)] : key;
261
256
  }
262
257
  function replacePlaceholders(key) {
263
258
  if (typeof key === "string" && key[0] === "$" && key[1] === "$") {
@@ -268,8 +263,9 @@ function prepareDef(def, vars) {
268
263
  }
269
264
  if (typeof key === "object" && key) {
270
265
  const result = {};
271
- for (const prop in key)
272
- result[prop] = replacePlaceholders(key[prop]);
266
+ for (const prop in key) {
267
+ result[replacePlaceholders(prop)] = replacePlaceholders(key[prop]);
268
+ }
273
269
  return result;
274
270
  }
275
271
  return getValue(key);
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.20",
5
+ "version": "0.15.21-alpha.3",
6
6
  "main": "./index.cjs",
7
7
  "exports": {
8
8
  "import": "./index.mjs",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "license": "Apache-2.0",
18
18
  "dependencies": {
19
- "@graffy/common": "0.15.20",
19
+ "@graffy/common": "0.15.21-alpha.3",
20
20
  "debug": "^4.3.3"
21
21
  }
22
22
  }