@graffy/common 0.19.0 → 0.19.1-alpha.2

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 (86) hide show
  1. package/coding/alphabet.js +5 -0
  2. package/coding/args.d.ts +7 -0
  3. package/coding/args.js +92 -0
  4. package/coding/base64.d.ts +2 -0
  5. package/coding/base64.js +41 -0
  6. package/coding/decodeTree.d.ts +2 -0
  7. package/coding/decodeTree.js +198 -0
  8. package/coding/decorate.js +211 -0
  9. package/coding/encodeTree.d.ts +2 -0
  10. package/coding/encodeTree.js +251 -0
  11. package/coding/id.js +4 -0
  12. package/coding/index.d.ts +8 -0
  13. package/{types/coding/index.d.ts → coding/index.js} +4 -4
  14. package/coding/number.d.ts +2 -0
  15. package/coding/number.js +39 -0
  16. package/coding/pack.d.ts +2 -0
  17. package/coding/pack.js +71 -0
  18. package/coding/path.d.ts +3 -0
  19. package/coding/path.js +41 -0
  20. package/coding/string.d.ts +2 -0
  21. package/coding/string.js +8 -0
  22. package/coding/struct.d.ts +11 -0
  23. package/coding/struct.js +162 -0
  24. package/index.d.ts +6 -0
  25. package/node/find.d.ts +2 -0
  26. package/node/find.js +14 -0
  27. package/node/index.d.ts +2 -0
  28. package/{types/node/index.d.ts → node/index.js} +1 -0
  29. package/node/types.d.ts +6 -0
  30. package/node/types.js +18 -0
  31. package/object.d.ts +4 -0
  32. package/object.js +86 -0
  33. package/ops/add.js +64 -0
  34. package/ops/finalize.js +19 -0
  35. package/{types/ops → ops}/getKnown.d.ts +1 -4
  36. package/ops/getKnown.js +24 -0
  37. package/ops/index.d.ts +9 -0
  38. package/ops/merge.d.ts +3 -0
  39. package/ops/merge.js +112 -0
  40. package/ops/path.d.ts +6 -0
  41. package/ops/path.js +91 -0
  42. package/ops/setVersion.js +29 -0
  43. package/ops/sieve.d.ts +3 -0
  44. package/ops/sieve.js +193 -0
  45. package/ops/slice.d.ts +13 -0
  46. package/ops/slice.js +153 -0
  47. package/ops/step.d.ts +6 -0
  48. package/ops/step.js +61 -0
  49. package/package.json +14 -8
  50. package/stream/index.d.ts +2 -0
  51. package/stream/makeWatcher.d.ts +10 -0
  52. package/stream/makeWatcher.js +19 -0
  53. package/stream/mergeStreams.js +20 -0
  54. package/util.d.ts +15 -0
  55. package/util.js +106 -0
  56. package/index.cjs +0 -1673
  57. package/index.mjs +0 -1673
  58. package/types/coding/args.d.ts +0 -5
  59. package/types/coding/base64.d.ts +0 -2
  60. package/types/coding/decodeTree.d.ts +0 -2
  61. package/types/coding/encodeTree.d.ts +0 -2
  62. package/types/coding/number.d.ts +0 -2
  63. package/types/coding/pack.d.ts +0 -2
  64. package/types/coding/path.d.ts +0 -3
  65. package/types/coding/string.d.ts +0 -2
  66. package/types/coding/struct.d.ts +0 -11
  67. package/types/node/find.d.ts +0 -2
  68. package/types/node/types.d.ts +0 -6
  69. package/types/object.d.ts +0 -4
  70. package/types/ops/merge.d.ts +0 -3
  71. package/types/ops/path.d.ts +0 -6
  72. package/types/ops/sieve.d.ts +0 -3
  73. package/types/ops/slice.d.ts +0 -13
  74. package/types/ops/step.d.ts +0 -6
  75. package/types/stream/makeWatcher.d.ts +0 -16
  76. package/types/util.d.ts +0 -15
  77. package/{types/coding → coding}/alphabet.d.ts +0 -0
  78. package/{types/coding → coding}/decorate.d.ts +0 -0
  79. package/{types/coding → coding}/id.d.ts +0 -0
  80. package/{types/index.d.ts → index.js} +0 -0
  81. package/{types/ops → ops}/add.d.ts +0 -0
  82. package/{types/ops → ops}/finalize.d.ts +0 -0
  83. package/{types/ops/index.d.ts → ops/index.js} +1 -1
  84. /package/{types/ops → ops}/setVersion.d.ts +0 -0
  85. /package/{types/stream/index.d.ts → stream/index.js} +0 -0
  86. /package/{types/stream → stream}/mergeStreams.d.ts +0 -0
