houdini 1.5.5 → 2.0.0-next.1

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 (85) hide show
  1. package/build/cmd-cjs/index.js +29267 -22336
  2. package/build/cmd-esm/index.js +27820 -20890
  3. package/build/codegen/generators/artifacts/index.d.ts +8 -0
  4. package/build/codegen/generators/runtime/pluginRuntime.d.ts +3 -0
  5. package/build/codegen/index.d.ts +3 -2
  6. package/build/codegen/transforms/fragmentVariables.d.ts +1 -1
  7. package/build/codegen/transforms/list.d.ts +2 -2
  8. package/build/codegen/transforms/paginate.d.ts +2 -34
  9. package/build/codegen/utils/flattenSelections.d.ts +1 -1
  10. package/build/codegen-cjs/index.js +24414 -19277
  11. package/build/codegen-esm/index.js +22975 -17838
  12. package/build/lib/config.d.ts +3 -0
  13. package/build/lib/fs.d.ts +3 -2
  14. package/build/lib/index.d.ts +1 -0
  15. package/build/lib/introspection.d.ts +1 -1
  16. package/build/lib/watchAndRun.d.ts +61 -0
  17. package/build/lib-cjs/index.js +26708 -20759
  18. package/build/lib-esm/index.js +25041 -19095
  19. package/build/runtime/lib/config.d.ts +7 -0
  20. package/build/runtime-cjs/cache/cache.js +22 -1
  21. package/build/runtime-cjs/cache/gc.js +1 -0
  22. package/build/runtime-cjs/cache/index.js +0 -2
  23. package/build/runtime-cjs/cache/lists.js +9 -0
  24. package/build/runtime-cjs/cache/staleManager.js +26 -1
  25. package/build/runtime-cjs/cache/storage.js +4 -0
  26. package/build/runtime-cjs/cache/subscription.js +1 -0
  27. package/build/runtime-cjs/client/documentStore.js +28 -2
  28. package/build/runtime-cjs/client/index.js +17 -1
  29. package/build/runtime-cjs/client/plugins/cache.js +8 -2
  30. package/build/runtime-cjs/client/plugins/fetch.js +14 -6
  31. package/build/runtime-cjs/client/plugins/fetchParams.js +2 -0
  32. package/build/runtime-cjs/client/plugins/fragment.js +1 -0
  33. package/build/runtime-cjs/client/plugins/index.js +9 -1
  34. package/build/runtime-cjs/client/plugins/injectedPlugins.js +0 -2
  35. package/build/runtime-cjs/client/plugins/mutation.js +6 -0
  36. package/build/runtime-cjs/client/plugins/optimisticKeys.js +10 -3
  37. package/build/runtime-cjs/client/plugins/query.js +4 -0
  38. package/build/runtime-cjs/client/utils/index.js +4 -0
  39. package/build/runtime-cjs/imports/config.js +0 -2
  40. package/build/runtime-cjs/imports/pluginConfig.js +0 -2
  41. package/build/runtime-cjs/index.js +12 -6
  42. package/build/runtime-cjs/lib/config.d.ts +7 -0
  43. package/build/runtime-cjs/lib/config.js +4 -0
  44. package/build/runtime-cjs/lib/deepEquals.js +2 -4
  45. package/build/runtime-cjs/lib/index.js +13 -0
  46. package/build/runtime-cjs/lib/pagination.js +2 -1
  47. package/build/runtime-cjs/lib/types.js +11 -1
  48. package/build/runtime-cjs/public/cache.js +11 -0
  49. package/build/runtime-cjs/public/record.js +5 -0
  50. package/build/runtime-cjs/router/jwt.js +15 -28
  51. package/build/runtime-cjs/router/match.js +2 -4
  52. package/build/runtime-cjs/router/server.js +6 -1
  53. package/build/runtime-cjs/router/session.js +1 -1
  54. package/build/runtime-esm/cache/cache.js +22 -1
  55. package/build/runtime-esm/cache/gc.js +1 -0
  56. package/build/runtime-esm/cache/lists.js +9 -0
  57. package/build/runtime-esm/cache/staleManager.js +26 -1
  58. package/build/runtime-esm/cache/storage.js +4 -0
  59. package/build/runtime-esm/cache/subscription.js +1 -0
  60. package/build/runtime-esm/client/documentStore.js +28 -2
  61. package/build/runtime-esm/client/index.js +13 -1
  62. package/build/runtime-esm/client/plugins/cache.js +4 -2
  63. package/build/runtime-esm/client/plugins/fetch.js +14 -6
  64. package/build/runtime-esm/client/plugins/fetchParams.js +2 -0
  65. package/build/runtime-esm/client/plugins/fragment.js +1 -0
  66. package/build/runtime-esm/client/plugins/mutation.js +6 -0
  67. package/build/runtime-esm/client/plugins/optimisticKeys.js +6 -3
  68. package/build/runtime-esm/client/plugins/query.js +4 -0
  69. package/build/runtime-esm/lib/config.d.ts +7 -0
  70. package/build/runtime-esm/lib/deepEquals.js +2 -4
  71. package/build/runtime-esm/lib/pagination.js +2 -1
  72. package/build/runtime-esm/lib/types.js +9 -0
  73. package/build/runtime-esm/public/cache.js +11 -0
  74. package/build/runtime-esm/public/record.js +5 -0
  75. package/build/runtime-esm/router/jwt.js +15 -28
  76. package/build/runtime-esm/router/match.js +2 -4
  77. package/build/runtime-esm/router/server.js +6 -1
  78. package/build/runtime-esm/router/session.js +1 -1
  79. package/build/test-cjs/index.js +26140 -21029
  80. package/build/test-esm/index.js +24475 -19364
  81. package/build/vite/hmr.d.ts +5 -0
  82. package/build/vite/schema.d.ts +0 -3
  83. package/build/vite-cjs/index.js +34920 -32093
  84. package/build/vite-esm/index.js +31443 -28617
  85. package/package.json +13 -14
