houdini 0.13.7-alpha.3 → 0.13.7
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/build/cmd.js
CHANGED
|
@@ -2595,7 +2595,7 @@ pp$1$1.parseClass = function(node, isStatement) {
|
|
|
2595
2595
|
};
|
|
2596
2596
|
|
|
2597
2597
|
pp$1$1.parseClassElement = function(constructorAllowsSuper) {
|
|
2598
|
-
var this$1
|
|
2598
|
+
var this$1 = this;
|
|
2599
2599
|
|
|
2600
2600
|
if (this.eat(types$2$1.semi)) { return null }
|
|
2601
2601
|
|
|
@@ -2603,14 +2603,14 @@ pp$1$1.parseClassElement = function(constructorAllowsSuper) {
|
|
|
2603
2603
|
var tryContextual = function (k, noLineBreak) {
|
|
2604
2604
|
if ( noLineBreak === void 0 ) noLineBreak = false;
|
|
2605
2605
|
|
|
2606
|
-
var start = this$1
|
|
2607
|
-
if (!this$1
|
|
2608
|
-
if (this$1
|
|
2609
|
-
if (method.key) { this$1
|
|
2606
|
+
var start = this$1.start, startLoc = this$1.startLoc;
|
|
2607
|
+
if (!this$1.eatContextual(k)) { return false }
|
|
2608
|
+
if (this$1.type !== types$2$1.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
|
|
2609
|
+
if (method.key) { this$1.unexpected(); }
|
|
2610
2610
|
method.computed = false;
|
|
2611
|
-
method.key = this$1
|
|
2611
|
+
method.key = this$1.startNodeAt(start, startLoc);
|
|
2612
2612
|
method.key.name = k;
|
|
2613
|
-
this$1
|
|
2613
|
+
this$1.finishNode(method.key, "Identifier");
|
|
2614
2614
|
return false
|
|
2615
2615
|
};
|
|
2616
2616
|
|
|
@@ -5621,11 +5621,11 @@ pp$9$1.getToken = function() {
|
|
|
5621
5621
|
// If we're in an ES6 environment, make parsers iterable
|
|
5622
5622
|
if (typeof Symbol !== "undefined")
|
|
5623
5623
|
{ pp$9$1[Symbol.iterator] = function() {
|
|
5624
|
-
var this$1
|
|
5624
|
+
var this$1 = this;
|
|
5625
5625
|
|
|
5626
5626
|
return {
|
|
5627
5627
|
next: function () {
|
|
5628
|
-
var token = this$1
|
|
5628
|
+
var token = this$1.getToken();
|
|
5629
5629
|
return {
|
|
5630
5630
|
done: token.type === types$2$1.eof,
|
|
5631
5631
|
value: token
|
|
@@ -6531,10 +6531,10 @@ function visit$1(
|
|
|
6531
6531
|
return node;
|
|
6532
6532
|
}
|
|
6533
6533
|
|
|
6534
|
-
var charToInteger
|
|
6535
|
-
var chars
|
|
6536
|
-
for (var i$
|
|
6537
|
-
charToInteger
|
|
6534
|
+
var charToInteger = {};
|
|
6535
|
+
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
6536
|
+
for (var i$2 = 0; i$2 < chars.length; i$2++) {
|
|
6537
|
+
charToInteger[chars.charCodeAt(i$2)] = i$2;
|
|
6538
6538
|
}
|
|
6539
6539
|
function decode(mappings) {
|
|
6540
6540
|
var decoded = [];
|
|
@@ -6561,7 +6561,7 @@ function decode(mappings) {
|
|
|
6561
6561
|
segment[0] = 0;
|
|
6562
6562
|
}
|
|
6563
6563
|
else {
|
|
6564
|
-
var integer = charToInteger
|
|
6564
|
+
var integer = charToInteger[c];
|
|
6565
6565
|
if (integer === undefined) {
|
|
6566
6566
|
throw new Error('Invalid character (' + String.fromCharCode(c) + ')');
|
|
6567
6567
|
}
|
|
@@ -16411,10 +16411,10 @@ Object.keys(attribute_lookup$1).forEach(name => {
|
|
|
16411
16411
|
metadata.property_name = name;
|
|
16412
16412
|
});
|
|
16413
16413
|
|
|
16414
|
-
var charToInteger$1
|
|
16415
|
-
var chars$1
|
|
16416
|
-
for (var i$2$
|
|
16417
|
-
charToInteger$1
|
|
16414
|
+
var charToInteger$1 = {};
|
|
16415
|
+
var chars$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
16416
|
+
for (var i$2$1 = 0; i$2$1 < chars$1.length; i$2$1++) {
|
|
16417
|
+
charToInteger$1[chars$1.charCodeAt(i$2$1)] = i$2$1;
|
|
16418
16418
|
}
|
|
16419
16419
|
function decode$1(mappings) {
|
|
16420
16420
|
var decoded = [];
|
|
@@ -16441,7 +16441,7 @@ function decode$1(mappings) {
|
|
|
16441
16441
|
segment[0] = 0;
|
|
16442
16442
|
}
|
|
16443
16443
|
else {
|
|
16444
|
-
var integer = charToInteger$1
|
|
16444
|
+
var integer = charToInteger$1[c];
|
|
16445
16445
|
if (integer === undefined) {
|
|
16446
16446
|
throw new Error('Invalid character (' + String.fromCharCode(c) + ')');
|
|
16447
16447
|
}
|
|
@@ -16528,7 +16528,7 @@ function encodeInteger$1(num) {
|
|
|
16528
16528
|
if (num > 0) {
|
|
16529
16529
|
clamped |= 32;
|
|
16530
16530
|
}
|
|
16531
|
-
result += chars$1
|
|
16531
|
+
result += chars$1[clamped];
|
|
16532
16532
|
} while (num > 0);
|
|
16533
16533
|
return result;
|
|
16534
16534
|
}
|
|
@@ -35890,13 +35890,10 @@ globSync$1.GlobSync = GlobSync$1;
|
|
|
35890
35890
|
var fs$3 = fs$2$1;
|
|
35891
35891
|
var rp$1 = fs_realpath;
|
|
35892
35892
|
var minimatch$1 = minimatch_1;
|
|
35893
|
-
glob_1.Glob;
|
|
35894
35893
|
var path$3 = path$6;
|
|
35895
35894
|
var assert$3 = require$$1$3;
|
|
35896
35895
|
var isAbsolute$1 = pathIsAbsolute.exports;
|
|
35897
35896
|
var common$1 = common$2;
|
|
35898
|
-
common$1.alphasort;
|
|
35899
|
-
common$1.alphasorti;
|
|
35900
35897
|
var setopts$1 = common$1.setopts;
|
|
35901
35898
|
var ownProp$1 = common$1.ownProp;
|
|
35902
35899
|
var childrenIgnored$1 = common$1.childrenIgnored;
|
|
@@ -36551,8 +36548,6 @@ var assert$2 = require$$1$3;
|
|
|
36551
36548
|
var isAbsolute = pathIsAbsolute.exports;
|
|
36552
36549
|
var globSync = sync;
|
|
36553
36550
|
var common = common$2;
|
|
36554
|
-
common.alphasort;
|
|
36555
|
-
common.alphasorti;
|
|
36556
36551
|
var setopts = common.setopts;
|
|
36557
36552
|
var ownProp = common.ownProp;
|
|
36558
36553
|
var inflight = inflight_1;
|
|
@@ -38625,7 +38620,7 @@ pp$1.parseClass = function(node, isStatement) {
|
|
|
38625
38620
|
};
|
|
38626
38621
|
|
|
38627
38622
|
pp$1.parseClassElement = function(constructorAllowsSuper) {
|
|
38628
|
-
var this$1
|
|
38623
|
+
var this$1 = this;
|
|
38629
38624
|
|
|
38630
38625
|
if (this.eat(types$7.semi)) { return null }
|
|
38631
38626
|
|
|
@@ -38633,14 +38628,14 @@ pp$1.parseClassElement = function(constructorAllowsSuper) {
|
|
|
38633
38628
|
var tryContextual = function (k, noLineBreak) {
|
|
38634
38629
|
if ( noLineBreak === void 0 ) noLineBreak = false;
|
|
38635
38630
|
|
|
38636
|
-
var start = this$1
|
|
38637
|
-
if (!this$1
|
|
38638
|
-
if (this$1
|
|
38639
|
-
if (method.key) { this$1
|
|
38631
|
+
var start = this$1.start, startLoc = this$1.startLoc;
|
|
38632
|
+
if (!this$1.eatContextual(k)) { return false }
|
|
38633
|
+
if (this$1.type !== types$7.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true }
|
|
38634
|
+
if (method.key) { this$1.unexpected(); }
|
|
38640
38635
|
method.computed = false;
|
|
38641
|
-
method.key = this$1
|
|
38636
|
+
method.key = this$1.startNodeAt(start, startLoc);
|
|
38642
38637
|
method.key.name = k;
|
|
38643
|
-
this$1
|
|
38638
|
+
this$1.finishNode(method.key, "Identifier");
|
|
38644
38639
|
return false
|
|
38645
38640
|
};
|
|
38646
38641
|
|
|
@@ -41651,11 +41646,11 @@ pp$9.getToken = function() {
|
|
|
41651
41646
|
// If we're in an ES6 environment, make parsers iterable
|
|
41652
41647
|
if (typeof Symbol !== "undefined")
|
|
41653
41648
|
{ pp$9[Symbol.iterator] = function() {
|
|
41654
|
-
var this$1
|
|
41649
|
+
var this$1 = this;
|
|
41655
41650
|
|
|
41656
41651
|
return {
|
|
41657
41652
|
next: function () {
|
|
41658
|
-
var token = this$1
|
|
41653
|
+
var token = this$1.getToken();
|
|
41659
41654
|
return {
|
|
41660
41655
|
done: token.type === types$7.eof,
|
|
41661
41656
|
value: token
|
|
@@ -42550,12 +42545,6 @@ function visit(
|
|
|
42550
42545
|
return node;
|
|
42551
42546
|
}
|
|
42552
42547
|
|
|
42553
|
-
var charToInteger = {};
|
|
42554
|
-
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
42555
|
-
for (var i$2 = 0; i$2 < chars.length; i$2++) {
|
|
42556
|
-
charToInteger[chars.charCodeAt(i$2)] = i$2;
|
|
42557
|
-
}
|
|
42558
|
-
|
|
42559
42548
|
// generate an ID that is, to all intents and purposes, unique
|
|
42560
42549
|
const id = (Math.round(Math.random() * 1e20)).toString(36);
|
|
42561
42550
|
const re = new RegExp(`_${id}_(?:(\\d+)|(AT)|(HASH))_(\\w+)?`, 'g');
|
|
@@ -50549,12 +50538,6 @@ Object.keys(attribute_lookup).forEach(name => {
|
|
|
50549
50538
|
metadata.property_name = name;
|
|
50550
50539
|
});
|
|
50551
50540
|
|
|
50552
|
-
var charToInteger$1 = {};
|
|
50553
|
-
var chars$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
50554
|
-
for (var i$2$1 = 0; i$2$1 < chars$1.length; i$2$1++) {
|
|
50555
|
-
charToInteger$1[chars$1.charCodeAt(i$2$1)] = i$2$1;
|
|
50556
|
-
}
|
|
50557
|
-
|
|
50558
50541
|
/* istanbul ignore next */
|
|
50559
50542
|
(typeof URL !== 'undefined' ? URL : require('url').URL);
|
|
50560
50543
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "houdini",
|
|
3
|
-
"version": "0.13.7
|
|
3
|
+
"version": "0.13.7",
|
|
4
4
|
"description": "The disappearing graphql client for SvelteKit",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build:runtime": "npm run build:runtime:cjs && npm run build:runtime:esm",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"rollup-plugin-preserve-shebangs": "^0.2.0",
|
|
58
58
|
"svelte": "^3.34.0"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "c83fd91b92e7be3b35604824c25d6fc0759fb458"
|
|
61
61
|
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { SubscriptionSelection, ListWhen, SubscriptionSpec } from '../types';
|
|
2
|
-
import { Cache } from './cache';
|
|
3
|
-
import { Record } from './record';
|
|
4
|
-
export declare class ListHandler {
|
|
5
|
-
readonly record: Record;
|
|
6
|
-
readonly key: string;
|
|
7
|
-
readonly listType: string;
|
|
8
|
-
private cache;
|
|
9
|
-
readonly selection: SubscriptionSelection;
|
|
10
|
-
private _when?;
|
|
11
|
-
private filters?;
|
|
12
|
-
readonly name: string;
|
|
13
|
-
readonly parentID: SubscriptionSpec['parentID'];
|
|
14
|
-
private connection;
|
|
15
|
-
constructor({ name, cache, record, key, listType, selection, when, filters, parentID, connection, }: {
|
|
16
|
-
name: string;
|
|
17
|
-
connection: boolean;
|
|
18
|
-
cache: Cache;
|
|
19
|
-
record: Record;
|
|
20
|
-
key: string;
|
|
21
|
-
listType: string;
|
|
22
|
-
selection: SubscriptionSelection;
|
|
23
|
-
when?: ListWhen;
|
|
24
|
-
filters?: ListHandler['filters'];
|
|
25
|
-
parentID?: SubscriptionSpec['parentID'];
|
|
26
|
-
});
|
|
27
|
-
when(when?: ListWhen): ListHandler;
|
|
28
|
-
append(selection: SubscriptionSelection, data: {}, variables?: {}): void;
|
|
29
|
-
prepend(selection: SubscriptionSelection, data: {}, variables?: {}): void;
|
|
30
|
-
addToList(selection: SubscriptionSelection, data: {}, variables: {}, where: 'first' | 'last'): void;
|
|
31
|
-
removeID(id: string, variables?: {}): void;
|
|
32
|
-
remove(data: {}, variables?: {}): void;
|
|
33
|
-
private validateWhen;
|
|
34
|
-
[Symbol.iterator](): Generator<Record, void, unknown>;
|
|
35
|
-
}
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
export class ListHandler {
|
|
2
|
-
constructor({ name, cache, record, key, listType, selection, when, filters, parentID, connection, }) {
|
|
3
|
-
this.record = record;
|
|
4
|
-
this.key = key;
|
|
5
|
-
this.listType = listType;
|
|
6
|
-
this.cache = cache;
|
|
7
|
-
this.selection = selection;
|
|
8
|
-
this._when = when;
|
|
9
|
-
this.filters = filters;
|
|
10
|
-
this.name = name;
|
|
11
|
-
this.parentID = parentID;
|
|
12
|
-
this.connection = connection;
|
|
13
|
-
}
|
|
14
|
-
// when applies a when condition to a new list pointing to the same spot
|
|
15
|
-
when(when) {
|
|
16
|
-
return new ListHandler({
|
|
17
|
-
cache: this.cache,
|
|
18
|
-
record: this.record,
|
|
19
|
-
key: this.key,
|
|
20
|
-
listType: this.listType,
|
|
21
|
-
selection: this.selection,
|
|
22
|
-
when,
|
|
23
|
-
filters: this.filters,
|
|
24
|
-
parentID: this.parentID,
|
|
25
|
-
name: this.name,
|
|
26
|
-
connection: this.connection,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
append(selection, data, variables = {}) {
|
|
30
|
-
return this.addToList(selection, data, variables, 'last');
|
|
31
|
-
}
|
|
32
|
-
prepend(selection, data, variables = {}) {
|
|
33
|
-
return this.addToList(selection, data, variables, 'first');
|
|
34
|
-
}
|
|
35
|
-
addToList(selection, data, variables = {}, where) {
|
|
36
|
-
// figure out the id of the type we are adding
|
|
37
|
-
const dataID = this.cache.id(this.listType, data);
|
|
38
|
-
// if there are conditions for this operation
|
|
39
|
-
if (!this.validateWhen() || !dataID) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
// we are going to implement the insert as a write with an update flag on a field
|
|
43
|
-
// that matches the key of the list. We'll have to embed the lists data and selection
|
|
44
|
-
// in the appropriate objects
|
|
45
|
-
let insertSelection = selection;
|
|
46
|
-
let insertData = data;
|
|
47
|
-
// if we are wrapping a connection, we have to embed the data under edges > node
|
|
48
|
-
if (this.connection) {
|
|
49
|
-
insertSelection = {
|
|
50
|
-
newEntry: {
|
|
51
|
-
keyRaw: this.key,
|
|
52
|
-
type: 'Connection',
|
|
53
|
-
fields: {
|
|
54
|
-
edges: {
|
|
55
|
-
keyRaw: 'edges',
|
|
56
|
-
type: 'ConnectionEdge',
|
|
57
|
-
update: (where === 'first' ? 'prepend' : 'append'),
|
|
58
|
-
fields: {
|
|
59
|
-
node: {
|
|
60
|
-
type: this.listType,
|
|
61
|
-
keyRaw: 'node',
|
|
62
|
-
fields: {
|
|
63
|
-
...selection,
|
|
64
|
-
__typename: {
|
|
65
|
-
keyRaw: '__typename',
|
|
66
|
-
type: 'String',
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
insertData = {
|
|
76
|
-
newEntry: {
|
|
77
|
-
edges: [{ node: { ...data, __typename: this.listType } }],
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
insertSelection = {
|
|
83
|
-
newEntries: {
|
|
84
|
-
keyRaw: this.key,
|
|
85
|
-
type: this.listType,
|
|
86
|
-
update: (where === 'first' ? 'prepend' : 'append'),
|
|
87
|
-
fields: {
|
|
88
|
-
...selection,
|
|
89
|
-
__typename: {
|
|
90
|
-
keyRaw: '__typename',
|
|
91
|
-
type: 'String',
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
insertData = {
|
|
97
|
-
newEntries: [{ ...data, __typename: this.listType }],
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
// get the list of specs that are subscribing to the list
|
|
101
|
-
const subscribers = this.record.getSubscribers(this.key);
|
|
102
|
-
// look up the new record in the cache
|
|
103
|
-
const newRecord = this.cache.internal.record(dataID);
|
|
104
|
-
// walk down the list fields relative to the new record
|
|
105
|
-
// and make sure all of the list's subscribers are listening
|
|
106
|
-
// to that object
|
|
107
|
-
this.cache.internal.insertSubscribers(newRecord, selection, variables, ...subscribers);
|
|
108
|
-
// update the cache with the data we just found
|
|
109
|
-
this.cache.write({
|
|
110
|
-
selection: insertSelection,
|
|
111
|
-
data: insertData,
|
|
112
|
-
variables,
|
|
113
|
-
parent: this.record.id,
|
|
114
|
-
applyUpdates: true,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
removeID(id, variables = {}) {
|
|
118
|
-
// if there are conditions for this operation
|
|
119
|
-
if (!this.validateWhen()) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
// if we are removing from a connection, the id we are removing from
|
|
123
|
-
// has to be computed
|
|
124
|
-
let parentID = this.record.id;
|
|
125
|
-
let targetID = id;
|
|
126
|
-
let targetKey = this.key;
|
|
127
|
-
// if we are removing a record from a connection we have to walk through
|
|
128
|
-
// some embedded references first
|
|
129
|
-
if (this.connection) {
|
|
130
|
-
const embeddedConnection = this.record.linkedRecord(this.key);
|
|
131
|
-
if (!embeddedConnection) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
// look at every embedded edge for the one with a node corresponding to the element
|
|
135
|
-
// we want to delete
|
|
136
|
-
for (const edge of embeddedConnection.flatLinkedList('edges') || []) {
|
|
137
|
-
if (!edge) {
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
// look at the edge's node
|
|
141
|
-
const node = edge.linkedRecord('node');
|
|
142
|
-
if (!node) {
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
// if we found the node
|
|
146
|
-
if (node.id === id) {
|
|
147
|
-
targetID = edge.id;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
parentID = embeddedConnection.id;
|
|
151
|
-
targetKey = 'edges';
|
|
152
|
-
}
|
|
153
|
-
// get the list of specs that are subscribing to the list
|
|
154
|
-
const subscribers = this.record.getSubscribers(this.key);
|
|
155
|
-
// disconnect record from any subscriptions associated with the list
|
|
156
|
-
this.cache.internal.unsubscribeSelection(this.cache.internal.record(targetID),
|
|
157
|
-
// if we're unsubscribing from a connection, only unsubscribe from the target
|
|
158
|
-
this.connection ? this.selection.edges.fields : this.selection, variables, ...subscribers.map(({ set }) => set));
|
|
159
|
-
// remove the target from the parent
|
|
160
|
-
this.cache.internal.record(parentID).removeFromLinkedList(targetKey, targetID);
|
|
161
|
-
// notify the subscribers about the change
|
|
162
|
-
this.cache.internal.notifySubscribers(subscribers, variables);
|
|
163
|
-
// if we are removing from a connection, delete the embedded edge holding the record
|
|
164
|
-
if (this.connection) {
|
|
165
|
-
this.cache.internal.deleteID(targetID);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
remove(data, variables = {}) {
|
|
169
|
-
const targetID = this.cache.id(this.listType, data);
|
|
170
|
-
if (!targetID) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
// figure out the id of the type we are adding
|
|
174
|
-
this.removeID(targetID, variables);
|
|
175
|
-
}
|
|
176
|
-
validateWhen() {
|
|
177
|
-
// if this when doesn't apply, we should look at others to see if we should update those behind the scenes
|
|
178
|
-
let ok = true;
|
|
179
|
-
// if there are conditions for this operation
|
|
180
|
-
if (this._when) {
|
|
181
|
-
// we only NEED there to be target filters for must's
|
|
182
|
-
const targets = this.filters;
|
|
183
|
-
// check must's first
|
|
184
|
-
if (this._when.must && targets) {
|
|
185
|
-
ok = Object.entries(this._when.must).reduce((prev, [key, value]) => Boolean(prev && targets[key] == value), ok);
|
|
186
|
-
}
|
|
187
|
-
// if there are no targets, nothing could be true that can we compare against
|
|
188
|
-
if (this._when.must_not) {
|
|
189
|
-
ok =
|
|
190
|
-
!targets ||
|
|
191
|
-
Object.entries(this._when.must_not).reduce((prev, [key, value]) => Boolean(prev && targets[key] != value), ok);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return ok;
|
|
195
|
-
}
|
|
196
|
-
// iterating over the list handler should be the same as iterating over
|
|
197
|
-
// the underlying linked list
|
|
198
|
-
*[Symbol.iterator]() {
|
|
199
|
-
for (let record of this.record.flatLinkedList(this.key)) {
|
|
200
|
-
yield record;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { GraphQLValue, Maybe, SubscriptionSpec } from '../types';
|
|
2
|
-
import { Cache, LinkedList } from './cache';
|
|
3
|
-
export declare class Record {
|
|
4
|
-
fields: {
|
|
5
|
-
[key: string]: GraphQLValue;
|
|
6
|
-
};
|
|
7
|
-
keyVersions: {
|
|
8
|
-
[key: string]: Set<string>;
|
|
9
|
-
};
|
|
10
|
-
readonly id: string;
|
|
11
|
-
private subscribers;
|
|
12
|
-
private recordLinks;
|
|
13
|
-
listLinks: {
|
|
14
|
-
[key: string]: LinkedList;
|
|
15
|
-
};
|
|
16
|
-
private cache;
|
|
17
|
-
private referenceCounts;
|
|
18
|
-
private lifetimes;
|
|
19
|
-
constructor(cache: Cache, id: string);
|
|
20
|
-
allSubscribers(): SubscriptionSpec[];
|
|
21
|
-
getField(fieldName: string): GraphQLValue;
|
|
22
|
-
writeField(fieldName: string, value: GraphQLValue): void;
|
|
23
|
-
writeRecordLink(fieldName: string, value: string | null): void;
|
|
24
|
-
writeListLink(fieldName: string, value: LinkedList): void;
|
|
25
|
-
linkedRecord(fieldName: string): Record;
|
|
26
|
-
linkedRecordID(fieldName: string): string;
|
|
27
|
-
linkedListIDs(fieldName: string): (string | null)[];
|
|
28
|
-
flatLinkedList(fieldName: string): Maybe<Record>[];
|
|
29
|
-
appendLinkedList(fieldName: string, id: string): void;
|
|
30
|
-
prependLinkedList(fieldName: string, id: string): void;
|
|
31
|
-
removeFromLinkedList(fieldName: string, id: string): void;
|
|
32
|
-
addSubscriber(rawKey: string, key: string, ...specs: SubscriptionSpec[]): void;
|
|
33
|
-
getSubscribers(fieldName: string): SubscriptionSpec[];
|
|
34
|
-
forgetSubscribers(...targets: SubscriptionSpec[]): void;
|
|
35
|
-
removeAllSubscribers(): void;
|
|
36
|
-
removeAllSubscriptionVersions(keyRaw: string, spec: SubscriptionSpec): void;
|
|
37
|
-
private forgetSubscribers_walk;
|
|
38
|
-
removeSubscribers(fields: string[], sets: SubscriptionSpec['set'][]): void;
|
|
39
|
-
onGcTick(): void;
|
|
40
|
-
}
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
// for the most part, this is a very low-level/dumb class that is meant to track state related
|
|
2
|
-
// to a specific entity in the cached graph.
|
|
3
|
-
export class Record {
|
|
4
|
-
constructor(cache, id) {
|
|
5
|
-
this.fields = {};
|
|
6
|
-
this.keyVersions = {};
|
|
7
|
-
this.subscribers = {};
|
|
8
|
-
this.recordLinks = {};
|
|
9
|
-
this.listLinks = {};
|
|
10
|
-
this.referenceCounts = {};
|
|
11
|
-
this.lifetimes = new Map();
|
|
12
|
-
this.cache = cache;
|
|
13
|
-
this.id = id;
|
|
14
|
-
}
|
|
15
|
-
allSubscribers() {
|
|
16
|
-
return Object.values(this.subscribers).flatMap((subscribers) => subscribers);
|
|
17
|
-
}
|
|
18
|
-
getField(fieldName) {
|
|
19
|
-
return this.fields[fieldName];
|
|
20
|
-
}
|
|
21
|
-
writeField(fieldName, value) {
|
|
22
|
-
this.fields[fieldName] = value;
|
|
23
|
-
}
|
|
24
|
-
writeRecordLink(fieldName, value) {
|
|
25
|
-
this.recordLinks[fieldName] = value;
|
|
26
|
-
}
|
|
27
|
-
writeListLink(fieldName, value) {
|
|
28
|
-
this.listLinks[fieldName] = value;
|
|
29
|
-
}
|
|
30
|
-
linkedRecord(fieldName) {
|
|
31
|
-
const linkedRecord = this.recordLinks[fieldName];
|
|
32
|
-
if (linkedRecord === null) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
return this.cache.internal.getRecord(linkedRecord);
|
|
36
|
-
}
|
|
37
|
-
linkedRecordID(fieldName) {
|
|
38
|
-
return this.recordLinks[fieldName];
|
|
39
|
-
}
|
|
40
|
-
linkedListIDs(fieldName) {
|
|
41
|
-
const ids = [];
|
|
42
|
-
// we need to flatten the list links
|
|
43
|
-
const unvisited = [this.listLinks[fieldName] || []];
|
|
44
|
-
while (unvisited.length > 0) {
|
|
45
|
-
const target = unvisited.shift();
|
|
46
|
-
for (const id of target) {
|
|
47
|
-
if (Array.isArray(id)) {
|
|
48
|
-
unvisited.push(id);
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
ids.push(id);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return ids;
|
|
55
|
-
}
|
|
56
|
-
flatLinkedList(fieldName) {
|
|
57
|
-
return this.linkedListIDs(fieldName).map(this.cache.internal.getRecord);
|
|
58
|
-
}
|
|
59
|
-
appendLinkedList(fieldName, id) {
|
|
60
|
-
// this could be the first time we've seen the list
|
|
61
|
-
if (!this.listLinks[fieldName]) {
|
|
62
|
-
this.listLinks[fieldName] = [];
|
|
63
|
-
}
|
|
64
|
-
this.listLinks[fieldName].push(id);
|
|
65
|
-
}
|
|
66
|
-
prependLinkedList(fieldName, id) {
|
|
67
|
-
// this could be the first time we've seen the list
|
|
68
|
-
if (!this.listLinks[fieldName]) {
|
|
69
|
-
this.listLinks[fieldName] = [];
|
|
70
|
-
}
|
|
71
|
-
this.listLinks[fieldName].unshift(id);
|
|
72
|
-
}
|
|
73
|
-
removeFromLinkedList(fieldName, id) {
|
|
74
|
-
this.listLinks[fieldName] = (this.listLinks[fieldName] || []).filter((link) => link !== id);
|
|
75
|
-
}
|
|
76
|
-
addSubscriber(rawKey, key, ...specs) {
|
|
77
|
-
// if this is the first time we've seen the raw key
|
|
78
|
-
if (!this.keyVersions[rawKey]) {
|
|
79
|
-
this.keyVersions[rawKey] = new Set();
|
|
80
|
-
}
|
|
81
|
-
// add this version of the key if we need to
|
|
82
|
-
this.keyVersions[rawKey].add(key);
|
|
83
|
-
// the existing list
|
|
84
|
-
const existingSubscribers = (this.subscribers[key] || []).map(({ set }) => set);
|
|
85
|
-
// the list of new subscribers
|
|
86
|
-
const newSubscribers = specs.filter(({ set }) => !existingSubscribers.includes(set));
|
|
87
|
-
this.subscribers[key] = this.getSubscribers(key).concat(...newSubscribers);
|
|
88
|
-
// if this is the first time we've seen this key
|
|
89
|
-
if (!this.referenceCounts[key]) {
|
|
90
|
-
this.referenceCounts[key] = new Map();
|
|
91
|
-
}
|
|
92
|
-
const counts = this.referenceCounts[key];
|
|
93
|
-
// clear the lifetime count for the field
|
|
94
|
-
this.lifetimes.delete(key);
|
|
95
|
-
// increment the reference count for every subscriber
|
|
96
|
-
for (const spec of specs) {
|
|
97
|
-
// we're going to increment the current value by one
|
|
98
|
-
counts.set(spec.set, (counts.get(spec.set) || 0) + 1);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
getSubscribers(fieldName) {
|
|
102
|
-
return this.subscribers[fieldName] || [];
|
|
103
|
-
}
|
|
104
|
-
forgetSubscribers(...targets) {
|
|
105
|
-
this.forgetSubscribers_walk(targets.map(({ set }) => set));
|
|
106
|
-
}
|
|
107
|
-
removeAllSubscribers() {
|
|
108
|
-
this.forgetSubscribers(...this.allSubscribers());
|
|
109
|
-
}
|
|
110
|
-
removeAllSubscriptionVersions(keyRaw, spec) {
|
|
111
|
-
// visit every version of the key we've seen and remove the spec from the list of subscribers
|
|
112
|
-
const versions = this.keyVersions[keyRaw];
|
|
113
|
-
// if there are no known versions, we're done
|
|
114
|
-
if (!versions) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
this.removeSubscribers([...this.keyVersions[keyRaw]], [spec.set]);
|
|
118
|
-
}
|
|
119
|
-
forgetSubscribers_walk(targets, visited = []) {
|
|
120
|
-
var _a;
|
|
121
|
-
// clean up any subscribers that reference the set
|
|
122
|
-
this.removeSubscribers(Object.keys(this.subscribers), targets);
|
|
123
|
-
visited.push(this.id);
|
|
124
|
-
// walk down to every record we know about
|
|
125
|
-
const linkedIDs = Object.keys(this.recordLinks);
|
|
126
|
-
for (const key of Object.keys(this.listLinks)) {
|
|
127
|
-
for (const child of this.linkedListIDs(key)) {
|
|
128
|
-
if (child !== null) {
|
|
129
|
-
linkedIDs.push(child);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
for (const linkedRecordID of linkedIDs) {
|
|
134
|
-
if (visited.includes(linkedRecordID)) {
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
(_a = this.cache.internal.getRecord(linkedRecordID)) === null || _a === void 0 ? void 0 : _a.forgetSubscribers_walk(targets, visited);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
removeSubscribers(fields, sets) {
|
|
141
|
-
var _a;
|
|
142
|
-
// clean up any subscribers that reference the set
|
|
143
|
-
for (const fieldName of fields) {
|
|
144
|
-
// build up a list of the sets we actually need to remove after
|
|
145
|
-
// checking reference counts
|
|
146
|
-
let targets = [];
|
|
147
|
-
for (const set of sets) {
|
|
148
|
-
// if we dont know this field/set combo, there's nothing to do (probably a bug somewhere)
|
|
149
|
-
if (!((_a = this.referenceCounts[fieldName]) === null || _a === void 0 ? void 0 : _a.has(set))) {
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
const counts = this.referenceCounts[fieldName];
|
|
153
|
-
const newVal = (counts.get(set) || 0) - 1;
|
|
154
|
-
// decrement the reference of every field
|
|
155
|
-
counts.set(set, newVal);
|
|
156
|
-
// if that was the last reference we knew of
|
|
157
|
-
if (newVal <= 0) {
|
|
158
|
-
targets.push(set);
|
|
159
|
-
// remove the reference to the set function
|
|
160
|
-
counts.delete(set);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
// we do need to remove the set from the list
|
|
164
|
-
this.subscribers[fieldName] = this.getSubscribers(fieldName).filter(({ set }) => !targets.includes(set));
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
// this function is invoked by the cache when the garbage collector is ticking
|
|
168
|
-
onGcTick() {
|
|
169
|
-
const fields = Object.keys(this.fields)
|
|
170
|
-
.concat(Object.keys(this.listLinks))
|
|
171
|
-
.concat(Object.keys(this.recordLinks));
|
|
172
|
-
// any fields with no reference counts need to be decremented
|
|
173
|
-
for (const field of fields) {
|
|
174
|
-
// {value} has a key for every subscriber - can check for no subscribers by looking
|
|
175
|
-
// at the number of fields in the value
|
|
176
|
-
if (!this.referenceCounts[field] || this.referenceCounts[field].size === 0) {
|
|
177
|
-
// lower the current count by 1
|
|
178
|
-
const previousCount = this.lifetimes.get(field) || 0;
|
|
179
|
-
this.lifetimes.set(field, previousCount + 1);
|
|
180
|
-
// if the lifetime exceeds the cache's buffer size we should remove the field, linked record, or list
|
|
181
|
-
if (this.lifetimes.get(field) > this.cache.cacheBufferSize) {
|
|
182
|
-
delete this.fields[field];
|
|
183
|
-
delete this.recordLinks[field];
|
|
184
|
-
delete this.recordLinks[field];
|
|
185
|
-
// if we dont have any data left, delete the record from the cache
|
|
186
|
-
if (Object.keys(this.fields).length === 0 &&
|
|
187
|
-
Object.keys(this.recordLinks).length === 0 &&
|
|
188
|
-
Object.keys(this.recordLinks).length === 0) {
|
|
189
|
-
this.cache.internal.deleteID(this.id);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|