houdini 1.5.4 → 2.0.0-next.0

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 (80) hide show
  1. package/build/cmd-cjs/index.js +29194 -22340
  2. package/build/cmd-esm/index.js +27597 -20744
  3. package/build/codegen/generators/artifacts/index.d.ts +8 -0
  4. package/build/codegen/index.d.ts +3 -2
  5. package/build/codegen/transforms/fragmentVariables.d.ts +1 -1
  6. package/build/codegen/transforms/list.d.ts +2 -2
  7. package/build/codegen/transforms/paginate.d.ts +2 -34
  8. package/build/codegen/utils/flattenSelections.d.ts +1 -1
  9. package/build/codegen-cjs/index.js +26128 -21041
  10. package/build/codegen-esm/index.js +24463 -19376
  11. package/build/lib/fs.d.ts +3 -2
  12. package/build/lib/index.d.ts +1 -0
  13. package/build/lib/watchAndRun.d.ts +61 -0
  14. package/build/lib-cjs/index.js +26668 -20749
  15. package/build/lib-esm/index.js +25001 -19085
  16. package/build/runtime-cjs/cache/cache.js +22 -1
  17. package/build/runtime-cjs/cache/gc.js +1 -0
  18. package/build/runtime-cjs/cache/index.js +0 -2
  19. package/build/runtime-cjs/cache/lists.js +9 -0
  20. package/build/runtime-cjs/cache/staleManager.js +26 -1
  21. package/build/runtime-cjs/cache/storage.js +4 -0
  22. package/build/runtime-cjs/cache/subscription.js +1 -0
  23. package/build/runtime-cjs/client/documentStore.js +28 -2
  24. package/build/runtime-cjs/client/index.js +17 -1
  25. package/build/runtime-cjs/client/plugins/cache.js +8 -2
  26. package/build/runtime-cjs/client/plugins/fetch.js +14 -6
  27. package/build/runtime-cjs/client/plugins/fetchParams.js +2 -0
  28. package/build/runtime-cjs/client/plugins/fragment.js +1 -0
  29. package/build/runtime-cjs/client/plugins/index.js +9 -1
  30. package/build/runtime-cjs/client/plugins/injectedPlugins.js +0 -2
  31. package/build/runtime-cjs/client/plugins/mutation.js +6 -0
  32. package/build/runtime-cjs/client/plugins/optimisticKeys.js +10 -3
  33. package/build/runtime-cjs/client/plugins/query.js +4 -0
  34. package/build/runtime-cjs/client/utils/index.js +4 -0
  35. package/build/runtime-cjs/imports/config.js +0 -2
  36. package/build/runtime-cjs/imports/pluginConfig.js +0 -2
  37. package/build/runtime-cjs/index.js +12 -6
  38. package/build/runtime-cjs/lib/config.js +4 -0
  39. package/build/runtime-cjs/lib/deepEquals.js +2 -4
  40. package/build/runtime-cjs/lib/index.js +13 -0
  41. package/build/runtime-cjs/lib/pagination.js +2 -1
  42. package/build/runtime-cjs/lib/types.js +11 -1
  43. package/build/runtime-cjs/public/cache.js +11 -0
  44. package/build/runtime-cjs/public/record.js +5 -0
  45. package/build/runtime-cjs/router/jwt.js +15 -28
  46. package/build/runtime-cjs/router/match.js +2 -4
  47. package/build/runtime-cjs/router/server.js +6 -1
  48. package/build/runtime-cjs/router/session.js +1 -1
  49. package/build/runtime-esm/cache/cache.js +22 -1
  50. package/build/runtime-esm/cache/gc.js +1 -0
  51. package/build/runtime-esm/cache/lists.js +9 -0
  52. package/build/runtime-esm/cache/staleManager.js +26 -1
  53. package/build/runtime-esm/cache/storage.js +4 -0
  54. package/build/runtime-esm/cache/subscription.js +1 -0
  55. package/build/runtime-esm/client/documentStore.js +28 -2
  56. package/build/runtime-esm/client/index.js +13 -1
  57. package/build/runtime-esm/client/plugins/cache.js +4 -2
  58. package/build/runtime-esm/client/plugins/fetch.js +14 -6
  59. package/build/runtime-esm/client/plugins/fetchParams.js +2 -0
  60. package/build/runtime-esm/client/plugins/fragment.js +1 -0
  61. package/build/runtime-esm/client/plugins/mutation.js +6 -0
  62. package/build/runtime-esm/client/plugins/optimisticKeys.js +6 -3
  63. package/build/runtime-esm/client/plugins/query.js +4 -0
  64. package/build/runtime-esm/lib/deepEquals.js +2 -4
  65. package/build/runtime-esm/lib/pagination.js +2 -1
  66. package/build/runtime-esm/lib/types.js +9 -0
  67. package/build/runtime-esm/public/cache.js +11 -0
  68. package/build/runtime-esm/public/record.js +5 -0
  69. package/build/runtime-esm/router/jwt.js +15 -28
  70. package/build/runtime-esm/router/match.js +2 -4
  71. package/build/runtime-esm/router/server.js +6 -1
  72. package/build/runtime-esm/router/session.js +1 -1
  73. package/build/test-cjs/index.js +26112 -21026
  74. package/build/test-esm/index.js +24447 -19361
  75. package/build/vite/hmr.d.ts +5 -0
  76. package/build/vite/imports.d.ts +2 -2
  77. package/build/vite/schema.d.ts +0 -3
  78. package/build/vite-cjs/index.js +34670 -31925
  79. package/build/vite-esm/index.js +31149 -28405
  80. package/package.json +13 -14
