@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
package/ops/slice.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ declare class Result {
2
+ root: Result;
3
+ known?: any[];
4
+ unknown?: any[];
5
+ linked?: any[];
6
+ constructor(root?: any);
7
+ addKnown(node: any): void;
8
+ addUnknown(node: any): void;
9
+ addLinked(children: any): any;
10
+ }
11
+ export default function slice(graph: any, query: any, root?: any): Result;
12
+ export declare function sliceRange(graph: any, query: any, result: any): void;
13
+ export {};
package/ops/slice.js ADDED
@@ -0,0 +1,153 @@
1
+ import { findFirst, findLast, isBranch, isLink, isOlder, isRange, } from "../node/index.js";
2
+ import { cmp, isMinKey, MAX_KEY, MIN_KEY } from "../util.js";
3
+ import add from "./add.js";
4
+ import merge from "./merge.js";
5
+ import { wrap } from "./path.js";
6
+ import { keyAfter, keyBefore } from "./step.js";
7
+ class Result {
8
+ constructor(root) {
9
+ // When linked queries are added, they are forwarded to the root.
10
+ this.root = root || this;
11
+ }
12
+ addKnown(node) {
13
+ this.known = this.known || [];
14
+ merge(this.known, [node]);
15
+ }
16
+ addUnknown(node) {
17
+ this.unknown = this.unknown || [];
18
+ this.unknown.push(node);
19
+ }
20
+ addLinked(children) {
21
+ if (this.root !== this)
22
+ return this.root.addLinked(children);
23
+ this.linked = this.linked || [];
24
+ add(this.linked, children);
25
+ }
26
+ }
27
+ export default function slice(graph, query, root) {
28
+ const result = new Result(root);
29
+ let currentQuery = query;
30
+ while (currentQuery) {
31
+ let index = 0;
32
+ for (const queryNode of currentQuery) {
33
+ if (isRange(queryNode)) {
34
+ sliceRange(graph, queryNode, result);
35
+ }
36
+ else {
37
+ const key = queryNode.key;
38
+ index = findFirst(graph, key);
39
+ sliceNode(graph[index], queryNode, result);
40
+ }
41
+ }
42
+ currentQuery = root ? undefined : result.linked;
43
+ delete result.linked;
44
+ }
45
+ delete result.root;
46
+ return result;
47
+ }
48
+ function sliceNode(graph, query, result) {
49
+ const { key, version } = query;
50
+ const { root } = result;
51
+ // console.log('Slicing', graph, query);
52
+ if (!graph || cmp(graph.key, key) > 0 || isOlder(graph, version)) {
53
+ // The node found doesn't match the query or it's too old.
54
+ result.addUnknown(query);
55
+ }
56
+ else if (isRange(graph)) {
57
+ // The graph is indicating that this value was deleted.
58
+ if (isBranch(query)) {
59
+ const { known } = slice([{ key: MIN_KEY, end: MAX_KEY, version: graph.version }], query.children);
60
+ result.addKnown({ key, version: graph.version, children: known });
61
+ }
62
+ else {
63
+ result.addKnown({ key, end: key, version: graph.version });
64
+ }
65
+ }
66
+ else if (isBranch(graph) && isBranch(query)) {
67
+ // Both sides are branches; recurse into them.
68
+ const { known, unknown } = slice(graph.children, query.children, root);
69
+ if (known)
70
+ result.addKnown({ ...graph, children: known });
71
+ if (unknown)
72
+ result.addUnknown({ ...query, children: unknown });
73
+ }
74
+ else if (isLink(graph)) {
75
+ result.addKnown(graph);
76
+ if (graph.prefix && isRange(query)) {
77
+ result.addLinked(wrap([query], graph.path, version, true));
78
+ }
79
+ else {
80
+ result.addLinked(wrap(query.children || query.value, graph.path, version, graph.prefix || query.prefix));
81
+ }
82
+ }
83
+ else if (isBranch(graph)) {
84
+ // The graph is a branch and query is requesting all children here.
85
+ result.addKnown(graph);
86
+ }
87
+ else if (isBranch(query)) {
88
+ // One graph is a leaf while the query is a leaf; return null.
89
+ const { known } = slice([{ key: MIN_KEY, end: MAX_KEY, version: graph.version }], query.children);
90
+ result.addKnown({ key, version: graph.version, children: known });
91
+ }
92
+ else {
93
+ result.addKnown(graph);
94
+ }
95
+ }
96
+ export function sliceRange(graph, query, result) {
97
+ let { key, end, limit = Number.POSITIVE_INFINITY, version } = query;
98
+ const step = cmp(key, end) < 0 ? 1 : -1;
99
+ // Prefixes are used to combine filtering and pagination. In schemas where
100
+ // prefixes are expected but a particular graph does not have a filter, it
101
+ // will have a prefix node with an empty string as key.
102
+ if (isMinKey(graph[0].key) && graph[0].prefix && graph[0].children) {
103
+ const { known, unknown } = slice(graph[0].children, [query], result.root);
104
+ if (known)
105
+ result.addKnown({ ...graph[0], children: known });
106
+ if (unknown)
107
+ result.addUnknown({ ...query[0], children: unknown });
108
+ return;
109
+ }
110
+ if (cmp(key, end) < 0) {
111
+ for (let i = findFirst(graph, key); cmp(key, end) <= 0 && limit > 0; i++) {
112
+ const node = graph[i];
113
+ if (!node || cmp(key, node.key) < 0 || isOlder(node, version))
114
+ break;
115
+ if (isRange(node)) {
116
+ result.addKnown(getOverlap(node, key, end));
117
+ }
118
+ else {
119
+ sliceNode(node, { ...query, key }, result);
120
+ limit--;
121
+ }
122
+ key = keyAfter(node.end || node.key);
123
+ }
124
+ }
125
+ else {
126
+ for (let i = findLast(graph, key) - 1; cmp(key, end) >= 0 && limit > 0; i--) {
127
+ const node = graph[i];
128
+ if (!node || cmp(key, node.end || node.key) > 0 || isOlder(node, version))
129
+ break;
130
+ if (isRange(node)) {
131
+ result.addKnown(getOverlap(node, end, key));
132
+ }
133
+ else {
134
+ sliceNode(node, { ...query, key }, result);
135
+ limit--;
136
+ }
137
+ key = keyBefore(node.key);
138
+ }
139
+ }
140
+ if (limit && (step < 0 ? cmp(key, end) > 0 : cmp(key, end) < 0)) {
141
+ const unknown = { ...query, key, end, limit };
142
+ result.addUnknown(unknown);
143
+ }
144
+ }
145
+ function getOverlap(node, key, end) {
146
+ if (cmp(node.key, key) >= 0 && cmp(node.end, end) <= 0)
147
+ return node;
148
+ return {
149
+ ...node,
150
+ key: cmp(node.key, key) > 0 ? node.key : key,
151
+ end: cmp(node.end, end) < 0 ? node.end : end,
152
+ };
153
+ }
package/ops/step.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare function keyStep(key: any): {
2
+ key: any;
3
+ step: any;
4
+ };
5
+ export declare function keyBefore(key: any): any;
6
+ export declare function keyAfter(key: any): any;
package/ops/step.js ADDED
@@ -0,0 +1,61 @@
1
+ import { addStringify, isMaxKey, isMinKey } from "../util.js";
2
+ export function keyStep(key) {
3
+ if (isMinKey(key))
4
+ return { key, step: 1 };
5
+ if (isMaxKey(key))
6
+ return { key, step: -1 };
7
+ const l = key.length - 1;
8
+ let newKey;
9
+ let step;
10
+ switch (key[l]) {
11
+ case 0:
12
+ newKey = key.slice(0, l);
13
+ addStringify(newKey);
14
+ step = 1;
15
+ break;
16
+ case 0xff:
17
+ newKey = key.slice(0, l);
18
+ addStringify(newKey);
19
+ newKey[l - 1]++;
20
+ step = -1;
21
+ break;
22
+ default:
23
+ newKey = key;
24
+ step = 0;
25
+ }
26
+ return { key: newKey, step };
27
+ }
28
+ export function keyBefore(key) {
29
+ if (isMinKey(key) || isMaxKey(key))
30
+ return key;
31
+ const l = key.length - 1;
32
+ let newKey;
33
+ if (key[l] === 0) {
34
+ newKey = key.slice(0, l);
35
+ }
36
+ else {
37
+ newKey = new Uint8Array(l + 2);
38
+ newKey.set(key, 0);
39
+ newKey[l]--;
40
+ newKey[l + 1] = 0xff;
41
+ }
42
+ addStringify(newKey);
43
+ return newKey;
44
+ }
45
+ export function keyAfter(key) {
46
+ if (isMaxKey(key))
47
+ return key;
48
+ const l = key.length - 1;
49
+ let newKey;
50
+ if (key[l] === 0xff) {
51
+ newKey = key.slice(0, l);
52
+ newKey[l - 1]++;
53
+ }
54
+ else {
55
+ newKey = new Uint8Array(l + 2);
56
+ newKey.set(key, 0);
57
+ newKey[l + 1] = 0;
58
+ }
59
+ addStringify(newKey);
60
+ return newKey;
61
+ }
package/package.json CHANGED
@@ -2,23 +2,29 @@
2
2
  "name": "@graffy/common",
