houdini 1.2.0-react.1 → 1.2.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 (79) hide show
  1. package/README.md +1 -1
  2. package/build/cmd-cjs/index.js +2213 -1533
  3. package/build/cmd-esm/index.js +2213 -1533
  4. package/build/codegen/generators/artifacts/selection.d.ts +2 -1
  5. package/build/codegen/generators/typescript/inlineType.d.ts +5 -2
  6. package/build/codegen/generators/typescript/loadingState.d.ts +8 -0
  7. package/build/codegen/transforms/fragmentVariables.d.ts +0 -11
  8. package/build/codegen-cjs/index.js +2143 -1487
  9. package/build/codegen-esm/index.js +2143 -1487
  10. package/build/lib/config.d.ts +5 -0
  11. package/build/lib/graphql.d.ts +5 -1
  12. package/build/lib/parse.d.ts +10 -1
  13. package/build/lib-cjs/index.js +702 -578
  14. package/build/lib-esm/index.js +699 -578
  15. package/build/runtime/cache/cache.d.ts +9 -8
  16. package/build/runtime/cache/stuff.d.ts +1 -4
  17. package/build/runtime/client/documentStore.d.ts +3 -3
  18. package/build/runtime/client/index.d.ts +8 -7
  19. package/build/runtime/client/plugins/cache.d.ts +1 -1
  20. package/build/runtime/client/plugins/fetch.d.ts +1 -0
  21. package/build/runtime/client/plugins/subscription.d.ts +1 -0
  22. package/build/runtime/client/plugins/throwOnError.d.ts +2 -1
  23. package/build/runtime/lib/pagination.d.ts +4 -6
  24. package/build/runtime/lib/selection.d.ts +1 -1
  25. package/build/runtime/lib/types.d.ts +37 -4
  26. package/build/runtime-cjs/cache/cache.d.ts +9 -8
  27. package/build/runtime-cjs/cache/cache.js +108 -43
  28. package/build/runtime-cjs/cache/stuff.d.ts +1 -4
  29. package/build/runtime-cjs/cache/stuff.js +2 -2
  30. package/build/runtime-cjs/cache/subscription.js +5 -5
  31. package/build/runtime-cjs/client/documentStore.d.ts +3 -3
  32. package/build/runtime-cjs/client/documentStore.js +10 -2
  33. package/build/runtime-cjs/client/index.d.ts +8 -7
  34. package/build/runtime-cjs/client/index.js +12 -4
  35. package/build/runtime-cjs/client/plugins/cache.d.ts +1 -1
  36. package/build/runtime-cjs/client/plugins/cache.js +10 -2
  37. package/build/runtime-cjs/client/plugins/fetch.d.ts +1 -0
  38. package/build/runtime-cjs/client/plugins/fetch.js +3 -2
  39. package/build/runtime-cjs/client/plugins/subscription.d.ts +1 -0
  40. package/build/runtime-cjs/client/plugins/subscription.js +1 -0
  41. package/build/runtime-cjs/client/plugins/throwOnError.d.ts +2 -1
  42. package/build/runtime-cjs/lib/config.js +2 -1
  43. package/build/runtime-cjs/lib/pagination.d.ts +4 -6
  44. package/build/runtime-cjs/lib/pagination.js +0 -12
  45. package/build/runtime-cjs/lib/scalars.js +1 -1
  46. package/build/runtime-cjs/lib/selection.d.ts +1 -1
  47. package/build/runtime-cjs/lib/selection.js +28 -1
  48. package/build/runtime-cjs/lib/types.d.ts +37 -4
  49. package/build/runtime-cjs/lib/types.js +3 -0
  50. package/build/runtime-esm/cache/cache.d.ts +9 -8
  51. package/build/runtime-esm/cache/cache.js +109 -44
  52. package/build/runtime-esm/cache/stuff.d.ts +1 -4
  53. package/build/runtime-esm/cache/stuff.js +2 -2
  54. package/build/runtime-esm/cache/subscription.js +5 -5
  55. package/build/runtime-esm/client/documentStore.d.ts +3 -3
  56. package/build/runtime-esm/client/documentStore.js +10 -2
  57. package/build/runtime-esm/client/index.d.ts +8 -7
  58. package/build/runtime-esm/client/index.js +15 -7
  59. package/build/runtime-esm/client/plugins/cache.d.ts +1 -1
  60. package/build/runtime-esm/client/plugins/cache.js +10 -2
  61. package/build/runtime-esm/client/plugins/fetch.d.ts +1 -0
  62. package/build/runtime-esm/client/plugins/fetch.js +3 -2
  63. package/build/runtime-esm/client/plugins/subscription.d.ts +1 -0
  64. package/build/runtime-esm/client/plugins/subscription.js +1 -0
  65. package/build/runtime-esm/client/plugins/throwOnError.d.ts +2 -1
  66. package/build/runtime-esm/lib/config.js +2 -1
  67. package/build/runtime-esm/lib/pagination.d.ts +4 -6
  68. package/build/runtime-esm/lib/pagination.js +0 -12
  69. package/build/runtime-esm/lib/scalars.js +1 -1
  70. package/build/runtime-esm/lib/selection.d.ts +1 -1
  71. package/build/runtime-esm/lib/selection.js +28 -1
  72. package/build/runtime-esm/lib/types.d.ts +37 -4
  73. package/build/runtime-esm/lib/types.js +2 -0
  74. package/build/test/index.d.ts +15 -0
  75. package/build/test-cjs/index.js +2174 -1490
  76. package/build/test-esm/index.js +2174 -1490
  77. package/build/vite-cjs/index.js +2243 -1561
  78. package/build/vite-esm/index.js +2243 -1561
  79. package/package.json +7 -1