@@ -0,0 +1,5 @@
1
+ /*
2
+ This is just like standard URL-safe Base64, except for using an alphabet
3
+ re-ordered for sortability.
4
+ */
5
+ export default '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
@@ -0,0 +1,7 @@
1
+ export declare function splitArgs(arg: any): [Record<string, any> | undefined, Record<string, any> | undefined];
2
+ export declare function encode(arg: any): {
3
+ key?: Uint8Array<ArrayBuffer>;
4
+ end?: Uint8Array<ArrayBuffer>;
5
+ limit?: number;
6
+ };
7
+ export declare function decode(node: any): any;
package/coding/args.js ADDED
@@ -0,0 +1,92 @@
1
+ import { keyAfter, keyBefore, keyStep } from "../ops/step.js";
2
+ import { cmp, errIf, isDef, isEmpty, isMaxKey, isMinKey, isPlainObject, MAX_KEY, MIN_KEY, } from "../util.js";
3
+ import { decode as decodeValue, encode as encodeValue } from "./struct.js";
4
+ function decodeBound(bound) {
5
+ const { key, step } = keyStep(bound);
6
+ if (isMinKey(key) || isMaxKey(key))
7
+ return { step };
8
+ const value = decodeValue(key);
9
+ return { key: value, step };
10
+ }
11
+ const pageProps = {
12
+ $all: 1,
13
+ $first: 1,
14
+ $last: 1,
15
+ $after: 1,
16
+ $before: 1,
17
+ $since: 1,
18
+ $until: 1,
19
+ $cursor: 1,
20
+ };
21
+ export function splitArgs(arg) {
22
+ const page = {};
23
+ const filter = {};
24
+ for (const p in arg)
25
+ (p in pageProps ? page : filter)[p] = arg[p];
26
+ return [
27
+ isEmpty(page) ? undefined : page,
28
+ isEmpty(filter) ? undefined : filter,
29
+ ];
30
+ }
31
+ export function encode(arg) {
32
+ if (!isPlainObject(arg))
33
+ return { key: encodeValue(arg) };
34
+ const [page, filter] = splitArgs(arg);
35
+ errIf('page_and_filter', page && filter, arg);
36
+ if (!page)
37
+ return { key: encodeValue(filter || {}) };
38
+ const { $cursor, ...range } = page;
39
+ const { $first, $all, $last, $after, $before, $since, $until } = range;
40
+ const hasRange = !isEmpty(range);
41
+ errIf('first_and_last', isDef($first) && isDef($last), arg);
42
+ errIf('all_and_last', isDef($all) && isDef($last), arg);
43
+ errIf('all_and_first', isDef($first) && isDef($all), arg);
44
+ errIf('after_and_since', isDef($after) && isDef($since), arg);
45
+ errIf('before_and_until', isDef($before) && isDef($until), arg);
46
+ errIf('cursor_and_range_arg', isDef($cursor) && hasRange, arg);
47
+ let [key, end] = hasRange ? [MIN_KEY, MAX_KEY] : [];
48
+ if (isDef($cursor))
49
+ key = encodeValue($cursor);
50
+ if (isDef($after))
51
+ key = keyAfter(encodeValue($after));
52
+ if (isDef($before))
53
+ end = keyBefore(encodeValue($before));
54
+ if (isDef($since))
55
+ key = encodeValue($since);
56
+ if (isDef($until))
57
+ end = encodeValue($until);
58
+ if (isDef($last))
59
+ [key, end] = [end, key];
60
+ const node = { key };
61
+ if (isDef(end))
62
+ node.end = end;
63
+ if ($first || $last)
64
+ node.limit = $first || $last;
65
+ return node;
66
+ }
67
+ export function decode(node) {
68
+ const { key, end, limit } = node;
69
+ errIf('no_key', !isDef(key));
70
+ errIf('limit_without_end', isDef(limit) && !isDef(end));
71
+ const kParts = decodeBound(key);
72
+ if (!isDef(end) || cmp(key, end) === 0)
73
+ return kParts.key;
74
+ const eParts = decodeBound(end);
75
+ const reverse = cmp(key, end) > 0;
76
+ const [lower, upper] = reverse ? [eParts, kParts] : [kParts, eParts];
77
+ const args = {};
78
+ if (limit) {
79
+ args[reverse ? '$last' : '$first'] = limit;
80
+ }
81
+ else if ((isMinKey(key) && isMaxKey(end)) ||
82
+ (isMinKey(end) && isMaxKey(key))) {
83
+ args.$all = true;
84
+ }
85
+ if (isDef(lower.key) && !isMinKey(lower.key)) {
86
+ args[lower.step === 1 ? '$after' : '$since'] = lower.key;
87
+ }
88
+ if (isDef(upper.key) && !isMaxKey(upper.key)) {
89
+ args[upper.step === -1 ? '$before' : '$until'] = upper.key;
90
+ }
91
+ return args;
92
+ }
@@ -0,0 +1,2 @@
1
+ export declare function encode(u8Arr: any): string;
2
+ export declare function decode(string: any, start?: number): any;
@@ -0,0 +1,41 @@
1
+ import { addStringify } from "../util.js";
2
+ import alpha from "./alphabet.js";
3
+ function getByte(view, offset) {
4
+ return offset < view.byteLength ? view.getUint8(offset) : 0;
5
+ }
6
+ function getChar(string, offset) {
7
+ return offset < string.length ? alpha.indexOf(string[offset]) : 0;
8
+ }
9
+ export function encode(u8Arr) {
10
+ const { buffer, byteOffset, byteLength } = u8Arr;
11
+ const view = new DataView(buffer, byteOffset, byteLength);
12
+ let str = '';
13
+ for (let i = 0; i < view.byteLength; i += 3) {
14
+ let value = (getByte(view, i) << 16) +
15
+ (getByte(view, i + 1) << 8) +
16
+ getByte(view, i + 2);
17
+ let gstr = '';
18
+ for (let j = 0; j < 4; j++) {
19
+ gstr = alpha[value & 0x3f] + gstr;
20
+ value = (value >> 6) | 0;
21
+ }
22
+ str += gstr;
23
+ }
24
+ return str.substring(0, Math.ceil((view.byteLength * 4) / 3));
25
+ }
26
+ export function decode(string, start = 0) {
27
+ const buffer = new ArrayBuffer(Math.floor(((string.length - start) * 3) / 4));
28
+ const view = new DataView(buffer);
29
+ for (let i = start; i < string.length; i += 4) {
30
+ let value = (getChar(string, i) << 18) +
31
+ (getChar(string, i + 1) << 12) +
32
+ (getChar(string, i + 2) << 6) +
33
+ getChar(string, i + 3);
34
+ for (let j = (i * 3) / 4 + 2; j >= (i * 3) / 4; j--) {
35
+ if (j < view.byteLength)
36
+ view.setUint8(j, value & 0xff);
37
+ value = (value >> 8) | 0;
38
+ }
39
+ }
40
+ return addStringify(new Uint8Array(buffer));
41
+ }
@@ -0,0 +1,2 @@
1
+ export declare function decodeGraph(graph: any): any[];
2
+ export declare function decodeQuery(query: any): any[];
@@ -0,0 +1,198 @@
1
+ import { isBranch, isLink, isPrefix, isRange } from "../node/index.js";
2
+ import { keyAfter } from "../ops/index.js";
3
+ import { clone, cmp, isDef, isEmpty, isMaxKey, isMinKey } from "../util.js";
4
+ import { decode as decodeArgs, splitArgs } from "./args.js";
5
+ import { decode as decodePath } from "./path.js";
6
+ const PRE_CHI_PUT = Symbol('PREFIX_CHILDREN_$PUT');
7
+ /**
8
+ @param {any[]} nodes
9
+ @param {{ isGraph?: boolean }} options
10
+ */
11
+ function decode(nodes = [], { isGraph } = {}) {
12
+ function decodeChildren(nodes) {
13
+ let result = [];
14
+ let allStrs = true;
15
+ let allNums = true;
16
+ //Pushes objects to the result set and updates allStrs and allNums.
17
+ function pushResult(...objects) {
18
+ for (const object of objects) {
19
+ if (isDef(object) && !Number.isInteger(object.$key))
20
+ allNums = false;
21
+ if (isDef(object) && typeof object.$key !== 'string')
22
+ allStrs = false;
23
+ }
24
+ result.push(...objects);
25
+ }
26
+ const putRanges = [];
27
+ const prefixChildPuts = [];
28
+ let lastNode = null;
29
+ // Graphs only: Constructs the $put array. Returns true if this is a range
30
+ // node that does not require to be added to the results.
31
+ function addPutRange({ key, end }) {
32
+ if (lastNode) {
33
+ if (lastNode.end) {
34
+ if (cmp(key, keyAfter(lastNode.end)) === 0) {
35
+ lastNode.end = end || key;
36
+ return end && cmp(end, key) !== 0;
37
+ }
38
+ }
39
+ else {
40
+ if (cmp(key, keyAfter(lastNode.key)) === 0) {
41
+ key = lastNode.key;
42
+ }
43
+ }
44
+ }
45
+ if (end && cmp(key, end) !== 0) {
46
+ lastNode = { key, end };
47
+ putRanges.push(lastNode);
48
+ return true;
49
+ }
50
+ lastNode = { key };
51
+ return false;
52
+ }
53
+ for (const node of nodes) {
54
+ if (isGraph && addPutRange(node))
55
+ continue;
56
+ if (isPrefix(node)) {
57
+ const decodedChildren = decodePrefixNode(node);
58
+ if (PRE_CHI_PUT in decodedChildren) {
59
+ prefixChildPuts.push(...decodedChildren[PRE_CHI_PUT]);
60
+ }
61
+ pushResult(...decodedChildren);
62
+ }
63
+ else if (isGraph && isRange(node))
64
+ pushResult(decodeRangeNode(node));
65
+ else if (isBranch(node))
66
+ pushResult(decodeBranchNode(node));
67
+ else if (isLink(node))
68
+ pushResult(decodeLinkNode(node));
69
+ else
70
+ pushResult(decodeLeafNode(node));
71
+ }
72
+ // Use a simplified format if all the keys are strings or it's a plain array.
73
+ if (allStrs ||
74
+ (allNums &&
75
+ putRanges.length === 1 &&
76
+ cmp(putRanges[0].key, 0) === 0 &&
77
+ cmp(putRanges[0].end, Number.POSITIVE_INFINITY) === 0)) {
78
+ result = result.reduce((collection, item) => {
79
+ if (Array.isArray(item)) {
80
+ collection[item.$key] = item;
81
+ delete item.$key;
82
+ return collection;
83
+ }
84
+ let { $key, $val } = item;
85
+ delete item.$key;
86
+ delete item.$val;
87
+ if ($val === null) {
88
+ $val = { $val };
89
+ }
90
+ else if (typeof $val === 'object') {
91
+ $val = clone($val);
92
+ Object.defineProperty($val, '$val', { value: true });
93
+ }
94
+ // biome-ignore format: tertnary chain
95
+ collection[$key] = (isDef($val) ? $val :
96
+ !isEmpty(item) || item.$ref || item.$put ? item :
97
+ isGraph ? null : true);
98
+ return collection;
99
+ }, allStrs ? {} : []);
100
+ }
101
+ if (isGraph && putRanges.length) {
102
+ if (isMinKey(putRanges[0].key) && isMaxKey(putRanges[0].end)) {
103
+ Object.defineProperty(result, '$put', { value: true });
104
+ }
105
+ else {
106
+ Object.defineProperty(result, '$put', {
107
+ value: putRanges
108
+ .map((rNode) => decodeArgs(rNode))
109
+ .concat(prefixChildPuts),
110
+ });
111
+ }
112
+ }
113
+ else if (prefixChildPuts.length) {
114
+ Object.defineProperty(result, '$put', { value: prefixChildPuts });
115
+ }
116
+ return result;
117
+ }
118
+ function decodePrefixNode(node) {
119
+ let args = decodeArgs(node);
120
+ if (!args)
121
+ args = {};
122
+ if (typeof args === 'string') {
123
+ throw Error(`decode.unencoded_prefix: ${args}`);
124
+ }
125
+ if (isLink(node)) {
126
+ args.$all = true;
127
+ const $ref = decodePath(node.path);
128
+ const lastKey = $ref[$ref.length - 1];
129
+ if (typeof lastKey === 'string') {
130
+ throw Error(`decode.unencoded_prefix_ref: ${node.path}`);
131
+ }
132
+ lastKey.$all = true;
133
+ const linkObject = { $key: args };
134
+ Object.defineProperty(linkObject, '$ref', { value: $ref });
135
+ return [linkObject];
136
+ }
137
+ /** @type {any[] & {$put?: any}} */
138
+ const children = decodeChildren(node.children);
139
+ if (!Array.isArray(children)) {
140
+ throw Error(`decode.prefix_without_encoded_child_keys:${node.key}`);
141
+ }
142
+ for (const child of children) {
143
+ if (typeof child.$key === 'string') {
144
+ throw Error(`decode.prefix_with_unencoded_child_key:${child.$key}`);
145
+ }
146
+ if (!splitArgs(child.$key)[0]) {
147
+ // splitArgs returns [page, filter]. If page is blank, it indicates
148
+ // we have a bare cursor.
149
+ child.$key = { $cursor: child.$key };
150
+ }
151
+ child.$key = { ...args, ...child.$key };
152
+ }
153
+ const ch = children;
154
+ if (ch.$put === true) {
155
+ ch[PRE_CHI_PUT] = [{ ...args, $all: true }];
156
+ }
157
+ else if (Array.isArray(ch.$put)) {
158
+ ch[PRE_CHI_PUT] = ch.$put.map((rarg) => ({
159
+ ...args,
160
+ ...rarg,
161
+ }));
162
+ }
163
+ else if (isDef(ch.$put)) {
164
+ ch[PRE_CHI_PUT] = [{ ...args, ...ch.$put }];
165
+ }
166
+ return children;
167
+ }
168
+ function decodeBranchNode(node) {
169
+ const child = decodeChildren(node.children);
170
+ child.$key = decodeArgs(node);
171
+ return child;
172
+ }
173
+ function decodeLeafNode(node) {
174
+ const child = isGraph ? { $val: node.value } : {};
175
+ child.$key = decodeArgs(node);
176
+ return child;
177
+ }
178
+ /**
179
+ Only for graphs;
180
+ */
181
+ function decodeRangeNode(node) {
182
+ if (cmp(node.key, node.end) === 0) {
183
+ return { $key: decodeArgs({ key: node.key }) };
184
+ }
185
+ }
186
+ function decodeLinkNode(node) {
187
+ const linkObject = { $key: decodeArgs(node) };
188
+ Object.defineProperty(linkObject, '$ref', { value: decodePath(node.path) });
189
+ return linkObject;
190
+ }
191
+ return decodeChildren(nodes);
192
+ }
193
+ export function decodeGraph(graph) {
194
+ return decode(graph, { isGraph: true });
195
+ }
196
+ export function decodeQuery(query) {
197
+ return decode(query, { isGraph: false });
198
+ }
@@ -0,0 +1,211 @@
1
+ import { findFirst, isRange } from "../node/index.js";
2
+ import { getNodeValue, IS_VAL, unwrap } from "../ops/index.js";
3
+ import { cmp, isDef, isEmpty, isMinKey, isPlainObject, MIN_KEY, } from "../util.js";
4
+ import { decode as decodeArgs, encode as encodeArgs, splitArgs, } from "./args.js";
5
+ import { decodeGraph } from "./decodeTree.js";
6
+ import { decode as decodePath, encode as encodePath, splitRef, } from "./path.js";
7
+ const REF = Symbol();
8
+ const PRE = Symbol();
9
+ export default function decorate(rootGraph, rootQuery) {
10
+ // console.log('Decorating', rootGraph, rootQuery);
11
+ function construct(plumGraph, query) {
12
+ if (plumGraph === null)
13
+ return null;
14
+ if (!isDef(plumGraph))
15
+ plumGraph = [];
16
+ if (query.$key)
17
+ query = [query];
18
+ // console.log('Constructing', plumGraph, query);
19
+ let graph;
20
+ if (query.$ref) {
21
+ const { $ref, ...props } = query;
22
+ const [range, filter] = splitRef($ref);
23
+ const path = encodePath($ref);
24
+ const targetPlumGraph = unwrap(rootGraph, path);
25
+ if (targetPlumGraph) {
26
+ if (range)
27
+ targetPlumGraph[PRE] = filter;
28
+ graph = construct(targetPlumGraph, range ? { $key: range, ...props } : props);
29
+ Object.defineProperty(graph, '$ref', { value: $ref });
30
+ }
31
+ }
32
+ else if (Array.isArray(query)) {
33
+ let pageKey;
34
+ graph = query.flatMap((item, i) => {
35
+ if (!item?.$key) {
36
+ // This is an integer-indexed array.
37
+ return construct(descend(plumGraph, i), item);
38
+ }
39
+ const { $key, $chi, ...props } = item;
40
+ const subQuery = $chi || (isEmpty(props) ? 1 : props);
41
+ if (!(isPlainObject($key) && splitArgs($key)[0])) {
42
+ // This is a non-string argument without pagination
43
+ return construct(descend(plumGraph, $key), subQuery);
44
+ }
45
+ // This is a pagination query.
46
+ if (pageKey) {
47
+ throw Error(`decorate.multi_range_query:${JSON.stringify({ $key, pageKey })}`);
48
+ }
49
+ pageKey = $key;
50
+ const children = slice(plumGraph, $key);
51
+ return children
52
+ .filter((node) => !isRange(node))
53
+ .map((node) => {
54
+ const $key = decodeArgs(node);
55
+ const subResult = construct(getValue(node), subQuery);
56
+ if (typeof subResult === 'object' && subResult) {
57
+ subResult.$key =
58
+ children[PRE] && !isMinKey(children[PRE])
59
+ ? { ...children[PRE], $cursor: $key }
60
+ : $key;
61
+ }
62
+ return subResult;
63
+ });
64
+ });
65
+ // .filter(Boolean);
66
+ if (pageKey)
67
+ addPageMeta(graph, pageKey);
68
+ }
69
+ else if (typeof query === 'object') {
70
+ graph = {};
71
+ for (const prop in query) {
72
+ graph[prop] = construct(descend(plumGraph, prop), query[prop]);
73
+ }
74
+ }
75
+ else if (query) {
76
+ if (Array.isArray(plumGraph) && !plumGraph.length) {
77
+ graph = undefined;
78
+ }
79
+ else if (typeof plumGraph !== 'object' || !plumGraph) {
80
+ graph = plumGraph;
81
+ }
82
+ else if (plumGraph[IS_VAL]) {
83
+ graph = Array.isArray(plumGraph)
84
+ ? plumGraph.slice(0)
85
+ : { ...plumGraph };
86
+ graph.$val = true;
87
+ }
88
+ else if (Array.isArray(plumGraph)) {
89
+ graph = deValNull(decodeGraph(plumGraph));
90
+ }
91
+ else {
92
+ throw Error('decorate.unexpected_graph');
93
+ }
94
+ }
95
+ if (plumGraph[REF]) {
96
+ Object.defineProperty(graph, '$ref', {
97
+ value: decodePath(plumGraph[REF]),
98
+ });
99
+ }
100
+ return graph;
101
+ }
102
+ function descend(children, $key) {
103
+ const key = ArrayBuffer.isView($key) ? $key : encodeArgs($key).key;
104
+ if (!Array.isArray(children))
105
+ return null;
106
+ const ix = findFirst(children, key);
107
+ const node = children[ix];
108
+ if (!node)
109
+ return;
110
+ if (isRange(node) && node.end >= key)
111
+ return null;
112
+ if (cmp(node.key, key) !== 0)
113
+ return;
114
+ const result = getValue(node);
115
+ if (node.prefix)
116
+ result[PRE] = $key;
117
+ return result;
118
+ }
119
+ function getValue(node) {
120
+ let result;
121
+ if (node.path) {
122
+ result = unwrap(rootGraph, node.path);
123
+ if (typeof result === 'object' && result)
124
+ result[REF] = node.path;
125
+ }
126
+ else {
127
+ result = getNodeValue(node);
128
+ }
129
+ return result;
130
+ }
131
+ function slice(children, $key) {
132
+ const [range, filter] = splitArgs($key);
133
+ if (isDef(filter)) {
134
+ children = descend(children, filter);
135
+ }
136
+ else if (isMinKey(children[0].key) && children[0].prefix) {
137
+ children = descend(children, MIN_KEY);
138
+ }
139
+ const { key, end, limit = Number.POSITIVE_INFINITY } = encodeArgs(range);
140
+ const ix = findFirst(children, key);
141
+ let i = ix;
142
+ let result;
143
+ if (cmp(key, end) < 0) {
144
+ for (let n = 0; i < children.length && n < limit; i++) {
145
+ if (!isRange(children[i]))
146
+ n++;
147
+ }
148
+ // console.log('slicing fwd', children, ix, i);
149
+ result = children.slice(ix, i);
150
+ }
151
+ else {
152
+ for (let n = 0; i >= 0 && n < limit; i--) {
153
+ if (!isRange(children[i]))
154
+ n++;
155
+ }
156
+ // console.log('slicing bkd', children, i + 1, ix + 1);
157
+ result = children.slice(i + 1, ix + 1);
158
+ }
159
+ if (children[REF])
160
+ result[REF] = children[REF];
161
+ if (children[PRE])
162
+ result[PRE] = children[PRE];
163
+ return result;
164
+ }
165
+ const result = construct(rootGraph, rootQuery);
166
+ // console.log('Decorate', result, rootGraph, rootQuery);
167
+ return result;
168
+ }
169
+ // Replace $val: null produced by
170
+ function deValNull(graph) {
171
+ if (typeof graph !== 'object' || !graph)
172
+ return graph;
173
+ if ('$val' in graph && graph.$val !== true)
174
+ return graph.$val;
175
+ // Important: update graph in-place to avoid losing non-enumerable props.
176
+ for (const prop in graph)
177
+ graph[prop] = deValNull(graph[prop]);
178
+ return graph;
179
+ }
180
+ function addPageMeta(graph, args) {
181
+ if (args.$all) {
182
+ Object.assign(graph, { $page: args, $prev: null, $next: null });
183
+ return;
184
+ }
185
+ const [page, filter] = splitArgs(args);
186
+ const { $first, $last, ...bounds } = page;
187
+ const count = $first || $last;
188
+ const $page = { ...filter, ...bounds, $all: true };
189
+ if (graph.length === count) {
190
+ // This result was limited by the count; update the "outer" bound.
191
+ if ($first) {
192
+ const boundKey = graph[graph.length - 1].$key;
193
+ $page.$until = isDef(boundKey?.$cursor) ? boundKey.$cursor : boundKey;
194
+ delete $page.$before;
195
+ }
196
+ else {
197
+ const boundKey = graph[0].$key;
198
+ $page.$since = isDef(boundKey?.$cursor) ? boundKey.$cursor : boundKey;
199
+ delete $page.$after;
200
+ }
201
+ }
202
+ // biome-ignore format: ternary chain
203
+ const $prev = isDef($page.$after) ? { ...filter, $last: count, $until: $page.$after } :
204
+ isDef($page.$since) ? { ...filter, $last: count, $before: $page.$since } :
205
+ null;
206
+ // biome-ignore format: ternary chain
207
+ const $next = isDef($page.$before) ? { ...filter, $first: count, $since: $page.$before } :
208
+ isDef($page.$until) ? { ...filter, $first: count, $after: $page.$until } :
209
+ null;
210
+ Object.assign(graph, { $page, $next, $prev });
211
+ }
@@ -0,0 +1,2 @@
1
+ export declare function encodeGraph(obj: any, version?: number): any;
2
+ export declare function encodeQuery(obj: any, version?: number): any;