3
3
  "description": "Common libraries that used by various Graffy modules.",
4
4
  "author": "aravind (https://github.com/aravindet)",
5
- "version": "0.19.0",
6
- "main": "./index.cjs",
5
+ "version": "0.19.1-alpha.2",
6
+ "main": "./cjs/index.js",
7
7
  "exports": {
8
- "import": "./index.mjs",
9
- "require": "./index.cjs"
8
+ ".": {
9
+ "import": "./index.js",
10
+ "types": "./index.d.ts"
11
+ },
12
+ "./*": {
13
+ "import": "./*.js",
14
+ "types": "./*.d.ts"
15
+ }
10
16
  },
11
- "module": "./index.mjs",
12
- "types": "./types/index.d.ts",
17
+ "types": "./index.d.ts",
13
18
  "repository": {
14
19
  "type": "git",
15
20
  "url": "git+https://github.com/usegraffy/graffy.git"
16
21
  },
17
22
  "license": "Apache-2.0",
18
23
  "dependencies": {
19
- "lodash": "^4.17.23",
20
24
  "debug": "^4.4.3",
21
- "@graffy/stream": "0.19.0",
25
+ "lodash": "^4.18.1",
26
+ "nanoid": "^5.1.11",
27
+ "@graffy/stream": "0.19.1-alpha.2",
22
28
  "merge-async-iterators": "^0.2.1"
23
29
  }
