@graffy/fill 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.
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export default function fill(_?: any): (store: any) => void;
package/index.js ADDED
@@ -0,0 +1,42 @@
1
+ import { merge, slice } from '@graffy/common';
2
+ import debug from 'debug';
3
+ import subscribe from "./subscribe.js";
4
+ const log = debug('graffy:fill');
5
+ const MAX_RECURSIONS = 10;
6
+ export default function fill(_ = undefined) {
7
+ return (store) => {
8
+ store.on('read', [], async function fillOnRead(query, options, next) {
9
+ let value = await next(query);
10
+ if (options.skipFill)
11
+ return value;
12
+ if (!value?.length) {
13
+ log('No progress', query);
14
+ throw Error('fill.no_progress');
15
+ // return null;
16
+ }
17
+ let budget = MAX_RECURSIONS;
18
+ while (budget-- > 1) {
19
+ // console.log('filled value', value);
20
+ const { known, unknown } = slice(value, query);
21
+ value = known;
22
+ if (!unknown)
23
+ break;
24
+ // console.log('unknown', unknown);
25
+ const res = await store.call('read', unknown, { skipFill: true });
26
+ // console.log('fetched', res);
27
+ merge(value, res);
28
+ }
29
+ if (!budget) {
30
+ log('fill.max_recursion', slice(value, query).unknown);
31
+ throw new Error('fill.max_recursion');
32
+ }
33
+ // console.log('Read', debug(query), 'returned', debug(value));
34
+ return value;
35
+ });
36
+ store.on('watch', [], function fillOnWatch(query, options, next) {
37
+ if (options.skipFill)
38
+ return next(query);
39
+ return subscribe(store, query, options);
40
+ });
41
+ };
42
+ }
package/package.json CHANGED
@@ -2,22 +2,27 @@
2
2
  "name": "@graffy/fill",
3
3
  "description": "Graffy module for fulfilling queries using multiple backends, traversing links and turning subscriptions into live queries.",
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
- "@graffy/common": "0.19.0",
20
- "debug": "^4.4.3",
21
- "@graffy/stream": "0.19.0"
24
+ "@graffy/common": "0.19.1-alpha.2",
25
+ "@graffy/stream": "0.19.1-alpha.2",
26
+ "debug": "^4.4.3"
22
27
  }
23
28
  }