@@ -19,21 +19,25 @@ var __copyProps = (to, from, except, desc) => {
19
19
  };
20
20
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
21
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
26
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
27
  mod
24
28
  ));
25
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
- var runtime_exports = {};
27
- __export(runtime_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
28
32
  cache: () => cache,
29
33
  getCache: () => getCache,
30
34
  graphql: () => graphql
31
35
  });
32
- module.exports = __toCommonJS(runtime_exports);
36
+ module.exports = __toCommonJS(index_exports);
33
37
  var import_cache = __toESM(require("./cache"), 1);
34
38
  var import_public = require("./public");
35
- __reExport(runtime_exports, require("./client"), module.exports);
36
- __reExport(runtime_exports, require("./lib"), module.exports);
39
+ __reExport(index_exports, require("./client"), module.exports);
40
+ __reExport(index_exports, require("./lib"), module.exports);
37
41
  function graphql(str) {
38
42
  if (globalThis?.process?.env?.HOUDINI_PLUGIN) {
39
43
  return str;
@@ -51,5 +55,7 @@ function getCache() {
51
55
  0 && (module.exports = {
52
56
  cache,
53
57
  getCache,
54
- graphql
58
+ graphql,
59
+ ...require("./client"),
60
+ ...require("./lib")
55
61
  });
@@ -18,6 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  return to;
19
19
  };
20
20
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
25
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
26
  mod
23
27
  ));