24
30
  }
@@ -0,0 +1,2 @@
1
+ export { default as makeWatcher } from './makeWatcher.js';
2
+ export { default as mergeStreams } from './mergeStreams.js';
@@ -0,0 +1,10 @@
1
+ export default function makeWatcher(): {
2
+ write: (change: any) => void;
3
+ watch: (...args: any[]) => {
4
+ debugId: string;
5
+ next: () => any;
6
+ return(value: any): any;
7
+ throw(error: any): any;
8
+ [Symbol.asyncIterator](): any;
9
+ };
10
+ };
@@ -0,0 +1,19 @@
1
+ import { makeStream } from '@graffy/stream';
2
+ export default function makeWatcher() {
3
+ const listeners = new Set();
4
+ function write(change) {
5
+ for (const push of listeners)
6
+ push(change);
7
+ }
8
+ function watch(...args) {
9
+ return makeStream((push, _end) => {
10
+ listeners.add(push);
11
+ // We do this instead of binding the first value to a variable
12
+ // to decide between pushing undefined and not making a push.
13
+ if (args.length)
14
+ Promise.resolve(args[0]).then(push);
15
+ return () => listeners.delete(push);
16
+ });
17
+ }
18
+ return { write, watch };
19
+ }
@@ -0,0 +1,20 @@
1
+ import mergeIterators from 'merge-async-iterators';
2
+ import { merge } from "../ops/index.js";
3
+ export default async function* mergeStreams(...streams) {
4
+ const firstValues = (await Promise.all(streams.map((stream) => stream.next()))).map((iter) => iter.value);
5
+ // If even one is a change-only stream, the result is a change-only stream
6
+ if (firstValues.some((value) => typeof value === 'undefined')) {
7
+ yield undefined;
8
+ for (const value of firstValues) {
9
+ if (typeof value !== 'undefined')
10
+ yield value;
11
+ }
12
+ }
13
+ else {
14
+ const merged = [];
15
+ for (const value of firstValues)
16
+ merge(merged, value);
17
+ yield merged;
18
+ }
19
+ yield* mergeIterators(streams);
20
+ }
package/util.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export declare const MIN_KEY: Uint8Array<ArrayBuffer>;
2
+ export declare const MAX_KEY: Uint8Array<ArrayBuffer>;
3
+ export declare function isMinKey(key: any): boolean;
4
+ export declare function isMaxKey(key: any): boolean;
5
+ export declare function err(message: any, { cause, ...args }?: {
6
+ cause?: any;
7
+ }): void;
8
+ export declare function errIf(message: any, condition: any, args?: any): void;
9
+ export declare function isEmpty(object: any): boolean;
10
+ export declare function isDef(value: any): boolean;
11
+ export declare function isPlainObject(arg: any): boolean;
12
+ export declare function clone(obj: any): any;
13
+ export declare function cmp(a: any, b: any): 0 | 1 | -1;
14
+ export declare function find(items: any, compare: any, first?: number, last?: any): number;
15
+ export declare function addStringify(buffer: any): any;
package/util.js ADDED
@@ -0,0 +1,106 @@
1
+ import debug from 'debug';
2
+ const isDebugMode = debug('graffy*').enabled;
3
+ export const MIN_KEY = new Uint8Array();
4
+ export const MAX_KEY = new Uint8Array([0xff]);
5
+ export function isMinKey(key) {
6
+ return key.length === 0;
7
+ }
8
+ export function isMaxKey(key) {
9
+ return key.length === 1 && key[0] === 0xff;
10
+ }
11
+ export function err(message, { cause = null, ...args } = {}) {
12
+ const e = new Error(message + (args ? ` ${JSON.stringify(args)}` : ''));
13
+ e.cause = cause;
14
+ throw e;
15
+ }
16
+ export function errIf(message, condition, args) {
17
+ if (condition)
18
+ err(message, args);
19
+ }
20
+ export function isEmpty(object) {
21
+ for (const _ in object)
22
+ return false;
23
+ return true;
24
+ }
25
+ export function isDef(value) {
26
+ return typeof value !== 'undefined';
27
+ }
28
+ export function isPlainObject(arg) {
29
+ return (typeof arg === 'object' &&
30
+ arg &&
31
+ !Array.isArray(arg) &&
32
+ !ArrayBuffer.isView(arg));
33
+ }
34
+ export function clone(obj) {
35
+ if (Array.isArray(obj)) {
36
+ return obj.slice(0);
37
+ }
38
+ return { ...obj };
39
+ }
40
+ export function cmp(a, b) {
41
+ const l = a.length < b.length ? a.length : b.length;
42
+ for (let i = 0; i < l; i++) {
43
+ if (a[i] < b[i])
44
+ return -1;
45
+ if (a[i] > b[i])
46
+ return 1;
47
+ }
48
+ if (a.length < b.length)
49
+ return -1;
50
+ if (a.length > b.length)
51
+ return 1;
52
+ return 0;
53
+ }
54
+ export function find(items, compare, first = 0, last = items.length) {
55
+ let currentFirst = first;
56
+ let currentLast = last;
57
+ while (currentFirst < currentLast) {
58
+ // console.log(currentFirst, currentLast);
59
+ const ix = ((currentFirst + currentLast) / 2) | 0;
60
+ const d = compare(items[ix]);
61
+ // console.log(ix, items[ix], d);
62
+ if (d < 0) {
63
+ currentFirst = ix + 1;
64
+ }
65
+ else if (d > 0) {
66
+ currentLast = ix;
67
+ }
68
+ else {
69
+ return ix;
70
+ }
71
+ }
72
+ return currentFirst;
73
+ }
74
+ function stringify() {
75
+ if (this?.length === 0)
76
+ return '\u00b7';
77
+ let str = '';
78
+ let bull = false;
79
+ this?.forEach?.((value, i) => {
80
+ if (value >= 32 && value <= 126) {
81
+ str += String.fromCharCode(value);
82
+ bull = true;
83
+ }
84
+ else {
85
+ str +=
86
+ (bull ? '\u00b7' : '') +
87
+ `0${value.toString(16)}`.slice(-2) +
88
+ (i < this.length - 1 ? '\u00b7' : '');
89
+ bull = false;
90
+ }
91
+ });
92
+ return str;
93
+ }
94
+ const inspectSymbol = Symbol.for('nodejs.util.inspect.custom');
95
+ export function addStringify(buffer) {
96
+ if (!isDebugMode)
97
+ return buffer;
98
+ if ('toJSON' in buffer || inspectSymbol in buffer)
99
+ return buffer;
100
+ buffer.toJSON = stringify;
101
+ buffer.toString = stringify;
102
+ buffer[inspectSymbol] = stringify;
103
+ return buffer;
104
+ }
105
+ addStringify(MIN_KEY);
106
+ addStringify(MAX_KEY);