@@ -1,4 +1,4 @@
1
- import { computeKey } from "../lib";
1
+ import { computeKey, PendingValue } from "../lib";
2
2
  import { computeID, defaultConfigValues, keyFieldsForType, getCurrentConfig } from "../lib/config";
3
3
  import { deepEquals } from "../lib/deepEquals";
4
4
  import { flatten } from "../lib/flatten";
@@ -6,7 +6,6 @@ import { getFieldsForType } from "../lib/selection";
6
6
  import { fragmentKey } from "../lib/types";
7
7
  import { GarbageCollector } from "./gc";
8
8
  import { ListManager } from "./lists";
9
- import { SchemaManager } from "./schema";
10
9
  import { StaleManager } from "./staleManager";
11
10
  import { InMemoryStorage } from "./storage";
12
11
  import { evaluateKey } from "./stuff";
@@ -21,7 +20,6 @@ class Cache {
21
20
  lists: new ListManager(this, rootID),
22
21
  lifetimes: new GarbageCollector(this),
23
22
  staleManager: new StaleManager(this),
24
- schema: new SchemaManager(this),
25
23
  disabled: disabled ?? typeof globalThis.window === "undefined"
26
24
  });
27
25
  if (Object.keys(config).length > 0) {
@@ -132,7 +130,6 @@ class CacheInternal {
132
130
  cache;
133
131
  lifetimes;
134
132
  staleManager;
135
- schema;
136
133
  constructor({
137
134
  storage,
138
135
  subscriptions,
@@ -140,7 +137,6 @@ class CacheInternal {
140
137
  cache,
141
138
  lifetimes,
142
139
  staleManager,
143
- schema,
144
140
  disabled,
145
141
  config
146
142
  }) {
@@ -150,7 +146,6 @@ class CacheInternal {
150
146
  this.cache = cache;
151
147
  this.lifetimes = lifetimes;
152
148
  this.staleManager = staleManager;
153
- this.schema = schema;
154
149
  this._config = config;
155
150
  this._disabled = disabled;
156
151
  try {
@@ -180,7 +175,11 @@ class CacheInternal {
180
175
  if (this._disabled) {
181
176
  return [];
182
177
  }
183
- let targetSelection = getFieldsForType(selection, data["__typename"]);
178
+ let targetSelection = getFieldsForType(
179
+ selection,
180
+ data["__typename"],
181
+ false
182
+ );
184
183
  for (const [field, value] of Object.entries(data)) {
185
184
  if (!selection || !targetSelection[field]) {
186
185
  continue;
@@ -191,17 +190,9 @@ class CacheInternal {
191
190
  selection: fieldSelection,
192
191
  operations,
193
192
  abstract: isAbstract,
194
- updates,
195
- nullable
193
+ updates
196
194
  } = targetSelection[field];
197
195
  const key = evaluateKey(keyRaw, variables);
198
- this.schema.setFieldType({
199
- parent,
200
- key: keyRaw,
201
- type: linkedType,
202
- nullable,
203
- link: !!fieldSelection
204
- });
205
196
  if (value && typeof value === "object" && "__typename" in value && value["__typename"]) {
206
197
  linkedType = value["__typename"];
207
198
  }
@@ -446,42 +437,83 @@ class CacheInternal {
446
437
  parent = rootID,
447
438
  variables,
448
439
  stepsFromConnection = null,
449
- ignoreMasking
440
+ ignoreMasking,
441
+ fullCheck = false,
442
+ loading: generateLoading
450
443
  }) {
451
444
  if (parent === null) {
452
445
  return { data: null, partial: false, stale: false, hasData: true };
453
446
  }
454
447
  const target = {};
455
448
  if (selection.fragments) {
456
- target[fragmentKey] = Object.fromEntries(
457
- Object.entries(selection.fragments).map(([key, value]) => [
458
- key,
459
- {
460
- parent,
461
- variables: evaluateFragmentVariables(value, variables ?? {})
462
- }
463
- ])
464
- );
449
+ target[fragmentKey] = {
450
+ loading: Boolean(generateLoading),
451
+ values: Object.fromEntries(
452
+ Object.entries(selection.fragments).filter(([, value]) => !generateLoading || value.loading).map(([key, value]) => [
453
+ key,
454
+ {
455
+ parent,
456
+ variables: evaluateFragmentVariables(
457
+ value.arguments,
458
+ variables ?? {}
459
+ )
460
+ }
461
+ ])
462
+ )
463
+ };
465
464
  }
466
465
  let hasData = !!selection.fragments;
467
466
  let partial = false;
468
467
  let cascadeNull = false;
469
468
  let stale = false;
470
469
  const typename = this.storage.get(parent, "__typename").value;
471
- let targetSelection = getFieldsForType(selection, typename);
470
+ let targetSelection = getFieldsForType(selection, typename, !!generateLoading);
472
471
  for (const [
473
472
  attributeName,
474
- { type, keyRaw, selection: fieldSelection, nullable, list, visible }
473
+ {
474
+ type,
475
+ keyRaw,
476
+ selection: fieldSelection,
477
+ nullable,
478
+ list,
479
+ visible,
480
+ directives,
481
+ loading: fieldLoading,
482
+ abstractHasRequired
483
+ }
475
484
  ] of Object.entries(targetSelection)) {
476
- if (!visible && !ignoreMasking) {
485
+ if (!visible && !ignoreMasking && !fullCheck) {
477
486
  continue;
478
487
  }
488
+ const includeDirective = directives?.find((d) => {
489
+ return d.name === "include";
490
+ });
491
+ if (includeDirective) {
492
+ if (!evaluateFragmentVariables(includeDirective.arguments, variables ?? {})["if"]) {
493
+ continue;
494
+ }
495
+ }
496
+ const skipDirective = directives?.find((d) => {
497
+ return d.name === "skip";
498
+ });
499
+ if (skipDirective) {
500
+ if (evaluateFragmentVariables(skipDirective.arguments, variables ?? {})["if"]) {
501
+ continue;
502
+ }
503
+ }
504
+ const fieldTarget = visible || ignoreMasking ? target : {};
479
505
  const key = evaluateKey(keyRaw, variables);
480
- const { value } = this.storage.get(parent, key);
506
+ if (generateLoading && !fieldLoading) {
507
+ continue;
508
+ }
509
+ let { value } = this.storage.get(parent, key);
481
510
  const dt_field = this.staleManager.getFieldTime(parent, key);
482
511
  if (dt_field === null) {
483
512
  stale = true;
484
513
  }
514
+ if (generateLoading) {
515
+ value = void 0;
516
+ }
485
517
  let nextStep = stepsFromConnection;
486
518
  if (nextStep !== null) {
487
519
  if (nextStep >= 2) {
@@ -497,17 +529,20 @@ class CacheInternal {
497
529
  if (typeof value === "undefined" && !embeddedCursor) {
498
530
  partial = true;
499
531
  }
500
- if (typeof value === "undefined" || value === null) {
501
- target[attributeName] = null;
532
+ if (generateLoading && fieldLoading?.kind === "value") {
533
+ fieldTarget[attributeName] = PendingValue;
534
+ hasData = true;
535
+ } else if (!generateLoading && typeof value === "undefined" || value === null) {
536
+ fieldTarget[attributeName] = null;
502
537
  if (typeof value !== "undefined") {
503
538
  hasData = true;
504
539
  }
505
540
  } else if (!fieldSelection) {
506
541
  const fnUnmarshal = this.config?.scalars?.[type]?.unmarshal;
507
542
  if (fnUnmarshal) {
508
- target[attributeName] = fnUnmarshal(value);
543
+ fieldTarget[attributeName] = fnUnmarshal(value);
509
544
  } else {
510
- target[attributeName] = value;
545
+ fieldTarget[attributeName] = value;
511
546
  }
512
547
  hasData = true;
513
548
  } else if (Array.isArray(value)) {
@@ -516,9 +551,11 @@ class CacheInternal {
516
551
  variables,
517
552
  linkedList: value,
518
553
  stepsFromConnection: nextStep,
519
- ignoreMasking: !!ignoreMasking
554
+ ignoreMasking: !!ignoreMasking,
555
+ fullCheck,
556
+ loading: generateLoading
520
557
  });
521
- target[attributeName] = listValue.data;
558
+ fieldTarget[attributeName] = listValue.data;
522
559
  if (listValue.partial) {
523
560
  partial = true;
524
561
  }
@@ -534,9 +571,11 @@ class CacheInternal {
534
571
  selection: fieldSelection,
535
572
  variables,
536
573
  stepsFromConnection: nextStep,
537
- ignoreMasking
574
+ ignoreMasking,
575
+ fullCheck,
576
+ loading: generateLoading
538
577
  });
539
- target[attributeName] = objectFields.data;
578
+ fieldTarget[attributeName] = objectFields.data;
540
579
  if (objectFields.partial) {
541
580
  partial = true;
542
581
  }
@@ -547,13 +586,27 @@ class CacheInternal {
547
586
  hasData = true;
548
587
  }
549
588
  }
550
- if (target[attributeName] === null && !nullable && !embeddedCursor) {
551
- cascadeNull = true;
589
+ if (generateLoading && fieldLoading?.list) {
590
+ fieldTarget[attributeName] = wrapInLists(
591
+ Array.from({ length: fieldLoading.list.count }).fill(
592
+ fieldTarget[attributeName]
593
+ ),
594
+ fieldLoading.list.depth - 1
595
+ );
596
+ }
597
+ if (fieldTarget[attributeName] === null && !nullable && !embeddedCursor) {
598
+ if (abstractHasRequired) {
599
+ target[attributeName] = {
600
+ __typename: "@required field missing; don't match this"
601
+ };
602
+ } else {
603
+ cascadeNull = true;
604
+ }
552
605
  }
553
606
  }
554
607
  return {
555
608
  data: cascadeNull ? null : target,
556
- partial: hasData && partial,
609
+ partial: !generateLoading && hasData && partial,
557
610
  stale: hasData && stale,
558
611
  hasData
559
612
  };
@@ -579,7 +632,9 @@ class CacheInternal {
579
632
  variables,
580
633
  linkedList,
581
634
  stepsFromConnection,
582
- ignoreMasking
635
+ ignoreMasking,
636
+ fullCheck,
637
+ loading
583
638
  }) {
584
639
  const result = [];
585
640
  let partialData = false;
@@ -592,7 +647,9 @@ class CacheInternal {
592
647
  variables,
593
648
  linkedList: entry,
594
649
  stepsFromConnection,
595
- ignoreMasking
650
+ ignoreMasking,
651
+ fullCheck,
652
+ loading
596
653
  });
597
654
  result.push(nestedValue.data);
598
655
  if (nestedValue.partial) {
@@ -614,7 +671,9 @@ class CacheInternal {
614
671
  selection: fields,
615
672
  variables,
616
673
  stepsFromConnection,
617
- ignoreMasking
674
+ ignoreMasking,
675
+ fullCheck,
676
+ loading
618
677
  });
619
678
  result.push(data);
620
679
  if (partial) {
@@ -721,6 +780,12 @@ function evaluateFragmentVariables(variables, args) {
721
780
  Object.entries(variables).map(([key, value]) => [key, fragmentVariableValue(value, args)])
722
781
  );
723
782
  }
783
+ function wrapInLists(target, count = 0) {
784
+ if (count === 0) {
785
+ return target;
786
+ }
787
+ return wrapInLists([target], count - 1);
788
+ }
724
789
  function fragmentVariableValue(value, args) {
725
790
  if (value.kind === "StringValue") {
726
791
  return value.value;
@@ -1,4 +1 @@
1
- import type { GraphQLValue } from '../lib/types';
2
- export declare function evaluateKey(key: string, variables?: {
3
- [key: string]: GraphQLValue;
4
- }): string;
1
+ export declare function evaluateKey(key: string, variables?: Record<string, any> | null): string;
@@ -1,4 +1,4 @@
1
- function evaluateKey(key, variables = {}) {
1
+ function evaluateKey(key, variables = null) {
2
2
  let evaluated = "";
3
3
  let varName = "";
4
4
  let inString = false;
@@ -8,7 +8,7 @@ function evaluateKey(key, variables = {}) {
8
8
  varName += char;
9
9
  continue;
10
10
  }
11
- const value = variables[varName.slice(1)];
11
+ const value = variables?.[varName.slice(1)];
12
12
  evaluated += typeof value !== "undefined" ? JSON.stringify(value) : "undefined";
13
13
  varName = "";
14
14
  }
@@ -17,7 +17,7 @@ class InMemorySubscriptions {
17
17
  parentType
18
18
  }) {
19
19
  const __typename = this.cache._internal_unstable.storage.get(parent, "__typename").value;
20
- let targetSelection = getFieldsForType(selection, __typename);
20
+ let targetSelection = getFieldsForType(selection, __typename, false);
21
21
  for (const fieldSelection of Object.values(targetSelection || {})) {
22
22
  const {
23
23
  keyRaw,
@@ -34,7 +34,7 @@ class InMemorySubscriptions {
34
34
  let targetSelection2;
35
35
  if (innerSelection) {
36
36
  const __typename2 = this.cache._internal_unstable.storage.get(parent, "__typename").value;
37
- targetSelection2 = getFieldsForType(innerSelection, __typename2);
37
+ targetSelection2 = getFieldsForType(innerSelection, __typename2, false);
38
38
  }
39
39
  this.addFieldSubscription({
40
40
  id: parent,
@@ -145,7 +145,7 @@ class InMemorySubscriptions {
145
145
  filters
146
146
  } = selection;
147
147
  const key = evaluateKey(keyRaw, variables);
148
- const fieldSelection = innerSelection ? getFieldsForType(innerSelection, parentType) : void 0;
148
+ const fieldSelection = innerSelection ? getFieldsForType(innerSelection, parentType, false) : void 0;
149
149
  this.addFieldSubscription({
150
150
  id: parent,
151
151
  key,
@@ -175,7 +175,7 @@ class InMemorySubscriptions {
175
175
  linkedRecord,
176
176
  "__typename"
177
177
  ).value;
178
- let targetSelection2 = getFieldsForType(childSelection, __typename);
178
+ let targetSelection2 = getFieldsForType(childSelection, __typename, false);
179
179
  this.addMany({
180
180
  parent: linkedRecord,
181
181
  variables,
@@ -194,7 +194,7 @@ class InMemorySubscriptions {
194
194
  visited.push(id);
195
195
  const linkedIDs = [];
196
196
  const __typename = this.cache._internal_unstable.storage.get(id, "__typename").value;
197
- let targetSelection = getFieldsForType(selection, __typename);
197
+ let targetSelection = getFieldsForType(selection, __typename, false);
198
198
  for (const fieldSelection of Object.values(targetSelection || {})) {
199
199
  const key = evaluateKey(fieldSelection.keyRaw, variables);
200
200
  this.removeSubscribers(id, key, targets);
@@ -2,8 +2,8 @@ import type { HoudiniClient } from '.';
2
2
  import type { Layer } from '../cache/storage';
3
3
  import type { ConfigFile } from '../lib/config';
4
4
  import { Writable } from '../lib/store';
5
- import type { DocumentArtifact, QueryResult, GraphQLObject, SubscriptionSpec, CachePolicies } from '../lib/types';
6
- export declare class DocumentStore<_Data extends GraphQLObject, _Input extends Record<string, any>> extends Writable<QueryResult<_Data, _Input>> {
5
+ import type { DocumentArtifact, QueryResult, GraphQLObject, SubscriptionSpec, CachePolicies, GraphQLVariables } from '../lib/types';
6
+ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends GraphQLVariables> extends Writable<QueryResult<_Data, _Input>> {
7
7
  #private;
8
8
  pendingPromise: {
9
9
  then: (val: any) => void;
@@ -20,7 +20,7 @@ export declare class DocumentStore<_Data extends GraphQLObject, _Input extends R
20
20
  send({ metadata, session, fetch, variables, policy, stuff, cacheParams, setup, silenceEcho, }?: SendParams): Promise<QueryResult<_Data, _Input>>;
21
21
  cleanup(): Promise<void>;
22
22
  }
23
- declare function marshalVariables<_Data extends GraphQLObject, _Input extends {}>(ctx: ClientPluginContext): Record<string, any>;
23
+ declare function marshalVariables<_Data extends GraphQLObject, _Input extends GraphQLVariables>(ctx: ClientPluginContext): Record<string, any>;
24
24
  export type ClientPlugin = () => ClientHooks | null | (ClientHooks | ClientPlugin | null)[];
25
25
  export type ClientHooks = {
26
26
  start?: ClientPluginEnterPhase;
@@ -48,7 +48,15 @@ class DocumentStore extends Writable {
48
48
  this.#plugins = pipeline ?? [
49
49
  cachePolicy({
50
50
  enabled: cache,
51
- setFetching: (fetching2) => this.update((state) => ({ ...state, fetching: fetching2 }))
51
+ setFetching: (fetching2, data) => {
52
+ this.update((state) => {
53
+ const newState = { ...state, fetching: fetching2 };
54
+ if (fetching2 && data) {
55
+ newState.data = data;
56
+ }
57
+ return newState;
58
+ });
59
+ }
52
60
  })(),
53
61
  ...plugins ?? []
54
62
  ];
@@ -292,7 +300,7 @@ class ClientPluginContextWrapper {
292
300
  };
293
301
  const firstInit = !ctx.stuff.inputs || !ctx.stuff.inputs.init;
294
302
  const hasChanged = Object.keys(changed).length > 0 || firstInit;
295
- if (artifact.kind !== ArtifactKind.Fragment && hasChanged) {
303
+ if (hasChanged) {
296
304
  const newVariables = {
297
305
  ...ctx.stuff.inputs?.marshaled,
298
306
  ...marshalInputs({
@@ -1,11 +1,11 @@
1
1
  /// <reference path="../../../../../houdini.d.ts" />
2
- import type { DocumentArtifact, GraphQLObject, NestedList } from '../lib/types';
3
- import type { ClientPlugin, ClientHooks } from './documentStore';
2
+ import type { DocumentArtifact, GraphQLVariables, GraphQLObject, NestedList } from '../lib/types';
3
+ import type { ClientHooks, ClientPlugin } from './documentStore';
4
4
  import { DocumentStore } from './documentStore';
5
- import { type FetchParamFn, type ThrowOnErrorParams } from './plugins';
5
+ import type { FetchParamFn, ThrowOnErrorOperations, ThrowOnErrorParams } from './plugins';
6
6
  export { DocumentStore, type ClientPlugin, type SendParams } from './documentStore';
7
7
  export { fetch, mutation, query, subscription } from './plugins';
8
- type ConstructorArgs = {
8
+ export type HoudiniClientConstructorArgs = {
9
9
  url: string;
10
10
  fetchParams?: FetchParamFn;
11
11
  plugins?: NestedList<ClientPlugin>;
@@ -19,9 +19,10 @@ export type ObserveParams<_Data extends GraphQLObject, _Artifact extends Documen
19
19
  fetching?: boolean;
20
20
  };
21
21
  export declare class HoudiniClient {
22
- #private;
23
22
  url: string;
24
- constructor({ url, fetchParams, plugins, pipeline, throwOnError }: ConstructorArgs);
25
- observe<_Data extends GraphQLObject, _Input extends Record<string, any>>({ artifact, cache, initialValue, fetching, }: ObserveParams<_Data>): DocumentStore<_Data, _Input>;
23
+ readonly plugins: ClientPlugin[];
24
+ readonly throwOnError_operations: ThrowOnErrorOperations[];
25
+ constructor({ url, fetchParams, plugins, pipeline, throwOnError, }: HoudiniClientConstructorArgs);
26
+ observe<_Data extends GraphQLObject, _Input extends GraphQLVariables>({ artifact, cache, initialValue, fetching, }: ObserveParams<_Data>): DocumentStore<_Data, _Input>;
26
27
  }
27
28
  export declare function createPluginHooks(plugins: ClientPlugin[]): ClientHooks[];
@@ -2,25 +2,33 @@ import { flatten } from "../lib/flatten";
2
2
  import { DocumentStore } from "./documentStore";
3
3
  import {
4
4
  fetch as fetchPlugin,
5
+ fetchParams as fetchParamsPlugin,
6
+ fragment as fragmentPlugin,
5
7
  mutation as mutationPlugin,
6
8
  query as queryPlugin,
7
- fragment as fragmentPlugin,
8
- throwOnError as throwOnErrorPlugin,
9
- fetchParams as fetchParamsPlugin
9
+ throwOnError as throwOnErrorPlugin
10
10
  } from "./plugins";
11
11
  import pluginsFromPlugins from "./plugins/injectedPlugins";
12
12
  import { DocumentStore as DocumentStore2 } from "./documentStore";
13
13
  import { fetch, mutation, query, subscription } from "./plugins";
14
14
  class HoudiniClient {
15
15
  url;
16
- #plugins;
17
- constructor({ url, fetchParams, plugins, pipeline, throwOnError }) {
16
+ plugins;
17
+ throwOnError_operations;
18
+ constructor({
19
+ url,
20
+ fetchParams,
21
+ plugins,
22
+ pipeline,
23
+ throwOnError
24
+ }) {
18
25
  if (plugins && pipeline) {
19
26
  throw new Error(
20
27
  "A client cannot be given a pipeline and a list of plugins at the same time."
21
28
  );
22
29
  }
23
- this.#plugins = flatten(
30
+ this.throwOnError_operations = throwOnError?.operations ?? [];
31
+ this.plugins = flatten(
24
32
  [].concat(
25
33
  throwOnError ? [throwOnErrorPlugin(throwOnError)] : [],
26
34
  fetchParamsPlugin(fetchParams),
@@ -46,7 +54,7 @@ class HoudiniClient {
46
54
  return new DocumentStore({
47
55
  client: this,
48
56
  artifact,
49
- plugins: createPluginHooks(this.#plugins),
57
+ plugins: createPluginHooks(this.plugins),
50
58
  cache,
51
59
  initialValue,
52
60
  fetching
@@ -3,7 +3,7 @@ import { Cache } from '../../cache/cache';
3
3
  import type { ClientPlugin } from '../documentStore';
4
4
  export declare const cachePolicy: ({ enabled, setFetching, cache: localCache, serverSideFallback, }: {
5
5
  enabled: boolean;
6
- setFetching: (val: boolean) => void;
6
+ setFetching: (val: boolean, data?: any) => void;
7
7
  cache?: Cache | undefined;
8
8
  serverSideFallback?: boolean | undefined;
9
9
  }) => ClientPlugin;
@@ -17,7 +17,7 @@ const cachePolicy = ({
17
17
  const value = localCache.read({
18
18
  selection: artifact.selection,
19
19
  variables: marshalVariables(ctx),
20
- parent: ctx.stuff?.parentID
20
+ fullCheck: true
21
21
  });
22
22
  const allowed = !value.partial || artifact.kind === ArtifactKind.Query && artifact.partial;
23
23
  if (policy === CachePolicy.CacheOnly) {
@@ -54,7 +54,15 @@ const cachePolicy = ({
54
54
  }, 0);
55
55
  }
56
56
  if (!ctx.stuff?.silenceLoading) {
57
- setFetching(!useCache);
57
+ let fetchingState = null;
58
+ if (!useCache && "enableLoadingState" in artifact && artifact.enableLoadingState) {
59
+ fetchingState = localCache.read({
60
+ selection: artifact.selection,
61
+ variables: marshalVariables(ctx),
62
+ loading: true
63
+ }).data;
64
+ }
65
+ setFetching(!useCache, fetchingState);
58
66
  }
59
67
  return next(ctx);
60
68
  },
@@ -21,6 +21,7 @@ export type FetchContext = {
21
21
  export type RequestHandlerArgs = FetchContext & FetchParams;
22
22
  export type RequestHandler<_Data = any> = (args: RequestHandlerArgs) => Promise<RequestPayload<_Data>>;
23
23
  export type FetchParams = {
24
+ name: string;
24
25
  text: string;
25
26
  hash: string;
26
27
  variables: {
@@ -8,6 +8,7 @@ const fetch = (target) => {
8
8
  }
9
9
  const fetch2 = ctx.fetch ?? globalThis.fetch;
10
10
  const fetchParams = {
11
+ name: ctx.artifact.name,
11
12
  text: ctx.text,
12
13
  hash: ctx.hash,
13
14
  variables: marshalVariables(ctx)
@@ -48,10 +49,10 @@ const defaultFetch = (url, params) => {
48
49
  "Could not find configured client url. Please specify one in your HoudiniClient constructor."
49
50
  );
50
51
  }
51
- return async ({ fetch: fetch2, text, variables }) => {
52
+ return async ({ fetch: fetch2, name, text, variables }) => {
52
53
  const result = await fetch2(url, {
53
54
  method: "POST",
54
- body: JSON.stringify({ query: text, variables }),
55
+ body: JSON.stringify({ operationName: name, query: text, variables }),
55
56
  ...params,
56
57
  headers: {
57
58
  Accept: "application/graphql+json, application/json",
@@ -3,6 +3,7 @@ export declare function subscription(factory: SubscriptionHandler): import("../d
3
3
  export type SubscriptionHandler = (ctx: ClientPluginContext) => SubscriptionClient;
4
4
  export type SubscriptionClient = {
5
5
  subscribe: (payload: {
6
+ operationName: string;
6
7
  query: string;
7
8
  variables?: {};
8
9
  }, handlers: {
@@ -32,6 +32,7 @@ function subscription(factory) {
32
32
  clearSubscription?.();
33
33
  clearSubscription = client.subscribe(
34
34
  {
35
+ operationName: ctx.artifact.name,
35
36
  query: ctx.artifact.raw,
36
37
  variables: marshalVariables(ctx)
37
38
  },
@@ -1,7 +1,8 @@
1
1
  import type { QueryResult } from '../../lib';
2
2
  import type { ClientPlugin, ClientPluginContext } from '../documentStore';
3
+ export type ThrowOnErrorOperations = 'all' | 'query' | 'mutation' | 'subscription';
3
4
  export type ThrowOnErrorParams = {
4
- operations: ('all' | 'query' | 'mutation' | 'subscription')[];
5
+ operations: ThrowOnErrorOperations[];
5
6
  error?: (errors: NonNullable<QueryResult<any, any>['errors']>, ctx: ClientPluginContext) => unknown;
6
7
  };
7
8
  export declare const throwOnError: ({ operations, error }: ThrowOnErrorParams) => ClientPlugin;
@@ -24,7 +24,8 @@ function defaultConfigValues(file) {
24
24
  };
25
25
  }
26
26
  function keyFieldsForType(configFile, type) {
27
- return configFile.types?.[type]?.keys || configFile.defaultKeys;
27
+ const withDefault = defaultConfigValues(configFile);
28
+ return withDefault.types?.[type]?.keys || withDefault.defaultKeys;
28
29
  }
29
30
  function computeID(configFile, type, data) {
30
31
  const fields = keyFieldsForType(configFile, type);
@@ -1,16 +1,14 @@
1
1
  import type { SendParams } from '../client/documentStore';
2
- import { FetchParams } from './types';
3
- import type { CursorHandlers, FetchFn, GraphQLObject, QueryArtifact, QueryResult } from './types';
4
- export declare function cursorHandlers<_Data extends GraphQLObject, _Input extends Record<string, any>>({ artifact, storeName, fetchUpdate: parentFetchUpdate, fetch: parentFetch, getState, getVariables, getSession, }: {
2
+ import type { CursorHandlers, FetchFn, GraphQLObject, GraphQLVariables, QueryArtifact, QueryResult, FetchParams } from './types';
3
+ export declare function cursorHandlers<_Data extends GraphQLObject, _Input extends GraphQLVariables>({ artifact, fetchUpdate: parentFetchUpdate, fetch: parentFetch, getState, getVariables, getSession, }: {
5
4
  artifact: QueryArtifact;
6
- storeName: string;
7
5
  getState: () => _Data | null;
8
- getVariables: () => _Input;
6
+ getVariables: () => NonNullable<_Input>;
9
7
  getSession: () => Promise<App.Session>;
10
8
  fetch: FetchFn<_Data, _Input>;
11
9
  fetchUpdate: (arg: SendParams, updates: string[]) => ReturnType<FetchFn<_Data, _Input>>;
12
10
  }): CursorHandlers<_Data, _Input>;
13
- export declare function offsetHandlers<_Data extends GraphQLObject, _Input extends {}>({ artifact, storeName, getState, getVariables, fetch: parentFetch, fetchUpdate: parentFetchUpdate, getSession, }: {
11
+ export declare function offsetHandlers<_Data extends GraphQLObject, _Input extends GraphQLVariables>({ artifact, storeName, getState, getVariables, fetch: parentFetch, fetchUpdate: parentFetchUpdate, getSession, }: {
14
12
  artifact: QueryArtifact;
15
13
  fetch: FetchFn<_Data, _Input>;
16
14
  fetchUpdate: (arg: SendParams) => ReturnType<FetchFn<_Data, _Input>>;
@@ -1,11 +1,9 @@
1
1
  import { getCurrentConfig } from "./config";
2
- import { siteURL } from "./constants";
3
2
  import { deepEquals } from "./deepEquals";
4
3
  import { countPage, extractPageInfo, missingPageSizeError } from "./pageInfo";
5
4
  import { CachePolicy } from "./types";
6
5
  function cursorHandlers({
7
6
  artifact,
8
- storeName,
9
7
  fetchUpdate: parentFetchUpdate,
10
8
  fetch: parentFetch,
11
9
  getState,
@@ -39,16 +37,6 @@ function cursorHandlers({
39
37
  },
40
38
  isSinglePage ? [] : [where === "start" ? "prepend" : "append"]
41
39
  );
42
- const resultPath = [...artifact.refetch.path];
43
- if (artifact.refetch.embedded) {
44
- const { targetType } = artifact.refetch;
45
- if (!config.types?.[targetType]?.resolve) {
46
- throw new Error(
47
- `Missing type resolve configuration for ${targetType}. For more information, see ${siteURL}/guides/pagination#paginated-fragments`
48
- );
49
- }
50
- resultPath.unshift(config.types[targetType].resolve.queryField);
51
- }
52
40
  };
53
41
  const getPageInfo = () => {
54
42
  return extractPageInfo(getState(), artifact.refetch?.path ?? []);
@@ -11,7 +11,7 @@ async function marshalSelection({
11
11
  if (Array.isArray(data)) {
12
12
  return await Promise.all(data.map((val) => marshalSelection({ selection, data: val })));
13
13
  }
14
- const targetSelection = getFieldsForType(selection, data["__typename"]);
14
+ const targetSelection = getFieldsForType(selection, data["__typename"], false);
15
15
  return Object.fromEntries(
16
16
  await Promise.all(
17
17
  Object.entries(data).map(async ([fieldName, value]) => {