package/subscribe.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export default function subscribe(store: any, originalQuery: any, { raw }: {
2
+ raw: any;
3
+ }): {
4
+ debugId: string;
5
+ next: () => any;
6
+ return(value: any): any;
7
+ throw(error: any): any;
8
+ [Symbol.asyncIterator](): any;
9
+ };
package/subscribe.js ADDED
@@ -0,0 +1,130 @@
1
+ import { add, finalize, merge, sieve, slice } from '@graffy/common';
2
+ import { makeStream } from '@graffy/stream';
3
+ import debug from 'debug';
4
+ const log = debug('graffy:fill:subscribe');
5
+ export default function subscribe(store, originalQuery, { raw }) {
6
+ const empty = () => finalize([], originalQuery, 0);
7
+ let push;
8
+ let end;
9
+ let upstream;
10
+ const query = [];
11
+ let data = empty();
12
+ let payload = [];
13
+ const stream = makeStream((streamPush, streamEnd) => {
14
+ push = (v) => {
15
+ log('Push', v);
16
+ streamPush(v);
17
+ };
18
+ end = streamEnd;
19
+ return unsubscribe;
20
+ });
21
+ resubscribe(originalQuery);
22
+ return stream;
23
+ async function resubscribe(unknown) {
24
+ try {
25
+ const changed = add(query, unknown);
26
+ log(changed ? 'Resubscribing' : 'Not resubscribing', unknown);
27
+ if (!changed)
28
+ return;
29
+ if (upstream)
30
+ upstream.return(); // Close the existing stream.
31
+ upstream = store.call('watch', query, { skipFill: true });
32
+ let { value } = await upstream.next();
33
+ log('First payload', typeof value, value);
34
+ if (typeof value === 'undefined') {
35
+ // The upstream is a change subscription, not a live query,
36
+ // so we need to fetch the initial value.
37
+ // TODO: Get a version corresponding to the subscription's start
38
+ // and verify that the store.read response is newer.
39
+ value = await store.call('read', unknown, { skipCache: true });
40
+ log('Read initial value', value);
41
+ }
42
+ // value = value && slice(value, unknown).known;
43
+ putValue(value, false);
44
+ }
45
+ catch (e) {
46
+ log('resubscribe error', e);
47
+ error(e);
48
+ }
49
+ putStream(upstream);
50
+ }
51
+ async function putStream(stream) {
52
+ // TODO: Backpressure: pause pulling if downstream listener is saturated.
53
+ log('Start putting stream');
54
+ try {
55
+ for await (const value of stream)
56
+ putValue(value, true);
57
+ }
58
+ catch (e) {
59
+ error(e);
60
+ }
61
+ }
62
+ function putValue(value, isChange) {
63
+ if (typeof value === 'undefined')
64
+ return;
65
+ log('Put', isChange ? 'Change' : 'Value', typeof value);
66
+ if (value === null) {
67
+ // No results exist at this moment.
68
+ data = empty();
69
+ push(null);
70
+ return;
71
+ }
72
+ // We do this to ensure that everything in value gets incorporated
73
+ // into data, even as we use sieve to ensure only actual changes are
74
+ // added to payload.
75
+ // if (!isChange) merge(data, [{ key: '', end: '\uffff', version: -1 }]);
76
+ // log('Data before sieve', (data));
77
+ let sieved;
78
+ if (isChange) {
79
+ sieved = sieve(data, value);
80
+ }
81
+ else {
82
+ sieved = slice(value, query).known;
83
+ if (sieved)
84
+ merge(data, sieved);
85
+ }
86
+ log('Sieved: ', sieved && sieved);
87
+ if (raw && sieved) {
88
+ // log('Payload before adding sieved', (payload));
89
+ merge(payload, sieved);
90
+ // log('Payload after adding sieved', (payload));
91
+ }
92
+ // The new value might have removed a link, making parts of
93
+ // data unnecessary, or added a link, introducing
94
+ // new data requirements. Let's find out.
95
+ let { known, unknown } = slice(data, originalQuery);
96
+ data = known || empty();
97
+ log('Data and unknown', data, unknown && unknown);
98
+ log('Payload and value', payload, value && value);
99
+ if (isChange && value && unknown) {
100
+ // The sieve may have removed some necessary data (that we weren't aware
101
+ // was necessary). Get it back.
102
+ const valueParts = slice(value, unknown);
103
+ if (valueParts.known) {
104
+ merge(data, valueParts.known);
105
+ if (raw)
106
+ merge(payload, valueParts.known);
107
+ unknown = valueParts.unknown;
108
+ }
109
+ }
110
+ if (unknown)
111
+ return resubscribe(unknown);
112
+ if (!raw) {
113
+ if (!isChange || sieved?.length)
114
+ push(data);
115
+ }
116
+ else if (payload.length) {
117
+ push(payload);
118
+ payload = [];
119
+ }
120
+ }
121
+ function error(e) {
122
+ if (end)
123
+ end(e);
124
+ unsubscribe();
125
+ }
126
+ function unsubscribe() {
127
+ if (upstream)
128
+ upstream.return();
129
+ }
130
+ }
package/index.cjs DELETED
@@ -1,130 +0,0 @@
1
- "use strict";
2
- const common = require("@graffy/common");
3
- const debug = require("debug");
4
- const stream = require("@graffy/stream");
5
- const log$1 = debug("graffy:fill:subscribe");
6
- function subscribe(store, originalQuery, { raw }) {
7
- const empty = () => common.finalize([], originalQuery, 0);
8
- let push;
9
- let end;
10
- let upstream;
11
- const query = [];
12
- let data = empty();
13
- let payload = [];
14
- const stream$1 = stream.makeStream((streamPush, streamEnd) => {
15
- push = (v) => {
16
- log$1("Push", v);
17
- streamPush(v);
18
- };
19
- end = streamEnd;
20
- return unsubscribe;
21
- });
22
- resubscribe(originalQuery);
23
- return stream$1;
24
- async function resubscribe(unknown) {
25
- try {
26
- const changed = common.add(query, unknown);
27
- log$1(changed ? "Resubscribing" : "Not resubscribing", unknown);
28
- if (!changed) return;
29
- if (upstream) upstream.return();
30
- upstream = store.call("watch", query, { skipFill: true });
31
- let { value } = await upstream.next();
32
- log$1("First payload", typeof value, value);
33
- if (typeof value === "undefined") {
34
- value = await store.call("read", unknown, { skipCache: true });
35
- log$1("Read initial value", value);
36
- }
37
- putValue(value, false);
38
- } catch (e) {
39
- log$1("resubscribe error", e);
40
- error(e);
41
- }
42
- putStream(upstream);
43
- }
44
- async function putStream(stream2) {
45
- log$1("Start putting stream");
46
- try {
47
- for await (const value of stream2) putValue(value, true);
48
- } catch (e) {
49
- error(e);
50
- }
51
- }
52
- function putValue(value, isChange) {
53
- if (typeof value === "undefined") return;
54
- log$1("Put", isChange ? "Change" : "Value", typeof value);
55
- if (value === null) {
56
- data = empty();
57
- push(null);
58
- return;
59
- }
60
- let sieved;
61
- if (isChange) {
62
- sieved = common.sieve(data, value);
63
- } else {
64
- sieved = common.slice(value, query).known;
65
- if (sieved) common.merge(data, sieved);
66
- }
67
- log$1("Sieved: ", sieved && sieved);
68
- if (raw && sieved) {
69
- common.merge(payload, sieved);
70
- }
71
- let { known, unknown } = common.slice(data, originalQuery);
72
- data = known || empty();
73
- log$1("Data and unknown", data, unknown && unknown);
74
- log$1("Payload and value", payload, value && value);
75
- if (isChange && value && unknown) {
76
- const valueParts = common.slice(value, unknown);
77
- if (valueParts.known) {
78
- common.merge(data, valueParts.known);
79
- if (raw) common.merge(payload, valueParts.known);
80
- unknown = valueParts.unknown;
81
- }
82
- }
83
- if (unknown) return resubscribe(unknown);
84
- if (!raw) {
85
- if (!isChange || sieved?.length) push(data);
86
- } else if (payload.length) {
87
- push(payload);
88
- payload = [];
89
- }
90
- }
91
- function error(e) {
92
- if (end) end(e);
93
- unsubscribe();
94
- }
95
- function unsubscribe() {
96
- if (upstream) upstream.return();
97
- }
98
- }
99
- const log = debug("graffy:fill");
100
- const MAX_RECURSIONS = 10;
101
- function fill(_) {
102
- return (store) => {
103
- store.on("read", [], async function fillOnRead(query, options, next) {
104
- let value = await next(query);
105
- if (options.skipFill) return value;
106
- if (!value?.length) {
107
- log("No progress", query);
108
- throw Error("fill.no_progress");
109
- }
110
- let budget = MAX_RECURSIONS;
111
- while (budget-- > 1) {
112
- const { known, unknown } = common.slice(value, query);
113
- value = known;
114
- if (!unknown) break;
115
- const res = await store.call("read", unknown, { skipFill: true });
116
- common.merge(value, res);
117
- }
118
- if (!budget) {
119
- log("fill.max_recursion", common.slice(value, query).unknown);
120
- throw new Error("fill.max_recursion");
121
- }
122
- return value;
123
- });
124
- store.on("watch", [], function fillOnWatch(query, options, next) {
125
- if (options.skipFill) return next(query);
126
- return subscribe(store, query, options);
127
- });
128
- };
129
- }
130
- module.exports = fill;
package/index.mjs DELETED
@@ -1,131 +0,0 @@
1
- import { finalize, add, sieve, slice, merge } from "@graffy/common";
2
- import debug from "debug";
3
- import { makeStream } from "@graffy/stream";
4
- const log$1 = debug("graffy:fill:subscribe");
5
- function subscribe(store, originalQuery, { raw }) {
6
- const empty = () => finalize([], originalQuery, 0);
7
- let push;
8
- let end;
9
- let upstream;
10
- const query = [];
11
- let data = empty();
12
- let payload = [];
13
- const stream = makeStream((streamPush, streamEnd) => {
14
- push = (v) => {
15
- log$1("Push", v);
16
- streamPush(v);
17
- };
18
- end = streamEnd;
19
- return unsubscribe;
20
- });
21
- resubscribe(originalQuery);
22
- return stream;
23
- async function resubscribe(unknown) {
24
- try {
25
- const changed = add(query, unknown);
26
- log$1(changed ? "Resubscribing" : "Not resubscribing", unknown);
27
- if (!changed) return;
28
- if (upstream) upstream.return();
29
- upstream = store.call("watch", query, { skipFill: true });
30
- let { value } = await upstream.next();
31
- log$1("First payload", typeof value, value);
32
- if (typeof value === "undefined") {
33
- value = await store.call("read", unknown, { skipCache: true });
34
- log$1("Read initial value", value);
35
- }
36
- putValue(value, false);
37
- } catch (e) {
38
- log$1("resubscribe error", e);
39
- error(e);
40
- }
41
- putStream(upstream);
42
- }
43
- async function putStream(stream2) {
44
- log$1("Start putting stream");
45
- try {
46
- for await (const value of stream2) putValue(value, true);
47
- } catch (e) {
48
- error(e);
49
- }
50
- }
51
- function putValue(value, isChange) {
52
- if (typeof value === "undefined") return;
53
- log$1("Put", isChange ? "Change" : "Value", typeof value);
54
- if (value === null) {
55
- data = empty();
56
- push(null);
57
- return;
58
- }
59
- let sieved;
60
- if (isChange) {
61
- sieved = sieve(data, value);
62
- } else {
63
- sieved = slice(value, query).known;
64
- if (sieved) merge(data, sieved);
65
- }
66
- log$1("Sieved: ", sieved && sieved);
67
- if (raw && sieved) {
68
- merge(payload, sieved);
69
- }
70
- let { known, unknown } = slice(data, originalQuery);
71
- data = known || empty();
72
- log$1("Data and unknown", data, unknown && unknown);
73
- log$1("Payload and value", payload, value && value);
74
- if (isChange && value && unknown) {
75
- const valueParts = slice(value, unknown);
76
- if (valueParts.known) {
77
- merge(data, valueParts.known);
78
- if (raw) merge(payload, valueParts.known);
79
- unknown = valueParts.unknown;
80
- }
81
- }
82
- if (unknown) return resubscribe(unknown);
83
- if (!raw) {
84
- if (!isChange || sieved?.length) push(data);
85
- } else if (payload.length) {
86
- push(payload);
87
- payload = [];
88
- }
89
- }
90
- function error(e) {
91
- if (end) end(e);
92
- unsubscribe();
93
- }
94
- function unsubscribe() {
95
- if (upstream) upstream.return();
96
- }
97
- }
98
- const log = debug("graffy:fill");
99
- const MAX_RECURSIONS = 10;
100
- function fill(_) {
101
- return (store) => {
102
- store.on("read", [], async function fillOnRead(query, options, next) {
103
- let value = await next(query);
104
- if (options.skipFill) return value;
105
- if (!value?.length) {
106
- log("No progress", query);
107
- throw Error("fill.no_progress");
108
- }
109
- let budget = MAX_RECURSIONS;
110
- while (budget-- > 1) {
111
- const { known, unknown } = slice(value, query);
112
- value = known;
113
- if (!unknown) break;
114
- const res = await store.call("read", unknown, { skipFill: true });
115
- merge(value, res);
116
- }
117
- if (!budget) {
118
- log("fill.max_recursion", slice(value, query).unknown);
119
- throw new Error("fill.max_recursion");
120
- }
121
- return value;
122
- });
123
- store.on("watch", [], function fillOnWatch(query, options, next) {
124
- if (options.skipFill) return next(query);
125
- return subscribe(store, query, options);
126
- });
127
- };
128
- }
129
- export {
130
- fill as default
131
- };
package/types/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export default function fill(_: any): (store: any) => void;
@@ -1,15 +0,0 @@
1
- export default function subscribe(store: any, originalQuery: any, { raw }: {
2
- raw: any;
3
- }): {
4
- debugId: any;
5
- next: () => any;
6
- return(value: any): Promise<{
7
- value: any;
8
- done: boolean;
9
- }>;
10
- throw(error: any): Promise<{
11
- value: any;
12
- done: boolean;
13
- }>;
14
- [Symbol.asyncIterator](): /*elided*/ any;
15
- };