@@ -196,6 +196,13 @@ export type WatchSchemaConfig = {
196
196
  * logic you need
197
197
  */
198
198
  headers?: Record<string, string | ((env: Record<string, string | undefined>) => string)> | ((env: Record<string, string | undefined>) => Record<string, string>);
199
+ /**
200
+ * Write the schema to disk on pull.
201
+ * Useful for IDE integration.
202
+ * Set to false when you have read only access to the schema or directory it's in.
203
+ * Defaults to true
204
+ */
205
+ writePolledSchema?: boolean;
199
206
  };
200
207
  export type ScalarSpec = {
201
208
  type: string;
@@ -38,6 +38,9 @@ var import_storage = require("./storage");
38
38
  var import_stuff = require("./stuff");
39
39
  var import_subscription = require("./subscription");
40
40
  class Cache {
41
+ // the internal implementation for a lot of the cache's methods are moved into
42
+ // a second class to avoid users from relying on unstable APIs. typescript's private
43
+ // label accomplishes this but would not prevent someone using vanilla js
41
44
  _internal_unstable;
42
45
  constructor({
43
46
  disabled,
@@ -60,6 +63,8 @@ class Cache {
60
63
  this.setConfig((0, import_config.defaultConfigValues)(config));
61
64
  }
62
65
  }
66
+ // walk down the selection and save the values that we encounter.
67
+ // any changes will notify subscribers. writing to an optimistic layer will resolve it
63
68
  write({
64
69
  layer: layerID,
65
70
  notifySubscribers = [],
@@ -70,6 +75,7 @@ class Cache {
70
75
  this.#notifySubscribers(subscribers.concat(notifySubscribers));
71
76
  return subscribers;
72
77
  }
78
+ // reconstruct an object with the fields/relations specified by a selection
73
79
  read(...args) {
74
80
  const { data, partial, stale, hasData } = this._internal_unstable.getSelection(...args);
75
81
  if (!hasData) {
@@ -81,6 +87,7 @@ class Cache {
81
87
  stale
82
88
  };
83
89
  }
90
+ // register the provided callbacks with the fields specified by the selection
84
91
  subscribe(spec, variables = {}) {
85
92
  if (this._internal_unstable.disabled) {
86
93
  return;
@@ -92,6 +99,7 @@ class Cache {
92
99
  variables
93
100
  });
94
101
  }
102
+ // stop listening to a particular subscription
95
103
  unsubscribe(spec, variables = {}) {
96
104
  return this._internal_unstable.subscriptions.remove(
97
105
  spec.parentID || import_stuff.rootID,
@@ -100,6 +108,7 @@ class Cache {
100
108
  variables
101
109
  );
102
110
  }
111
+ // return the list handler to mutate a named list in the cache
103
112
  list(name, parentID, allLists, skipMatches) {
104
113
  const handler = this._internal_unstable.lists.get(name, parentID, allLists, skipMatches);
105
114
  if (!handler) {
@@ -109,10 +118,12 @@ class Cache {
109
118
  }
110
119
  return handler;
111
120
  }
121
+ // when an optimistic key resolves, we might momentarily know the same record by different IDs
112
122
  registerKeyMap(source, mapped) {
113
123
  this._internal_unstable.storage.registerIDMapping(source, mapped);
114
124
  this._internal_unstable.subscriptions.copySubscribers(source, mapped);
115
125
  }
126
+ // remove the record from the cache's store and unsubscribe from it
116
127
  delete(id, layer) {
117
128
  const recordIDs = [this._internal_unstable.storage.idMaps[id], id].filter(
118
129
  Boolean
@@ -123,6 +134,7 @@ class Cache {
123
134
  this._internal_unstable.storage.delete(recordID, layer);
124
135
  }
125
136
  }
137
+ // set the cache's config
126
138
  setConfig(config) {
127
139
  this._internal_unstable.setConfig(config);
128
140
  }
@@ -204,6 +216,7 @@ class Cache {
204
216
  }
205
217
  this.#notifySubscribers(toNotify);
206
218
  }
219
+ // reset the whole cache
207
220
  reset() {
208
221
  const subSpecs = this._internal_unstable.subscriptions.reset();
209
222
  this._internal_unstable.staleManager.reset();
@@ -233,6 +246,7 @@ class Cache {
233
246
  }
234
247
  }
235
248
  class CacheInternal {
249
+ // for server-side requests we need to be able to flag the cache as disabled so we dont write to it
236
250
  disabled = false;
237
251
  _config;
238
252
  storage;
@@ -397,7 +411,8 @@ class CacheInternal {
397
411
  forceNotify
398
412
  });
399
413
  }
400
- } else if (Array.isArray(value) && (typeof previousValue === "undefined" || previousValue === null || Array.isArray(previousValue))) {
414
+ } else if (Array.isArray(value) && // make typescript happy
415
+ (typeof previousValue === "undefined" || previousValue === null || Array.isArray(previousValue))) {
401
416
  let oldIDs = [...previousValue || []];
402
417
  const emptyEdges = !updates ? [] : oldIDs.map((id) => {
403
418
  if (!id) {
@@ -593,6 +608,7 @@ class CacheInternal {
593
608
  }
594
609
  return toNotify;
595
610
  }
611
+ // reconstruct an object defined by its selection
596
612
  getSelection({
597
613
  selection,
598
614
  parent = import_stuff.rootID,
@@ -781,6 +797,8 @@ class CacheInternal {
781
797
  }
782
798
  return {
783
799
  data: cascadeNull ? null : target,
800
+ // our value is considered true if there is some data but not everything
801
+ // has a full value
784
802
  partial: !generateLoading && hasData && partial,
785
803
  stale: hasData && stale,
786
804
  hasData
@@ -796,12 +814,15 @@ class CacheInternal {
796
814
  }
797
815
  return type + ":" + id;
798
816
  }
817
+ // the list of fields that we need in order to compute an objects id
799
818
  idFields(type) {
800
819
  return (0, import_config.keyFieldsForType)(this.config, type);
801
820
  }
802
821
  computeID(type, data) {
803
822
  return (0, import_config.computeID)(this.config, type, data);
804
823
  }
824
+ // figure out if this is an embedded object or a linked one by looking for all of the fields marked as
825
+ // required to compute the entity's id
805
826
  isEmbedded(linkedType, value) {
806
827
  const idFields = this.idFields(linkedType);
807
828
  return idFields.length === 0 || idFields.filter((field) => typeof value[field] === "undefined").length > 0;
@@ -24,6 +24,7 @@ module.exports = __toCommonJS(gc_exports);
24
24
  class GarbageCollector {
25
25
  cache;
26
26
  lifetimes = /* @__PURE__ */ new Map();
27
+ // the number of ticks of the garbage collector that a piece of data will
27
28
  get cacheBufferSize() {
28
29
  return this.cache._internal_unstable.config.cacheBufferSize ?? 10;
29
30
  }
@@ -23,5 +23,3 @@ __export(cache_exports, {
23
23
  module.exports = __toCommonJS(cache_exports);
24
24
  var import_cache = require("./cache");
25
25
  var cache_default = new import_cache.Cache();
26
- // Annotate the CommonJS export names for ESM import in node:
27
- 0 && (module.exports = {});
@@ -32,6 +32,7 @@ class ListManager {
32
32
  this.rootID = rootID2;
33
33
  this.cache = cache;
34
34
  }
35
+ // associate list names with the handler that wraps the list
35
36
  lists = /* @__PURE__ */ new Map();
36
37
  listsByField = /* @__PURE__ */ new Map();
37
38
  get(listName, id, allLists, skipMatches) {
@@ -170,6 +171,8 @@ class List {
170
171
  get fieldRef() {
171
172
  return `${this.recordID}.${this.key}`;
172
173
  }
174
+ // looks for the collection of all of the lists in the cache that satisfies a when
175
+ // condition
173
176
  when(when) {
174
177
  return this.manager.lists.get(this.name).get(this.recordID).when(when);
175
178
  }
@@ -326,6 +329,8 @@ class List {
326
329
  const subscribers = this.cache._internal_unstable.subscriptions.get(this.recordID, this.key);
327
330
  this.cache._internal_unstable.subscriptions.remove(
328
331
  targetID,
332
+ // if we are unsubscribing from a connection, the fields we care about
333
+ // are tucked away under edges
329
334
  this.connection ? this.selection.fields.edges.selection : this.selection,
330
335
  subscribers.map((sub) => sub[0]),
331
336
  variables
@@ -384,6 +389,8 @@ class List {
384
389
  this.addToList(selection, data, variables, where, layer);
385
390
  }
386
391
  }
392
+ // iterating over the list handler should be the same as iterating over
393
+ // the underlying linked list
387
394
  *[Symbol.iterator]() {
388
395
  let entries = [];
389
396
  let value = this.cache._internal_unstable.storage.get(this.recordID, this.key).value;
@@ -442,6 +449,8 @@ class ListCollection {
442
449
  deleteListWithKey(key) {
443
450
  return this.lists = this.lists.filter((list) => list.key !== key);
444
451
  }
452
+ // iterating over the collection should be the same as iterating over
453
+ // the underlying list
445
454
  *[Symbol.iterator]() {
446
455
  for (let list of this.lists) {
447
456
  for (const entry of list) {
@@ -24,6 +24,15 @@ module.exports = __toCommonJS(staleManager_exports);
24
24
  var import_lib = require("../lib");
25
25
  class StaleManager {
26
26
  cache;
27
+ // id { "User:1" "_ROOT_"
28
+ // field { "id" "viewer"
29
+ // number | undefined | null
30
+ // }
31
+ // }
32
+ // number => data ok (not stale!)
33
+ // undefined => no data (not stale!)
34
+ // null => data stale (stale)
35
+ // nulls mean that the value is stale, and the number is the time that the value was set
27
36
  fieldsTime = /* @__PURE__ */ new Map();
28
37
  constructor(cache) {
29
38
  this.cache = cache;
@@ -33,13 +42,28 @@ class StaleManager {
33
42
  this.fieldsTime.set(id, /* @__PURE__ */ new Map());
34
43
  }
35
44
  };
45
+ /**
46
+ * get the FieldTime info
47
+ * @param id User:1
48
+ * @param field firstName
49
+ */
36
50
  getFieldTime(id, field) {
37
51
  return this.fieldsTime.get(id)?.get(field);
38
52
  }
53
+ /**
54
+ * set the date to a field
55
+ * @param id User:1
56
+ * @param field firstName
57
+ */
39
58
  setFieldTimeToNow(id, field) {
40
59
  this.#initMapId(id);
41
- this.fieldsTime.get(id)?.set(field, new Date().valueOf());
60
+ this.fieldsTime.get(id)?.set(field, (/* @__PURE__ */ new Date()).valueOf());
42
61
  }
62
+ /**
63
+ * set null to a field (stale)
64
+ * @param id User:1
65
+ * @param field firstName
66
+ */
43
67
  markFieldStale(id, field) {
44
68
  this.#initMapId(id);
45
69
  this.fieldsTime.get(id)?.set(field, null);
@@ -80,6 +104,7 @@ class StaleManager {
80
104
  }
81
105
  }
82
106
  }
107
+ // clean up the stale manager
83
108
  delete(id, field) {
84
109
  if (this.fieldsTime.has(id)) {
85
110
  this.fieldsTime.get(id)?.delete(field);
@@ -43,6 +43,7 @@ class InMemoryStorage {
43
43
  this.idMaps[from] = to;
44
44
  this.idMaps[to] = from;
45
45
  }
46
+ // create a layer and return its id
46
47
  createLayer(optimistic = false) {
47
48
  const layer = new Layer(this.idCount++);
48
49
  layer.optimistic = optimistic;
@@ -210,6 +211,8 @@ class InMemoryStorage {
210
211
  }
211
212
  return this.data[this.data.length - 1];
212
213
  }
214
+ // return a string representation of all of the data and necessary state to
215
+ // recreate the information stored
213
216
  serialize() {
214
217
  return JSON.stringify({
215
218
  rank: this.rank,
@@ -343,6 +346,7 @@ class Layer {
343
346
  [id]: {
344
347
  ...this.operations[id],
345
348
  deleted: true,
349
+ // reapply any delete undos
346
350
  undoDeletesInList: []
347
351
  }
348
352
  };
@@ -158,6 +158,7 @@ class InMemorySubscriptions {
158
158
  }, {})
159
159
  });
160
160
  }
161
+ // this is different from add because of the treatment of lists
161
162
  addMany({
162
163
  parent,
163
164
  variables,
@@ -36,9 +36,14 @@ class DocumentStore extends import_store.Writable {
36
36
  artifact;
37
37
  #client;
38
38
  #configFile;
39
+ // the list of instantiated plugins
39
40
  #plugins;
41
+ // we need to track the last set of variables used so we can
42
+ // detect if they have changed
40
43
  #lastVariables;
44
+ // we need the last context value we've seen in order to pass it during cleanup
41
45
  #lastContext = null;
46
+ // a reference to the earliest resolving open promise that the store has sent
42
47
  pendingPromise = null;
43
48
  serverSideFallback;
44
49
  controllerKey(variables) {
@@ -77,6 +82,7 @@ class DocumentStore extends import_store.Writable {
77
82
  this.#lastVariables = null;
78
83
  this.#configFile = (0, import_config.getCurrentConfig)();
79
84
  this.#plugins = pipeline ?? [
85
+ // cache policy needs to always come first so that it can be the first network to fire
80
86
  (0, import_plugins.cachePolicy)({
81
87
  cache,
82
88
  enabled: enableCache,
@@ -93,6 +99,7 @@ class DocumentStore extends import_store.Writable {
93
99
  ...plugins ?? []
94
100
  ];
95
101
  }
102
+ // used by the client to send a new set of variables to the pipeline
96
103
  async send({
97
104
  metadata,
98
105
  session,
@@ -159,6 +166,7 @@ class DocumentStore extends import_store.Writable {
159
166
  reject,
160
167
  then: (...args) => promise.then(...args)
161
168
  },
169
+ // patch the context with new variables
162
170
  context
163
171
  };
164
172
  if (this.pendingPromise === null) {
@@ -237,7 +245,14 @@ class DocumentStore extends import_store.Writable {
237
245
  marshalVariables,
238
246
  updateState: this.update.bind(this),
239
247
  next: (newContext) => {
240
- const nextIndex = ["forward", "error"].includes(direction) ? index + 1 : index;
248
+ const nextIndex = ["forward", "error"].includes(direction) ? (
249
+ // if we're going forward, add one
250
+ index + 1
251
+ ) : (
252
+ // if we're moving backwards but called next, we
253
+ // we need to invoke the same hook
254
+ index
255
+ );
241
256
  const nextStep = ["backwards", "error"].includes(direction) ? 0 : ctx.currentStep;
242
257
  this.#step("forward", {
243
258
  ...ctx,
@@ -247,7 +262,14 @@ class DocumentStore extends import_store.Writable {
247
262
  });
248
263
  },
249
264
  resolve: (newContext, value2) => {
250
- const nextIndex = direction === "backwards" ? index - 1 : index;
265
+ const nextIndex = direction === "backwards" ? (
266
+ // if we're going backwards, subtract one
267
+ index - 1
268
+ ) : (
269
+ // if we're moving forwards but then call resolve
270
+ // we need to visit the same hook
271
+ index
272
+ );
251
273
  this.#step(
252
274
  "backwards",
253
275
  {
@@ -344,6 +366,7 @@ class DocumentStore extends import_store.Writable {
344
366
  }
345
367
  }
346
368
  class ClientPluginContextWrapper {
369
+ // separate the last variables from what we pass to the user
347
370
  #context;
348
371
  #lastVariables;
349
372
  constructor({
@@ -356,6 +379,8 @@ class ClientPluginContextWrapper {
356
379
  get variables() {
357
380
  return this.#context.variables;
358
381
  }
382
+ // draft produces a wrapper over the context so users can mutate it without
383
+ // actually affecting the context values
359
384
  draft() {
360
385
  const ctx = {
361
386
  ...this.#context
@@ -423,6 +448,7 @@ class ClientPluginContextWrapper {
423
448
  };
424
449
  return ctx;
425
450
  }
451
+ // apply applies the draft value in a new context
426
452
  apply(values, newVariables) {
427
453
  if (newVariables) {
428
454
  values = this.applyVariables(this.#context, values);
@@ -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
  ));
@@ -42,7 +46,9 @@ var import_injectedPlugins = __toESM(require("./plugins/injectedPlugins"), 1);
42
46
  var import_documentStore2 = require("./documentStore");
43
47
  var import_plugins2 = require("./plugins");
44
48
  class HoudiniClient {
49
+ // the URL of the api
45
50
  url;
51
+ // expose operations settings
46
52
  throwOnError_operations;
47
53
  cache = null;
48
54
  throwOnError;
@@ -50,7 +56,9 @@ class HoudiniClient {
50
56
  pipeline;
51
57
  extraPlugins;
52
58
  proxies = {};
59
+ // this is modified by page entries when they load in order to register the components source
53
60
  componentCache = {};
61
+ // we need the ability to link the client up with an external cache
54
62
  setCache(cache) {
55
63
  this.cache = cache;
56
64
  }
@@ -77,16 +85,24 @@ class HoudiniClient {
77
85
  get plugins() {
78
86
  return (0, import_flatten.flatten)(
79
87
  [].concat(
88
+ // if they specified a throw behavior
80
89
  this.throwOnError ? [(0, import_plugins.throwOnError)(this.throwOnError)] : [],
81
90
  (0, import_plugins.fetchParams)(this.fetchParams),
82
- this.pipeline ?? [
91
+ // if the user wants to specify the entire pipeline, let them do so
92
+ this.pipeline ?? // the user doesn't have a specific pipeline so we should just add their desired plugins
93
+ // to the standard set
94
+ [
83
95
  (0, import_plugins.optimisticKeys)(this.cache ?? import_cache.default),
96
+ // make sure that documents always work
84
97
  (0, import_plugins.query)(this.cache ?? import_cache.default),
85
98
  (0, import_plugins.mutation)(this.cache ?? import_cache.default),
86
99
  (0, import_plugins.fragment)(this.cache ?? import_cache.default)
87
100
  ].concat(
101
+ // add the specified middlewares
88
102
  this.extraPlugins ?? [],
103
+ // and any middlewares we got from plugins
89
104
  import_injectedPlugins.default,
105
+ // if they provided a fetch function, use it as the body for the fetch middleware
90
106
  (0, import_plugins.fetch)()
91
107
  )
92
108
  )
@@ -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
  ));
@@ -49,7 +53,8 @@ const cachePolicy = ({
49
53
  variables: marshalVariables(ctx),
50
54
  fullCheck: true
51
55
  });
52
- const allowed = !value.partial || artifact.kind === import_types.ArtifactKind.Query && artifact.partial;
56
+ const allowed = !value.partial || // or the artifact allows for partial responses
57
+ artifact.kind === import_types.ArtifactKind.Query && artifact.partial;
53
58
  if (policy === import_types.CachePolicy.CacheOnly) {
54
59
  return resolve(ctx, {
55
60
  fetching: false,
@@ -73,7 +78,8 @@ const cachePolicy = ({
73
78
  stale: value.stale
74
79
  });
75
80
  }
76
- if (useCache && !value.partial && !value.stale && ctx.policy !== "CacheAndNetwork") {
81
+ if (useCache && !value.partial && !value.stale && // if the policy is CacheAndNetwork then we don't want to stop here regardless
82
+ ctx.policy !== "CacheAndNetwork") {
77
83
  return;
78
84
  }
79
85
  }
@@ -50,6 +50,8 @@ const fetch = (target) => {
50
50
  }
51
51
  }
52
52
  const result = await fetchFn({
53
+ // wrap the user's fetch function so we can identify SSR by checking
54
+ // the response.url
53
55
  fetch: (url, args) => {
54
56
  const newArgs = handleMultipart(fetchParams, args) ?? args;
55
57
  return fetch2(url, {
@@ -142,8 +144,7 @@ function isExtractableFile(value) {
142
144
  return typeof File !== "undefined" && value instanceof File || typeof Blob !== "undefined" && value instanceof Blob;
143
145
  }
144
146
  function extractFiles(value) {
145
- if (!arguments.length)
146
- throw new TypeError("Argument 1 `value` is required.");
147
+ if (!arguments.length) throw new TypeError("Argument 1 `value` is required.");
147
148
  const clones = /* @__PURE__ */ new Map();
148
149
  const files = /* @__PURE__ */ new Map();
149
150
  function recurse(value2, path, recursed) {
@@ -158,8 +159,16 @@ function extractFiles(value) {
158
159
  let clone = clones.get(value2);
159
160
  const uncloned = !clone;
160
161
  if (uncloned) {
161
- clone = valueIsList ? [] : value2 instanceof Object ? {} : /* @__PURE__ */ Object.create(null);
162
- clones.set(value2, clone);
162
+ clone = valueIsList ? [] : (
163
+ // Replicate if the plain object is an `Object` instance.
164
+ value2 instanceof /** @type {any} */
165
+ Object ? {} : /* @__PURE__ */ Object.create(null)
166
+ );
167
+ clones.set(
168
+ value2,
169
+ /** @type {Clone} */
170
+ clone
171
+ );
163
172
  }
164
173
  if (!recursed.has(value2)) {
165
174
  const pathPrefix = path ? `${path}.` : "";
@@ -168,8 +177,7 @@ function extractFiles(value) {
168
177
  let index = 0;
169
178
  for (const item of value2) {
170
179
  const itemClone = recurse(item, pathPrefix + index++, recursedDeeper);
171
- if (uncloned)
172
- clone.push(itemClone);
180
+ if (uncloned) clone.push(itemClone);
173
181
  }
174
182
  } else
175
183
  for (const key in value2) {
@@ -26,11 +26,13 @@ const fetchParams = (fn = () => ({})) => () => ({
26
26
  next({
27
27
  ...ctx,
28
28
  fetchParams: fn({
29
+ // most of the stuff comes straight from the context
29
30
  config: ctx.config,
30
31
  policy: ctx.policy,
31
32
  metadata: ctx.metadata,
32
33
  session: ctx.session,
33
34
  stuff: ctx.stuff,
35
+ // a few fields are renamed or modified
34
36
  document: ctx.artifact,
35
37
  variables: marshalVariables(ctx),
36
38
  text: ctx.text,
@@ -28,6 +28,7 @@ const fragment = (cache) => (0, import_utils.documentPlugin)(import_types.Artifa
28
28
  let subscriptionSpec = null;
29
29
  let lastReference = null;
30
30
  return {
31
+ // establish the cache subscription
31
32
  start(ctx, { next, resolve, variablesChanged, marshalVariables }) {
32
33
  if (!ctx.stuff.parentID) {
33
34
  return next(ctx);
@@ -33,5 +33,13 @@ __reExport(plugins_exports, require("./fetchParams"), module.exports);
33
33
  var import_optimisticKeys = require("./optimisticKeys");
34
34
  // Annotate the CommonJS export names for ESM import in node:
35
35
  0 && (module.exports = {
36
- optimisticKeys
36
+ optimisticKeys,
37
+ ...require("./fetch"),
38
+ ...require("./cache"),
39
+ ...require("./query"),
40
+ ...require("./fragment"),
41
+ ...require("./mutation"),
42
+ ...require("./subscription"),
43
+ ...require("./throwOnError"),
44
+ ...require("./fetchParams")
37
45
  });
@@ -23,5 +23,3 @@ __export(injectedPlugins_exports, {
23
23
  module.exports = __toCommonJS(injectedPlugins_exports);
24
24
  const plugins = [];
25
25
  var injectedPlugins_default = plugins;
26
- // Annotate the CommonJS export names for ESM import in node:
27
- 0 && (module.exports = {});
@@ -33,6 +33,7 @@ const mutation = (cache) => (0, import_utils.documentPlugin)(import_types.Artifa
33
33
  if (optimisticResponse) {
34
34
  toNotify = cache.write({
35
35
  selection: ctx.artifact.selection,
36
+ // make sure that any scalar values get processed into something we can cache
36
37
  data: await (0, import_scalars.marshalSelection)({
37
38
  selection: ctx.artifact.selection,
38
39
  data: optimisticResponse
@@ -43,8 +44,13 @@ const mutation = (cache) => (0, import_utils.documentPlugin)(import_types.Artifa
43
44
  }
44
45
  ctx.cacheParams = {
45
46
  ...ctx.cacheParams,
47
+ // write to the mutation's layer
46
48
  layer: layerOptimistic,
49
+ // notify any subscribers that we updated with the optimistic response
50
+ // in order to address situations where the optimistic update was wrong
47
51
  notifySubscribers: toNotify,
52
+ // make sure that we notify subscribers for any values that we compare
53
+ // in order to address any race conditions when comparing the previous value
48
54
  forceNotify: true
49
55
  };
50
56
  next(ctx);
@@ -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
  ));
@@ -52,6 +56,8 @@ const optimisticKeys = (cache, callbackCache = callbacks, keyCache = keys, objec
52
56
  }
53
57
  next(newCtx);
54
58
  },
59
+ // if a request has variables that contain an optimistic key we need to block the
60
+ // request before it is sent to the server
55
61
  beforeNetwork(ctx, { next }) {
56
62
  if (Object.keys(keyCache).length === 0) {
57
63
  return next(ctx);
@@ -101,6 +107,7 @@ const optimisticKeys = (cache, callbackCache = callbacks, keyCache = keys, objec
101
107
  }
102
108
  resolve(ctx);
103
109
  },
110
+ // when the mutation ends, we no longer have any dependents that we have to track
104
111
  end(ctx, { resolve }) {
105
112
  if (typeof ctx.stuff.mutationID !== "undefined") {
106
113
  delete keyCache[ctx.stuff.mutationID];
@@ -299,13 +306,13 @@ function replaceKeyWithVariable(variables, keys2) {
299
306
  }
300
307
  function generateKey(type) {
301
308
  if (type === "Int") {
302
- return new Date().getTime();
309
+ return (/* @__PURE__ */ new Date()).getTime();
303
310
  }
304
311
  if (type === "String") {
305
- return new Date().getTime().toString();
312
+ return (/* @__PURE__ */ new Date()).getTime().toString();
306
313
  }
307
314
  if (type === "ID") {
308
- return new Date().getTime().toString();
315
+ return (/* @__PURE__ */ new Date()).getTime().toString();
309
316
  }
310
317
  throw new Error(
311
318
  `unsupported type for optimistic key: ${type}. Please provide a value in your mutation arguments.`
@@ -33,6 +33,8 @@ const query = (cache) => (0, import_utils.documentPlugin)(import_types.ArtifactK
33
33
  };
34
34
  ctx.variables = {
35
35
  ...lastVariables,
36
+ // we need to evaluate any runtime scalars but allow the user to overwrite them
37
+ // by explicitly passing variables
36
38
  ...Object.fromEntries(
37
39
  Object.entries(ctx.artifact.input?.runtimeScalars ?? {}).map(
38
40
  ([field, type]) => {
@@ -48,6 +50,8 @@ const query = (cache) => (0, import_utils.documentPlugin)(import_types.ArtifactK
48
50
  };
49
51
  next(ctx);
50
52
  },
53
+ // patch subscriptions on the way out so that we don't get a cache update
54
+ // before the promise resolves
51
55
  end(ctx, { resolve, marshalVariables, variablesChanged }) {
52
56
  if (variablesChanged(ctx) && !ctx.cacheParams?.disableSubscriptions) {
53
57
  if (subscriptionSpec) {
@@ -16,3 +16,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
16
16
  var utils_exports = {};
17
17
  module.exports = __toCommonJS(utils_exports);
18
18
  __reExport(utils_exports, require("./documentPlugins"), module.exports);
19
+ // Annotate the CommonJS export names for ESM import in node:
20
+ 0 && (module.exports = {
21
+ ...require("./documentPlugins")
22
+ });
@@ -22,5 +22,3 @@ __export(config_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(config_exports);
24
24
  var config_default = {};
25
- // Annotate the CommonJS export names for ESM import in node:
26
- 0 && (module.exports = {});