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$1 = this;
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$1.start, startLoc = this$1$1.startLoc;
2607
- if (!this$1$1.eatContextual(k)) { return false }
2608
- if (this$1$1.type !== types$2$1.parenL && (!noLineBreak || !this$1$1.canInsertSemicolon())) { return true }
2609
- if (method.key) { this$1$1.unexpected(); }
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$1.startNodeAt(start, startLoc);
2611
+ method.key = this$1.startNodeAt(start, startLoc);
2612
2612
  method.key.name = k;
2613
- this$1$1.finishNode(method.key, "Identifier");
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$1 = this;
5624
+ var this$1 = this;
5625
5625
 
5626
5626
  return {
5627
5627
  next: function () {
5628
- var token = this$1$1.getToken();
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$2 = {};
6535
- var chars$2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
6536
- for (var i$3 = 0; i$3 < chars$2.length; i$3++) {
6537
- charToInteger$2[chars$2.charCodeAt(i$3)] = i$3;
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$2[c];
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$1 = {};
16415
- var chars$1$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
16416
- for (var i$2$2 = 0; i$2$2 < chars$1$1.length; i$2$2++) {
16417
- charToInteger$1$1[chars$1$1.charCodeAt(i$2$2)] = i$2$2;
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$1[c];
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$1[clamped];
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$1 = this;
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$1.start, startLoc = this$1$1.startLoc;
38637
- if (!this$1$1.eatContextual(k)) { return false }
38638
- if (this$1$1.type !== types$7.parenL && (!noLineBreak || !this$1$1.canInsertSemicolon())) { return true }
38639
- if (method.key) { this$1$1.unexpected(); }
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$1.startNodeAt(start, startLoc);
38636
+ method.key = this$1.startNodeAt(start, startLoc);
38642
38637
  method.key.name = k;
38643
- this$1$1.finishNode(method.key, "Identifier");
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$1 = this;
41649
+ var this$1 = this;
41655
41650
 
41656
41651
  return {
41657
41652
  next: function () {
41658
- var token = this$1$1.getToken();
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-alpha.3",
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": "ee15950c805df12d854b3e91fc861d51e2ce2f0c"
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
- }