@@ -22,8 +22,7 @@ __export(deepEquals_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(deepEquals_exports);
24
24
  function deepEquals(objA, objB, map = /* @__PURE__ */ new WeakMap()) {
25
- if (Object.is(objA, objB))
26
- return true;
25
+ if (Object.is(objA, objB)) return true;
27
26
  if (objA instanceof Date && objB instanceof Date) {
28
27
  return objA.getTime() === objB.getTime();
29
28
  }
@@ -33,8 +32,7 @@ function deepEquals(objA, objB, map = /* @__PURE__ */ new WeakMap()) {
33
32
  if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
34
33
  return false;
35
34
  }
36
- if (map.get(objA) === objB)
37
- return true;
35
+ if (map.get(objA) === objB) return true;
38
36
  map.set(objA, objB);
39
37
  const keysA = Reflect.ownKeys(objA);
40
38
  const keysB = Reflect.ownKeys(objB);
@@ -25,3 +25,16 @@ __reExport(lib_exports, require("./store"), module.exports);
25
25
  __reExport(lib_exports, require("./key"), module.exports);
26
26
  __reExport(lib_exports, require("./lru"), module.exports);
27
27
  __reExport(lib_exports, require("./selection"), module.exports);
28
+ // Annotate the CommonJS export names for ESM import in node:
29
+ 0 && (module.exports = {
30
+ ...require("./config"),
31
+ ...require("./constants"),
32
+ ...require("./deepEquals"),
33
+ ...require("./log"),
34
+ ...require("./scalars"),
35
+ ...require("./types"),
36
+ ...require("./store"),
37
+ ...require("./key"),
38
+ ...require("./lru"),
39
+ ...require("./selection")
40
+ });
@@ -143,7 +143,8 @@ function cursorHandlers({
143
143
  const queryVariables = {};
144
144
  const count = (0, import_pageInfo.countPage)(artifact.refetch.path.concat("edges"), getState()) || artifact.refetch.pageSize;
145
145
  if (count && count > artifact.refetch.pageSize) {
146
- if (currentPageInfo.hasPreviousPage && currentPageInfo.hasNextPage && !(variables?.["first"] && variables?.["after"] || variables?.["last"] && variables?.["before"])) {
146
+ if (currentPageInfo.hasPreviousPage && currentPageInfo.hasNextPage && // only log if they haven't provided special parameters
147
+ !(variables?.["first"] && variables?.["after"] || variables?.["last"] && variables?.["before"])) {
147
148
  console.warn(`\u26A0\uFE0F Encountered a fetch() in the middle of the connection.
148
149
  Make sure to pass a cursor value by hand that includes the current set (ie the entry before startCursor)
149
150
  `);
@@ -67,8 +67,17 @@ const RefetchUpdateMode = {
67
67
  replace: "replace"
68
68
  };
69
69
  const DataSource = {
70
+ /**
71
+ * from the browser cache
72
+ */
70
73
  Cache: "cache",
74
+ /**
75
+ * from a browser side `fetch`
76
+ */
71
77
  Network: "network",
78
+ /**
79
+ * from a server side `fetch`
80
+ */
72
81
  Ssr: "ssr"
73
82
  };
74
83
  const fragmentKey = " $fragments";
@@ -90,5 +99,6 @@ function isPending(value) {
90
99
  PendingValue,
91
100
  RefetchUpdateMode,
92
101
  fragmentKey,
93
- isPending
102
+ isPending,
103
+ ...require("../router/types")
94
104
  });
@@ -29,6 +29,9 @@ class Cache {
29
29
  constructor(cache) {
30
30
  this._internal_unstable = cache;
31
31
  }
32
+ // if the user is using the imperative API, we want the ability to break the API
33
+ // with any minor version. In order to do this, we require them to accept this contract
34
+ // through their config file
32
35
  validateInstabilityWarning() {
33
36
  if (!this.config.acceptImperativeInstability && !this.config.features?.imperativeCache) {
34
37
  console.warn(`\u26A0\uFE0F The imperative cache API is considered unstable and will change in any minor version release
@@ -36,6 +39,7 @@ Please acknowledge this by enabling the imperative cache feature flage in your c
36
39
  For more information: https://houdinigraphql.com/api/cache`);
37
40
  }
38
41
  }
42
+ // return the record proxy for the given type/id combo
39
43
  get(type, data) {
40
44
  this.validateInstabilityWarning();
41
45
  let recordID = this._internal_unstable._internal_unstable.id(type, data);
@@ -79,6 +83,7 @@ For more information: https://houdinigraphql.com/api/cache`);
79
83
  this.validateInstabilityWarning();
80
84
  this._internal_unstable.write({
81
85
  selection: query.artifact.selection,
86
+ // @ts-expect-error
82
87
  data,
83
88
  variables: (0, import_lib.marshalInputs)({
84
89
  config: this.config,
@@ -88,9 +93,15 @@ For more information: https://houdinigraphql.com/api/cache`);
88
93
  });
89
94
  return;
90
95
  }
96
+ /**
97
+ * Mark some elements of the cache stale.
98
+ */
91
99
  markStale(type, options) {
92
100
  return this._internal_unstable.markTypeStale(type ? { ...options, type } : void 0);
93
101
  }
102
+ /**
103
+ * Reset the entire cache by clearing all records and lists
104
+ */
94
105
  reset() {
95
106
  return this._internal_unstable.reset();
96
107
  }
@@ -77,6 +77,11 @@ class Record {
77
77
  delete() {
78
78
  this.#cache._internal_unstable.delete(this.#id);
79
79
  }
80
+ /**
81
+ * Mark some elements of the record stale in the cache.
82
+ * @param field
83
+ * @param when
84
+ */
80
85
  markStale(field, {
81
86
  when
82
87
  } = {}) {
@@ -25,6 +25,7 @@ __export(jwt_exports, {
25
25
  module.exports = __toCommonJS(jwt_exports);
26
26
  function base64UrlParse(s) {
27
27
  return new Uint8Array(
28
+ // @ts-ignore
28
29
  Array.prototype.map.call(
29
30
  atob(s.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, "")),
30
31
  (c) => c.charCodeAt(0)
@@ -77,20 +78,16 @@ function _decodePayload(raw) {
77
78
  }
78
79
  }
79
80
  async function encode(payload, secret, options = { algorithm: "HS256", header: { typ: "JWT" } }) {
80
- if (typeof options === "string")
81
- options = { algorithm: options, header: { typ: "JWT" } };
81
+ if (typeof options === "string") options = { algorithm: options, header: { typ: "JWT" } };
82
82
  options = { algorithm: "HS256", header: { typ: "JWT" }, ...options };
83
83
  if (payload === null || typeof payload !== "object")
84
84
  throw new Error("payload must be an object");
85
85
  if (typeof secret !== "string" && typeof secret !== "object")
86
86
  throw new Error("secret must be a string or a JWK object");
87
- if (typeof options.algorithm !== "string")
88
- throw new Error("options.algorithm must be a string");
87
+ if (typeof options.algorithm !== "string") throw new Error("options.algorithm must be a string");
89
88
  const algorithm = algorithms[options.algorithm];
90
- if (!algorithm)
91
- throw new Error("algorithm not found");
92
- if (!payload.iat)
93
- payload.iat = Math.floor(Date.now() / 1e3);
89
+ if (!algorithm) throw new Error("algorithm not found");
90
+ if (!payload.iat) payload.iat = Math.floor(Date.now() / 1e3);
94
91
  const payloadAsJSON = JSON.stringify(payload);
95
92
  const partialToken = `${base64UrlStringify(
96
93
  _utf8ToUint8Array(JSON.stringify({ ...options.header, alg: options.algorithm }))
@@ -105,42 +102,33 @@ async function encode(payload, secret, options = { algorithm: "HS256", header: {
105
102
  keyData = _str2ab(
106
103
  secret.replace(/-----BEGIN.*?-----/g, "").replace(/-----END.*?-----/g, "").replace(/\s/g, "")
107
104
  );
108
- } else
109
- keyData = _utf8ToUint8Array(secret);
105
+ } else keyData = _utf8ToUint8Array(secret);
110
106
  const key = await crypto.subtle.importKey(keyFormat, keyData, algorithm, false, ["sign"]);
111
107
  const signature = await crypto.subtle.sign(algorithm, key, _utf8ToUint8Array(partialToken));
112
108
  return `${partialToken}.${base64UrlStringify(new Uint8Array(signature))}`;
113
109
  }
114
110
  async function verify(token, secret, options = { algorithm: "HS256", throwError: false }) {
115
- if (typeof options === "string")
116
- options = { algorithm: options, throwError: false };
111
+ if (typeof options === "string") options = { algorithm: options, throwError: false };
117
112
  options = { algorithm: "HS256", throwError: false, ...options };
118
- if (typeof token !== "string")
119
- throw new Error("token must be a string");
113
+ if (typeof token !== "string") throw new Error("token must be a string");
120
114
  if (typeof secret !== "string" && typeof secret !== "object")
121
115
  throw new Error("secret must be a string or a JWK object");
122
- if (typeof options.algorithm !== "string")
123
- throw new Error("options.algorithm must be a string");
116
+ if (typeof options.algorithm !== "string") throw new Error("options.algorithm must be a string");
124
117
  const tokenParts = token.split(".");
125
- if (tokenParts.length !== 3)
126
- throw new Error("token must consist of 3 parts");
118
+ if (tokenParts.length !== 3) throw new Error("token must consist of 3 parts");
127
119
  const algorithm = algorithms[options.algorithm];
128
- if (!algorithm)
129
- throw new Error("algorithm not found");
120
+ if (!algorithm) throw new Error("algorithm not found");
130
121
  const { payload } = decode(token);
131
122
  if (!payload) {
132
- if (options.throwError)
133
- throw "PARSE_ERROR";
123
+ if (options.throwError) throw "PARSE_ERROR";
134
124
  return false;
135
125
  }
136
126
  if (payload.nbf && payload.nbf > Math.floor(Date.now() / 1e3)) {
137
- if (options.throwError)
138
- throw "NOT_YET_VALID";
127
+ if (options.throwError) throw "NOT_YET_VALID";
139
128
  return false;
140
129
  }
141
130
  if (payload.exp && payload.exp <= Math.floor(Date.now() / 1e3)) {
142
- if (options.throwError)
143
- throw "EXPIRED";
131
+ if (options.throwError) throw "EXPIRED";
144
132
  return false;
145
133
  }
146
134
  let keyFormat = "raw";
@@ -153,8 +141,7 @@ async function verify(token, secret, options = { algorithm: "HS256", throwError:
153
141
  keyData = _str2ab(
154
142
  secret.replace(/-----BEGIN.*?-----/g, "").replace(/-----END.*?-----/g, "").replace(/\s/g, "")
155
143
  );
156
- } else
157
- keyData = _utf8ToUint8Array(secret);
144
+ } else keyData = _utf8ToUint8Array(secret);
158
145
  const key = await crypto.subtle.importKey(keyFormat, keyData, algorithm, false, ["verify"]);
159
146
  return await crypto.subtle.verify(
160
147
  algorithm,
@@ -138,14 +138,12 @@ function exec(match, params) {
138
138
  }
139
139
  buffered = "";
140
140
  if (value === void 0) {
141
- if (param.rest)
142
- result[param.name] = "";
141
+ if (param.rest) result[param.name] = "";
143
142
  } else {
144
143
  result[param.name] = decodeURIComponent(value);
145
144
  }
146
145
  }
147
- if (buffered)
148
- return;
146
+ if (buffered) return;
149
147
  return result;
150
148
  }
151
149
  function escape(str) {
@@ -51,7 +51,12 @@ function _serverHandler({
51
51
  if (schema) {
52
52
  client.registerProxy(graphqlEndpoint, async ({ query, variables, session }) => {
53
53
  const parsed = (0, import_graphql.parse)(query);
54
- return await (0, import_graphql.execute)(schema, parsed, null, session, variables);
54
+ return await (0, import_graphql.execute)({
55
+ schema,
56
+ document: parsed,
57
+ contextValue: session,
58
+ variableValues: variables
59
+ });
55
60
  });
56
61
  }
57
62
  return async (request) => {
@@ -59,7 +59,7 @@ async function redirect_auth(args) {
59
59
  }
60
60
  const session_cookie_name = "__houdini__";
61
61
  async function set_session(req, response, value) {
62
- const today = new Date();
62
+ const today = /* @__PURE__ */ new Date();
63
63
  const expires = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1e3);
64
64
  const serialized = await (0, import_jwt.encode)(value, req.session_keys[0]);
65
65
  response.headers.set(
@@ -11,6 +11,9 @@ import { InMemoryStorage } from "./storage";
11
11
  import { evaluateKey, rootID } from "./stuff";
12
12
  import { InMemorySubscriptions } from "./subscription";
13
13
  class Cache {
14
+ // the internal implementation for a lot of the cache's methods are moved into
15
+ // a second class to avoid users from relying on unstable APIs. typescript's private
16
+ // label accomplishes this but would not prevent someone using vanilla js
14
17
  _internal_unstable;
15
18
  constructor({
16
19
  disabled,
@@ -33,6 +36,8 @@ class Cache {
33
36
  this.setConfig(defaultConfigValues(config));
34
37
  }
35
38
  }
39
+ // walk down the selection and save the values that we encounter.
40
+ // any changes will notify subscribers. writing to an optimistic layer will resolve it
36
41
  write({
37
42
  layer: layerID,
38
43
  notifySubscribers = [],
@@ -43,6 +48,7 @@ class Cache {
43
48
  this.#notifySubscribers(subscribers.concat(notifySubscribers));
44
49
  return subscribers;
45
50
  }
51
+ // reconstruct an object with the fields/relations specified by a selection
46
52
  read(...args) {
47
53
  const { data, partial, stale, hasData } = this._internal_unstable.getSelection(...args);
48
54
  if (!hasData) {
@@ -54,6 +60,7 @@ class Cache {
54
60
  stale
55
61
  };
56
62
  }
63
+ // register the provided callbacks with the fields specified by the selection
57
64
  subscribe(spec, variables = {}) {
58
65
  if (this._internal_unstable.disabled) {
59
66
  return;
@@ -65,6 +72,7 @@ class Cache {
65
72
  variables
66
73
  });
67
74
  }
75
+ // stop listening to a particular subscription
68
76
  unsubscribe(spec, variables = {}) {
69
77
  return this._internal_unstable.subscriptions.remove(
70
78
  spec.parentID || rootID,
@@ -73,6 +81,7 @@ class Cache {
73
81
  variables
74
82
  );
75
83
  }
84
+ // return the list handler to mutate a named list in the cache
76
85
  list(name, parentID, allLists, skipMatches) {
77
86
  const handler = this._internal_unstable.lists.get(name, parentID, allLists, skipMatches);
78
87
  if (!handler) {
@@ -82,10 +91,12 @@ class Cache {
82
91
  }
83
92
  return handler;
84
93
  }
94
+ // when an optimistic key resolves, we might momentarily know the same record by different IDs
85
95
  registerKeyMap(source, mapped) {
86
96
  this._internal_unstable.storage.registerIDMapping(source, mapped);
87
97
  this._internal_unstable.subscriptions.copySubscribers(source, mapped);
88
98
  }
99
+ // remove the record from the cache's store and unsubscribe from it
89
100
  delete(id, layer) {
90
101
  const recordIDs = [this._internal_unstable.storage.idMaps[id], id].filter(
91
102
  Boolean
@@ -96,6 +107,7 @@ class Cache {
96
107
  this._internal_unstable.storage.delete(recordID, layer);
97
108
  }
98
109
  }
110
+ // set the cache's config
99
111
  setConfig(config) {
100
112
  this._internal_unstable.setConfig(config);
101
113
  }
@@ -177,6 +189,7 @@ class Cache {
177
189
  }
178
190
  this.#notifySubscribers(toNotify);
179
191
  }
192
+ // reset the whole cache
180
193
  reset() {
181
194
  const subSpecs = this._internal_unstable.subscriptions.reset();
182
195
  this._internal_unstable.staleManager.reset();
@@ -206,6 +219,7 @@ class Cache {
206
219
  }
207
220
  }
208
221
  class CacheInternal {
222
+ // for server-side requests we need to be able to flag the cache as disabled so we dont write to it
209
223
  disabled = false;
210
224
  _config;
211
225
  storage;
@@ -370,7 +384,8 @@ class CacheInternal {
370
384
  forceNotify
371
385
  });
372
386
  }
373
- } else if (Array.isArray(value) && (typeof previousValue === "undefined" || previousValue === null || Array.isArray(previousValue))) {
387
+ } else if (Array.isArray(value) && // make typescript happy
388
+ (typeof previousValue === "undefined" || previousValue === null || Array.isArray(previousValue))) {
374
389
  let oldIDs = [...previousValue || []];
375
390
  const emptyEdges = !updates ? [] : oldIDs.map((id) => {
376
391
  if (!id) {
@@ -566,6 +581,7 @@ class CacheInternal {
566
581
  }
567
582
  return toNotify;
568
583
  }
584
+ // reconstruct an object defined by its selection
569
585
  getSelection({
570
586
  selection,
571
587
  parent = rootID,
@@ -754,6 +770,8 @@ class CacheInternal {
754
770
  }
755
771
  return {
756
772
  data: cascadeNull ? null : target,
773
+ // our value is considered true if there is some data but not everything
774
+ // has a full value
757
775
  partial: !generateLoading && hasData && partial,
758
776
  stale: hasData && stale,
759
777
  hasData
@@ -769,12 +787,15 @@ class CacheInternal {
769
787
  }
770
788
  return type + ":" + id;
771
789
  }
790
+ // the list of fields that we need in order to compute an objects id
772
791
  idFields(type) {
773
792
  return keyFieldsForType(this.config, type);
774
793
  }
775
794
  computeID(type, data) {
776
795
  return computeID(this.config, type, data);
777
796
  }
797
+ // figure out if this is an embedded object or a linked one by looking for all of the fields marked as
798
+ // required to compute the entity's id
778
799
  isEmbedded(linkedType, value) {
779
800
  const idFields = this.idFields(linkedType);
780
801
  return idFields.length === 0 || idFields.filter((field) => typeof value[field] === "undefined").length > 0;
@@ -1,6 +1,7 @@
1
1
  class GarbageCollector {
2
2
  cache;
3
3
  lifetimes = /* @__PURE__ */ new Map();
4
+ // the number of ticks of the garbage collector that a piece of data will
4
5
  get cacheBufferSize() {
5
6
  return this.cache._internal_unstable.config.cacheBufferSize ?? 10;
6
7
  }
@@ -7,6 +7,7 @@ class ListManager {
7
7
  this.rootID = rootID2;
8
8
  this.cache = cache;
9
9
  }
10
+ // associate list names with the handler that wraps the list
10
11
  lists = /* @__PURE__ */ new Map();
11
12
  listsByField = /* @__PURE__ */ new Map();
12
13
  get(listName, id, allLists, skipMatches) {
@@ -145,6 +146,8 @@ class List {
145
146
  get fieldRef() {
146
147
  return `${this.recordID}.${this.key}`;
147
148
  }
149
+ // looks for the collection of all of the lists in the cache that satisfies a when
150
+ // condition
148
151
  when(when) {
149
152
  return this.manager.lists.get(this.name).get(this.recordID).when(when);
150
153
  }
@@ -301,6 +304,8 @@ class List {
301
304
  const subscribers = this.cache._internal_unstable.subscriptions.get(this.recordID, this.key);
302
305
  this.cache._internal_unstable.subscriptions.remove(
303
306
  targetID,
307
+ // if we are unsubscribing from a connection, the fields we care about
308
+ // are tucked away under edges
304
309
  this.connection ? this.selection.fields.edges.selection : this.selection,
305
310
  subscribers.map((sub) => sub[0]),
306
311
  variables
@@ -359,6 +364,8 @@ class List {
359
364
  this.addToList(selection, data, variables, where, layer);
360
365
  }
361
366
  }
367
+ // iterating over the list handler should be the same as iterating over
368
+ // the underlying linked list
362
369
  *[Symbol.iterator]() {
363
370
  let entries = [];
364
371
  let value = this.cache._internal_unstable.storage.get(this.recordID, this.key).value;
@@ -417,6 +424,8 @@ class ListCollection {
417
424
  deleteListWithKey(key) {
418
425
  return this.lists = this.lists.filter((list) => list.key !== key);
419
426
  }
427
+ // iterating over the collection should be the same as iterating over
428
+ // the underlying list
420
429
  *[Symbol.iterator]() {
421
430
  for (let list of this.lists) {
422
431
  for (const entry of list) {
@@ -1,6 +1,15 @@
1
1
  import { computeKey } from "../lib";
2
2
  class StaleManager {
3
3
  cache;
4
+ // id { "User:1" "_ROOT_"
5
+ // field { "id" "viewer"
6
+ // number | undefined | null
7
+ // }
8
+ // }
9
+ // number => data ok (not stale!)
10
+ // undefined => no data (not stale!)
11
+ // null => data stale (stale)
12
+ // nulls mean that the value is stale, and the number is the time that the value was set
4
13
  fieldsTime = /* @__PURE__ */ new Map();
5
14
  constructor(cache) {
6
15
  this.cache = cache;
@@ -10,13 +19,28 @@ class StaleManager {
10
19
  this.fieldsTime.set(id, /* @__PURE__ */ new Map());
11
20
  }
12
21
  };
22
+ /**
23
+ * get the FieldTime info
24
+ * @param id User:1
25
+ * @param field firstName
26
+ */
13
27
  getFieldTime(id, field) {
14
28
  return this.fieldsTime.get(id)?.get(field);
15
29
  }
30
+ /**
31
+ * set the date to a field
32
+ * @param id User:1
33
+ * @param field firstName
34
+ */
16
35
  setFieldTimeToNow(id, field) {
17
36
  this.#initMapId(id);
18
- this.fieldsTime.get(id)?.set(field, new Date().valueOf());
37
+ this.fieldsTime.get(id)?.set(field, (/* @__PURE__ */ new Date()).valueOf());
19
38
  }
39
+ /**
40
+ * set null to a field (stale)
41
+ * @param id User:1
42
+ * @param field firstName
43
+ */
20
44
  markFieldStale(id, field) {
21
45
  this.#initMapId(id);
22
46
  this.fieldsTime.get(id)?.set(field, null);
@@ -57,6 +81,7 @@ class StaleManager {
57
81
  }
58
82
  }
59
83
  }
84
+ // clean up the stale manager
60
85
  delete(id, field) {
61
86
  if (this.fieldsTime.has(id)) {
62
87
  this.fieldsTime.get(id)?.delete(field);
@@ -17,6 +17,7 @@ class InMemoryStorage {
17
17
  this.idMaps[from] = to;
18
18
  this.idMaps[to] = from;
19
19
  }
20
+ // create a layer and return its id
20
21
  createLayer(optimistic = false) {
21
22
  const layer = new Layer(this.idCount++);
22
23
  layer.optimistic = optimistic;
@@ -184,6 +185,8 @@ class InMemoryStorage {
184
185
  }
185
186
  return this.data[this.data.length - 1];
186
187
  }
188
+ // return a string representation of all of the data and necessary state to
189
+ // recreate the information stored
187
190
  serialize() {
188
191
  return JSON.stringify({
189
192
  rank: this.rank,
@@ -317,6 +320,7 @@ class Layer {
317
320
  [id]: {
318
321
  ...this.operations[id],
319
322
  deleted: true,
323
+ // reapply any delete undos
320
324
  undoDeletesInList: []
321
325
  }
322
326
  };
@@ -135,6 +135,7 @@ class InMemorySubscriptions {
135
135
  }, {})
136
136
  });
137
137
  }
138
+ // this is different from add because of the treatment of lists
138
139
  addMany({
139
140
  parent,
140
141
  variables,