@mearie/core 0.3.0 → 0.5.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.
package/dist/index.cjs CHANGED
@@ -318,6 +318,12 @@ const RootFieldKey = "__root";
318
318
  * @internal
319
319
  */
320
320
  const FragmentRefKey = "__fragmentRef";
321
+ /**
322
+ * Special key used to carry merged variable context (fragment args + operation variables)
323
+ * on fragment references. Used by readFragment to resolve variable-dependent field keys.
324
+ * @internal
325
+ */
326
+ const FragmentVarsKey = "__fragmentVars";
321
327
 
322
328
  //#endregion
323
329
  //#region src/cache/utils.ts
@@ -391,6 +397,14 @@ const isFragmentRef = (value) => {
391
397
  return typeof value === "object" && value !== null && FragmentRefKey in value;
392
398
  };
393
399
  /**
400
+ * Extracts the merged variable context for a specific fragment from a fragment reference.
401
+ * Returns the merged variables (fragment args + operation variables) if present, or an empty object.
402
+ * @internal
403
+ */
404
+ const getFragmentVars = (fragmentRef, fragmentName) => {
405
+ return fragmentRef[FragmentVarsKey]?.[fragmentName] ?? {};
406
+ };
407
+ /**
394
408
  * Type guard to check if a value is an array of fragment references.
395
409
  * @internal
396
410
  * @param value - Value to check.
@@ -501,33 +515,20 @@ const mergeFields = (target, source) => {
501
515
  const makeFieldKeyFromArgs = (field, args) => {
502
516
  return `${field}@${args && Object.keys(args).length > 0 ? stringify(args) : "{}"}`;
503
517
  };
504
- /**
505
- * Converts an EntityId to an EntityKey.
506
- * @internal
507
- * @param typename - The GraphQL typename of the entity.
508
- * @param id - The entity identifier (string, number, or composite key record).
509
- * @param keyFields - Optional ordered list of key field names for composite keys.
510
- * @returns An EntityKey.
511
- */
512
- const resolveEntityKey = (typename, id, keyFields) => {
513
- if (typeof id === "string" || typeof id === "number") return makeEntityKey(typename, [id]);
514
- return makeEntityKey(typename, keyFields ? keyFields.map((f) => id[f]) : Object.values(id));
515
- };
516
518
 
517
519
  //#endregion
518
520
  //#region src/cache/normalize.ts
519
- const SKIP = Symbol();
520
521
  const normalize = (schemaMeta, selections, storage, data, variables, accessor) => {
521
522
  const normalizeField = (storageKey, selections, value) => {
522
523
  if (isNullish(value)) return value;
523
524
  if (Array.isArray(value)) return value.map((item) => normalizeField(storageKey, selections, item));
524
525
  const data = value;
525
526
  const typename = data.__typename;
526
- const entityMeta = schemaMeta.entities[typename];
527
+ let entityMeta = schemaMeta.entities[typename];
527
528
  if (entityMeta) {
528
529
  const keys = entityMeta.keyFields.map((field) => data[field]);
529
- if (!keys.every((k) => k !== void 0 && k !== null)) return SKIP;
530
- storageKey = makeEntityKey(typename, keys);
530
+ if (keys.every((k) => k !== void 0 && k !== null)) storageKey = makeEntityKey(typename, keys);
531
+ else entityMeta = void 0;
531
532
  }
532
533
  const fields = {};
533
534
  for (const selection of selections) if (selection.kind === "Field") {
@@ -535,13 +536,11 @@ const normalize = (schemaMeta, selections, storage, data, variables, accessor) =
535
536
  const fieldValue = data[selection.alias ?? selection.name];
536
537
  const oldValue = storageKey === null ? void 0 : storage[storageKey]?.[fieldKey];
537
538
  if (storageKey !== null && (!selection.selections || isNullish(oldValue) || isNullish(fieldValue))) accessor?.(storageKey, fieldKey, oldValue, fieldValue);
538
- const normalized = selection.selections ? normalizeField(null, selection.selections, fieldValue) : fieldValue;
539
- if (normalized === SKIP) continue;
540
- fields[fieldKey] = normalized;
539
+ fields[fieldKey] = selection.selections ? normalizeField(null, selection.selections, fieldValue) : fieldValue;
541
540
  if (storageKey !== null && selection.selections && !isNullish(oldValue) && !isNullish(fieldValue) && !isEntityLink(fields[fieldKey]) && !isEqual(oldValue, fields[fieldKey])) accessor?.(storageKey, fieldKey, oldValue, fields[fieldKey]);
542
541
  } else if (selection.kind === "FragmentSpread" || selection.kind === "InlineFragment" && selection.on === typename) {
543
542
  const inner = normalizeField(storageKey, selection.selections, value);
544
- if (inner !== SKIP && !isEntityLink(inner)) mergeFields(fields, inner);
543
+ if (!isEntityLink(inner)) mergeFields(fields, inner);
545
544
  }
546
545
  if (entityMeta && storageKey !== null) {
547
546
  const existing = storage[storageKey];
@@ -596,6 +595,17 @@ const denormalize = (selections, storage, value, variables, accessor) => {
596
595
  else fields[name] = value;
597
596
  } else if (selection.kind === "FragmentSpread") if (storageKey !== null && storageKey !== RootFieldKey) {
598
597
  fields[FragmentRefKey] = storageKey;
598
+ if (selection.args) {
599
+ const resolvedArgs = resolveArguments(selection.args, variables);
600
+ const mergedVars = {
601
+ ...variables,
602
+ ...resolvedArgs
603
+ };
604
+ fields[FragmentVarsKey] = {
605
+ ...fields[FragmentVarsKey],
606
+ [selection.name]: mergedVars
607
+ };
608
+ }
599
609
  if (accessor) denormalize(selection.selections, storage, { [EntityLinkKey]: storageKey }, variables, accessor);
600
610
  } else mergeFields(fields, denormalizeField(storageKey, selection.selections, value));
601
611
  else if (selection.kind === "InlineFragment" && selection.on === data[typenameFieldKey]) mergeFields(fields, denormalizeField(storageKey, selection.selections, value));
@@ -619,9 +629,74 @@ var Cache = class {
619
629
  #subscriptions = /* @__PURE__ */ new Map();
620
630
  #memo = /* @__PURE__ */ new Map();
621
631
  #stale = /* @__PURE__ */ new Set();
632
+ #optimisticKeys = [];
633
+ #optimisticLayers = /* @__PURE__ */ new Map();
634
+ #storageView = null;
622
635
  constructor(schemaMetadata) {
623
636
  this.#schemaMeta = schemaMetadata;
624
637
  }
638
+ #getStorageView() {
639
+ if (this.#optimisticKeys.length === 0) return this.#storage;
640
+ if (this.#storageView) return this.#storageView;
641
+ const merged = { ...this.#storage };
642
+ for (const storageKey of Object.keys(this.#storage)) merged[storageKey] = { ...this.#storage[storageKey] };
643
+ for (const key of this.#optimisticKeys) {
644
+ const layer = this.#optimisticLayers.get(key);
645
+ if (!layer) continue;
646
+ for (const storageKey of Object.keys(layer.storage)) merged[storageKey] = merged[storageKey] ? {
647
+ ...merged[storageKey],
648
+ ...layer.storage[storageKey]
649
+ } : { ...layer.storage[storageKey] };
650
+ }
651
+ this.#storageView = merged;
652
+ return merged;
653
+ }
654
+ /**
655
+ * Writes an optimistic response to a separate cache layer.
656
+ * The optimistic data is immediately visible in reads but does not affect the base storage.
657
+ * @internal
658
+ * @param key - Unique key identifying this optimistic mutation (typically the operation key).
659
+ * @param artifact - GraphQL document artifact.
660
+ * @param variables - Operation variables.
661
+ * @param data - The optimistic response data.
662
+ */
663
+ writeOptimistic(key, artifact, variables, data) {
664
+ const layerStorage = { [RootFieldKey]: {} };
665
+ const dependencies = /* @__PURE__ */ new Set();
666
+ normalize(this.#schemaMeta, artifact.selections, layerStorage, data, variables, (storageKey, fieldKey) => {
667
+ dependencies.add(makeDependencyKey(storageKey, fieldKey));
668
+ });
669
+ this.#optimisticKeys.push(key);
670
+ this.#optimisticLayers.set(key, {
671
+ storage: layerStorage,
672
+ dependencies
673
+ });
674
+ this.#storageView = null;
675
+ const subscriptions = /* @__PURE__ */ new Set();
676
+ for (const depKey of dependencies) {
677
+ const ss = this.#subscriptions.get(depKey);
678
+ if (ss) for (const s of ss) subscriptions.add(s);
679
+ }
680
+ for (const subscription of subscriptions) subscription.listener();
681
+ }
682
+ /**
683
+ * Removes an optimistic layer and notifies affected subscribers.
684
+ * @internal
685
+ * @param key - The key of the optimistic layer to remove.
686
+ */
687
+ removeOptimistic(key) {
688
+ const layer = this.#optimisticLayers.get(key);
689
+ if (!layer) return;
690
+ this.#optimisticLayers.delete(key);
691
+ this.#optimisticKeys = this.#optimisticKeys.filter((k) => k !== key);
692
+ this.#storageView = null;
693
+ const subscriptions = /* @__PURE__ */ new Set();
694
+ for (const depKey of layer.dependencies) {
695
+ const ss = this.#subscriptions.get(depKey);
696
+ if (ss) for (const s of ss) subscriptions.add(s);
697
+ }
698
+ for (const subscription of subscriptions) subscription.listener();
699
+ }
625
700
  /**
626
701
  * Writes a query result to the cache, normalizing entities.
627
702
  * @param artifact - GraphQL document artifact.
@@ -654,7 +729,8 @@ var Cache = class {
654
729
  */
655
730
  readQuery(artifact, variables) {
656
731
  let stale = false;
657
- const { data, partial } = denormalize(artifact.selections, this.#storage, this.#storage[RootFieldKey], variables, (storageKey, fieldKey) => {
732
+ const storage = this.#getStorageView();
733
+ const { data, partial } = denormalize(artifact.selections, storage, storage[RootFieldKey], variables, (storageKey, fieldKey) => {
658
734
  if (this.#stale.has(storageKey) || this.#stale.has(makeDependencyKey(storageKey, fieldKey))) stale = true;
659
735
  });
660
736
  if (partial) return {
@@ -679,7 +755,8 @@ var Cache = class {
679
755
  */
680
756
  subscribeQuery(artifact, variables, listener) {
681
757
  const dependencies = /* @__PURE__ */ new Set();
682
- denormalize(artifact.selections, this.#storage, this.#storage[RootFieldKey], variables, (storageKey, fieldKey) => {
758
+ const storageView = this.#getStorageView();
759
+ denormalize(artifact.selections, storageView, storageView[RootFieldKey], variables, (storageKey, fieldKey) => {
683
760
  const dependencyKey = makeDependencyKey(storageKey, fieldKey);
684
761
  dependencies.add(dependencyKey);
685
762
  });
@@ -694,19 +771,22 @@ var Cache = class {
694
771
  */
695
772
  readFragment(artifact, fragmentRef) {
696
773
  const entityKey = fragmentRef[FragmentRefKey];
697
- if (!this.#storage[entityKey]) return {
774
+ const fragmentVars = getFragmentVars(fragmentRef, artifact.name);
775
+ const storageView = this.#getStorageView();
776
+ if (!storageView[entityKey]) return {
698
777
  data: null,
699
778
  stale: false
700
779
  };
701
780
  let stale = false;
702
- const { data, partial } = denormalize(artifact.selections, this.#storage, { [EntityLinkKey]: entityKey }, {}, (storageKey, fieldKey) => {
781
+ const { data, partial } = denormalize(artifact.selections, storageView, { [EntityLinkKey]: entityKey }, fragmentVars, (storageKey, fieldKey) => {
703
782
  if (this.#stale.has(storageKey) || this.#stale.has(makeDependencyKey(storageKey, fieldKey))) stale = true;
704
783
  });
705
784
  if (partial) return {
706
785
  data: null,
707
786
  stale: false
708
787
  };
709
- const key = makeMemoKey("fragment", artifact.name, entityKey);
788
+ const argsId = Object.keys(fragmentVars).length > 0 ? entityKey + stringify(fragmentVars) : entityKey;
789
+ const key = makeMemoKey("fragment", artifact.name, argsId);
710
790
  const prev = this.#memo.get(key);
711
791
  const result = prev === void 0 ? data : replaceEqualDeep(prev, data);
712
792
  this.#memo.set(key, result);
@@ -717,8 +797,10 @@ var Cache = class {
717
797
  }
718
798
  subscribeFragment(artifact, fragmentRef, listener) {
719
799
  const entityKey = fragmentRef[FragmentRefKey];
800
+ const fragmentVars = getFragmentVars(fragmentRef, artifact.name);
720
801
  const dependencies = /* @__PURE__ */ new Set();
721
- denormalize(artifact.selections, this.#storage, { [EntityLinkKey]: entityKey }, {}, (storageKey, fieldKey) => {
802
+ const storageView = this.#getStorageView();
803
+ denormalize(artifact.selections, storageView, { [EntityLinkKey]: entityKey }, fragmentVars, (storageKey, fieldKey) => {
722
804
  const dependencyKey = makeDependencyKey(storageKey, fieldKey);
723
805
  dependencies.add(dependencyKey);
724
806
  });
@@ -748,9 +830,11 @@ var Cache = class {
748
830
  }
749
831
  subscribeFragments(artifact, fragmentRefs, listener) {
750
832
  const dependencies = /* @__PURE__ */ new Set();
833
+ const storageView = this.#getStorageView();
751
834
  for (const ref of fragmentRefs) {
752
835
  const entityKey = ref[FragmentRefKey];
753
- denormalize(artifact.selections, this.#storage, { [EntityLinkKey]: entityKey }, {}, (storageKey, fieldKey) => {
836
+ const fragmentVars = getFragmentVars(ref, artifact.name);
837
+ denormalize(artifact.selections, storageView, { [EntityLinkKey]: entityKey }, fragmentVars, (storageKey, fieldKey) => {
754
838
  dependencies.add(makeDependencyKey(storageKey, fieldKey));
755
839
  });
756
840
  }
@@ -762,8 +846,8 @@ var Cache = class {
762
846
  */
763
847
  invalidate(...targets) {
764
848
  const subscriptions = /* @__PURE__ */ new Set();
765
- for (const target of targets) if (target.__typename === "Query") if ("field" in target) {
766
- const fieldKey = makeFieldKeyFromArgs(target.field, target.args);
849
+ for (const target of targets) if (target.__typename === "Query") if ("$field" in target) {
850
+ const fieldKey = makeFieldKeyFromArgs(target.$field, target.$args);
767
851
  const depKey = makeDependencyKey(RootFieldKey, fieldKey);
768
852
  this.#stale.add(depKey);
769
853
  this.#collectSubscriptions(RootFieldKey, fieldKey, subscriptions);
@@ -771,32 +855,39 @@ var Cache = class {
771
855
  this.#stale.add(RootFieldKey);
772
856
  this.#collectSubscriptions(RootFieldKey, void 0, subscriptions);
773
857
  }
774
- else if ("id" in target) {
775
- const entityKey = resolveEntityKey(target.__typename, target.id, this.#schemaMeta.entities[target.__typename]?.keyFields);
776
- if ("field" in target) {
777
- const fieldKey = makeFieldKeyFromArgs(target.field, target.args);
778
- this.#stale.add(makeDependencyKey(entityKey, fieldKey));
779
- this.#collectSubscriptions(entityKey, fieldKey, subscriptions);
780
- } else {
781
- this.#stale.add(entityKey);
782
- this.#collectSubscriptions(entityKey, void 0, subscriptions);
783
- }
784
- } else {
785
- const prefix = `${target.__typename}:`;
786
- for (const key of Object.keys(this.#storage)) if (key.startsWith(prefix)) {
787
- const entityKey = key;
788
- if ("field" in target) {
789
- const fieldKey = makeFieldKeyFromArgs(target.field, target.args);
858
+ else {
859
+ const keyFields = this.#schemaMeta.entities[target.__typename]?.keyFields;
860
+ if (keyFields && this.#hasKeyFields(target, keyFields)) {
861
+ const keyValues = keyFields.map((f) => target[f]);
862
+ const entityKey = makeEntityKey(target.__typename, keyValues);
863
+ if ("$field" in target) {
864
+ const fieldKey = makeFieldKeyFromArgs(target.$field, target.$args);
790
865
  this.#stale.add(makeDependencyKey(entityKey, fieldKey));
791
866
  this.#collectSubscriptions(entityKey, fieldKey, subscriptions);
792
867
  } else {
793
868
  this.#stale.add(entityKey);
794
869
  this.#collectSubscriptions(entityKey, void 0, subscriptions);
795
870
  }
871
+ } else {
872
+ const prefix = `${target.__typename}:`;
873
+ for (const key of Object.keys(this.#storage)) if (key.startsWith(prefix)) {
874
+ const entityKey = key;
875
+ if ("$field" in target) {
876
+ const fieldKey = makeFieldKeyFromArgs(target.$field, target.$args);
877
+ this.#stale.add(makeDependencyKey(entityKey, fieldKey));
878
+ this.#collectSubscriptions(entityKey, fieldKey, subscriptions);
879
+ } else {
880
+ this.#stale.add(entityKey);
881
+ this.#collectSubscriptions(entityKey, void 0, subscriptions);
882
+ }
883
+ }
796
884
  }
797
885
  }
798
886
  for (const subscription of subscriptions) subscription.listener();
799
887
  }
888
+ #hasKeyFields(target, keyFields) {
889
+ return keyFields.every((f) => f in target);
890
+ }
800
891
  #collectSubscriptions(storageKey, fieldKey, out) {
801
892
  if (fieldKey === void 0) {
802
893
  const prefix = `${storageKey}.`;
@@ -824,6 +915,7 @@ var Cache = class {
824
915
  }
825
916
  /**
826
917
  * Extracts a serializable snapshot of the cache storage and structural sharing state.
918
+ * Optimistic layers are excluded because they represent transient in-flight state.
827
919
  */
828
920
  extract() {
829
921
  return {
@@ -841,6 +933,7 @@ var Cache = class {
841
933
  ...fields
842
934
  };
843
935
  for (const [key, value] of Object.entries(memo)) this.#memo.set(key, value);
936
+ this.#storageView = null;
844
937
  }
845
938
  /**
846
939
  * Clears all cache data.
@@ -850,6 +943,9 @@ var Cache = class {
850
943
  this.#subscriptions.clear();
851
944
  this.#memo.clear();
852
945
  this.#stale.clear();
946
+ this.#optimisticKeys = [];
947
+ this.#optimisticLayers.clear();
948
+ this.#storageView = null;
853
949
  }
854
950
  };
855
951
 
@@ -882,10 +978,10 @@ const cacheExchange = (options = {}) => {
882
978
  },
883
979
  io: (ops$) => {
884
980
  const fragment$ = require_make.pipe(ops$, require_make.filter((op) => op.variant === "request" && op.artifact.kind === "fragment"), require_make.mergeMap((op) => {
885
- const fragmentRef = op.metadata?.fragmentRef;
981
+ const fragmentRef = op.metadata?.fragment?.ref;
886
982
  if (!fragmentRef) return require_make.fromValue({
887
983
  operation: op,
888
- errors: [new ExchangeError("Fragment operation missing fragmentRef in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "cache" })]
984
+ errors: [new ExchangeError("Fragment operation missing fragment.ref in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "cache" })]
889
985
  });
890
986
  if (isFragmentRefArray(fragmentRef)) {
891
987
  const trigger = require_make.makeSubject();
@@ -917,7 +1013,9 @@ const cacheExchange = (options = {}) => {
917
1013
  errors: []
918
1014
  })));
919
1015
  }));
920
- const nonCache$ = require_make.pipe(ops$, require_make.filter((op) => op.variant === "request" && (op.artifact.kind === "mutation" || op.artifact.kind === "subscription" || op.artifact.kind === "query" && fetchPolicy === "network-only")));
1016
+ const nonCache$ = require_make.pipe(ops$, require_make.filter((op) => op.variant === "request" && (op.artifact.kind === "mutation" || op.artifact.kind === "subscription" || op.artifact.kind === "query" && fetchPolicy === "network-only")), require_make.tap((op) => {
1017
+ if (op.artifact.kind === "mutation" && op.metadata?.cache?.optimisticResponse) cache.writeOptimistic(op.key, op.artifact, op.variables, op.metadata.cache.optimisticResponse);
1018
+ }));
921
1019
  const query$ = require_make.pipe(ops$, require_make.filter((op) => op.variant === "request" && op.artifact.kind === "query" && fetchPolicy !== "network-only"), require_make.share());
922
1020
  const refetch$ = require_make.makeSubject();
923
1021
  return require_make.merge(fragment$, require_make.pipe(query$, require_make.mergeMap((op) => {
@@ -960,9 +1058,18 @@ const cacheExchange = (options = {}) => {
960
1058
  }), require_make.filter(() => fetchPolicy === "cache-only" || fetchPolicy === "cache-and-network" || fetchPolicy === "cache-first")), require_make.pipe(require_make.merge(nonCache$, require_make.pipe(query$, require_make.filter((op) => {
961
1059
  const { data } = cache.readQuery(op.artifact, op.variables);
962
1060
  return fetchPolicy === "cache-and-network" || data === null;
963
- })), require_make.pipe(ops$, require_make.filter((op) => op.variant === "teardown")), refetch$.source), forward, require_make.tap((result) => {
1061
+ })), require_make.pipe(ops$, require_make.filter((op) => op.variant === "teardown")), refetch$.source), forward, require_make.mergeMap((result) => {
1062
+ if (result.operation.variant === "request" && result.operation.artifact.kind === "mutation" && result.operation.metadata?.cache?.optimisticResponse) cache.removeOptimistic(result.operation.key);
964
1063
  if (result.operation.variant === "request" && result.data) cache.writeQuery(result.operation.artifact, result.operation.variables, result.data);
965
- }), require_make.filter((result) => result.operation.variant !== "request" || result.operation.artifact.kind !== "query" || fetchPolicy === "network-only" || !!(result.errors && result.errors.length > 0))));
1064
+ if (result.operation.variant !== "request" || result.operation.artifact.kind !== "query" || fetchPolicy === "network-only" || !!(result.errors && result.errors.length > 0)) return require_make.fromValue(result);
1065
+ const { data } = cache.readQuery(result.operation.artifact, result.operation.variables);
1066
+ if (data !== null) return empty();
1067
+ return require_make.fromValue({
1068
+ operation: result.operation,
1069
+ data: void 0,
1070
+ errors: [new ExchangeError("Cache failed to denormalize the network response. This is likely a bug in the cache normalizer.", { exchangeName: "cache" })]
1071
+ });
1072
+ })));
966
1073
  }
967
1074
  };
968
1075
  };
@@ -1014,10 +1121,10 @@ const fragmentExchange = () => {
1014
1121
  name: "fragment",
1015
1122
  io: (ops$) => {
1016
1123
  return require_make.merge(require_make.pipe(ops$, require_make.filter((op) => op.variant === "request" && op.artifact.kind === "fragment"), require_make.map((op) => {
1017
- const fragmentRef = op.metadata.fragmentRef;
1124
+ const fragmentRef = op.metadata.fragment?.ref;
1018
1125
  if (!fragmentRef) return {
1019
1126
  operation: op,
1020
- errors: [new ExchangeError("Fragment operation missing fragmentRef in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "fragment" })]
1127
+ errors: [new ExchangeError("Fragment operation missing fragment.ref in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "fragment" })]
1021
1128
  };
1022
1129
  return {
1023
1130
  operation: op,
@@ -1403,7 +1510,7 @@ var Client = class {
1403
1510
  key: this.createOperationKey(),
1404
1511
  metadata: {
1405
1512
  ...options?.metadata,
1406
- fragmentRef
1513
+ fragment: { ref: fragmentRef }
1407
1514
  },
1408
1515
  artifact,
1409
1516
  variables: {}
package/dist/index.d.cts CHANGED
@@ -68,8 +68,8 @@ type QueryOptions<T extends Artifact$1<'query'> = Artifact$1<'query'>> = {
68
68
  initialData?: DataOf$1<T>;
69
69
  metadata?: OperationMetadata;
70
70
  };
71
- type MutationOptions = {
72
- metadata?: OperationMetadata;
71
+ type MutationOptions<T extends Artifact$1<'mutation'> = Artifact$1<'mutation'>> = {
72
+ metadata?: OperationMetadata<T>;
73
73
  };
74
74
  type SubscriptionOptions = {
75
75
  metadata?: OperationMetadata;
@@ -93,31 +93,31 @@ declare class Client<TMeta extends SchemaMeta$1 = SchemaMeta$1> {
93
93
  get schema(): TMeta;
94
94
  get scalars(): ScalarsConfig<TMeta> | undefined;
95
95
  private createOperationKey;
96
- createOperation(artifact: Artifact$1, variables?: unknown, metadata?: OperationMetadata): Operation;
96
+ createOperation(artifact: Artifact$1, variables?: unknown, metadata?: Record<string, unknown>): Operation;
97
97
  executeOperation(operation: Operation): Source<OperationResult>;
98
98
  executeQuery<T extends Artifact$1<'query'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, QueryOptions<T>?] : [VariablesOf$1<T>, QueryOptions<T>?]): Source<OperationResult>;
99
- executeMutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions?] : [VariablesOf$1<T>, MutationOptions?]): Source<OperationResult>;
99
+ executeMutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions<T>?] : [VariablesOf$1<T>, MutationOptions<T>?]): Source<OperationResult>;
100
100
  executeSubscription<T extends Artifact$1<'subscription'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, SubscriptionOptions?] : [VariablesOf$1<T>, SubscriptionOptions?]): Source<OperationResult>;
101
101
  executeFragment<T extends Artifact$1<'fragment'>>(artifact: T, fragmentRef: FragmentRefs$1<T['name']> | FragmentRefs$1<T['name']>[], options?: FragmentOptions): Source<OperationResult>;
102
102
  query<T extends Artifact$1<'query'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, QueryOptions<T>?] : [VariablesOf$1<T>, QueryOptions<T>?]): Promise<DataOf$1<T>>;
103
- mutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions?] : [VariablesOf$1<T>, MutationOptions?]): Promise<DataOf$1<T>>;
103
+ mutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions<T>?] : [VariablesOf$1<T>, MutationOptions<T>?]): Promise<DataOf$1<T>>;
104
104
  /**
105
105
  * Returns the extension registered by a named exchange.
106
106
  * @param name - The exchange name.
107
107
  * @returns The extension object provided by the exchange.
108
108
  */
109
- extension<TName extends keyof ExchangeExtensionMap>(name: TName): ExchangeExtensionMap[TName];
109
+ extension<TName extends keyof ExchangeExtensionMap<TMeta>>(name: TName): ExchangeExtensionMap<TMeta>[TName];
110
110
  extension(name: string): unknown;
111
- maybeExtension<TName extends keyof ExchangeExtensionMap>(name: TName): ExchangeExtensionMap[TName] | undefined;
111
+ maybeExtension<TName extends keyof ExchangeExtensionMap<TMeta>>(name: TName): ExchangeExtensionMap<TMeta>[TName] | undefined;
112
112
  maybeExtension(name: string): unknown;
113
113
  dispose(): void;
114
114
  }
115
115
  declare const createClient: <T extends SchemaMeta$1>(config: ClientOptions<T>) => Client<T>;
116
116
  //#endregion
117
117
  //#region src/exchange.d.ts
118
- interface OperationMetadataMap {}
118
+ interface OperationMetadataMap<T extends Artifact$1 = Artifact$1> {}
119
119
  interface OperationResultMetadataMap {}
120
- type OperationMetadata = { [K in keyof OperationMetadataMap]?: OperationMetadataMap[K] } & Record<string, unknown>;
120
+ type OperationMetadata<T extends Artifact$1 = Artifact$1> = { [K in keyof OperationMetadataMap<T>]?: OperationMetadataMap<T>[K] } & Record<string, unknown>;
121
121
  type BaseOperation = {
122
122
  key: string;
123
123
  metadata: OperationMetadataMap & Record<string, unknown>;
@@ -143,14 +143,14 @@ type ExchangeInput<TMeta extends SchemaMeta$1 = SchemaMeta$1> = {
143
143
  client: Client<TMeta>;
144
144
  };
145
145
  type ExchangeIO = (operations: Source<Operation>) => Source<OperationResult>;
146
- interface ExchangeExtensionMap {}
147
- type ExchangeResult<TName extends keyof ExchangeExtensionMap | (string & {}) = string> = {
146
+ interface ExchangeExtensionMap<TMeta extends SchemaMeta$1 = SchemaMeta$1> {}
147
+ type ExchangeResult<TName extends keyof ExchangeExtensionMap | (string & {}) = string, TMeta extends SchemaMeta$1 = SchemaMeta$1> = {
148
148
  name: TName;
149
149
  io: ExchangeIO;
150
- } & (TName extends keyof ExchangeExtensionMap ? {
151
- extension: ExchangeExtensionMap[TName];
150
+ } & (TName extends keyof ExchangeExtensionMap<TMeta> ? {
151
+ extension: ExchangeExtensionMap<TMeta>[TName];
152
152
  } : {});
153
- type Exchange<TName extends keyof ExchangeExtensionMap | (string & {}) = string> = <TMeta extends SchemaMeta$1 = SchemaMeta$1>(input: ExchangeInput<TMeta>) => ExchangeResult<TName>;
153
+ type Exchange<TName extends keyof ExchangeExtensionMap | (string & {}) = string> = <TMeta extends SchemaMeta$1 = SchemaMeta$1>(input: ExchangeInput<TMeta>) => ExchangeResult<TName, TMeta>;
154
154
  //#endregion
155
155
  //#region src/exchanges/http.d.ts
156
156
  declare module '@mearie/core' {
@@ -195,34 +195,38 @@ declare module '@mearie/core' {
195
195
  declare const dedupExchange: () => Exchange;
196
196
  //#endregion
197
197
  //#region src/cache/types.d.ts
198
- /**
199
- * Identifier for a single entity, supporting simple or composite keys.
200
- */
201
- type EntityId = string | number | Record<string, string | number>;
202
- /**
203
- * Target specification for cache invalidation operations.
204
- */
205
- type InvalidateTarget = {
206
- __typename: string;
207
- id: EntityId;
208
- } | {
209
- __typename: string;
210
- id: EntityId;
211
- field: string;
212
- args?: Record<string, unknown>;
213
- } | {
198
+ type EntityTypes<TMeta extends SchemaMeta$1> = NonNullable<TMeta[' $entityTypes']>;
199
+ type QueryFields<TMeta extends SchemaMeta$1> = NonNullable<TMeta[' $queryFields']>;
200
+ type KeyFieldsOf<E> = E extends {
201
+ keyFields: infer KF;
202
+ } ? KF : Record<string, unknown>;
203
+ type FieldsOf<E> = E extends {
204
+ fields: infer F extends string;
205
+ } ? F : string;
206
+ type EntityInvalidateTarget<Entities> = { [K in keyof Entities & string]: {
207
+ __typename: K;
208
+ } | ({
209
+ __typename: K;
210
+ } & KeyFieldsOf<Entities[K]>) | {
211
+ __typename: K;
212
+ $field: FieldsOf<Entities[K]>;
213
+ $args?: Record<string, unknown>;
214
+ } | ({
215
+ __typename: K;
216
+ $field: FieldsOf<Entities[K]>;
217
+ $args?: Record<string, unknown>;
218
+ } & KeyFieldsOf<Entities[K]>) }[keyof Entities & string];
219
+ type QueryInvalidateTarget<QF extends string> = {
214
220
  __typename: 'Query';
215
221
  } | {
216
222
  __typename: 'Query';
217
- field: string;
218
- args?: Record<string, unknown>;
219
- } | {
220
- __typename: string;
221
- } | {
222
- __typename: string;
223
- field: string;
224
- args?: Record<string, unknown>;
223
+ $field: QF;
224
+ $args?: Record<string, unknown>;
225
225
  };
226
+ /**
227
+ * Target specification for cache invalidation operations.
228
+ */
229
+ type InvalidateTarget<TMeta extends SchemaMeta$1 = SchemaMeta$1> = EntityInvalidateTarget<EntityTypes<TMeta>> | QueryInvalidateTarget<QueryFields<TMeta>>;
226
230
  /**
227
231
  * Opaque type representing a serializable cache snapshot.
228
232
  */
@@ -232,17 +236,22 @@ type CacheSnapshot = {
232
236
  /**
233
237
  * Operations available for programmatic cache manipulation.
234
238
  */
235
- type CacheOperations = {
239
+ type CacheOperations<TMeta extends SchemaMeta$1 = SchemaMeta$1> = {
236
240
  extract(): CacheSnapshot;
237
241
  hydrate(data: CacheSnapshot): void;
238
- invalidate(...targets: InvalidateTarget[]): void;
242
+ invalidate(...targets: InvalidateTarget<TMeta>[]): void;
239
243
  clear(): void;
240
244
  };
241
245
  //#endregion
242
246
  //#region src/exchanges/cache.d.ts
243
247
  declare module '@mearie/core' {
244
- interface ExchangeExtensionMap {
245
- cache: CacheOperations;
248
+ interface ExchangeExtensionMap<TMeta extends SchemaMeta$1> {
249
+ cache: CacheOperations<TMeta>;
250
+ }
251
+ interface OperationMetadataMap<T extends Artifact$1> {
252
+ cache?: {
253
+ optimisticResponse?: T extends Artifact$1<'mutation'> ? DataOf$1<T> : never;
254
+ };
246
255
  }
247
256
  interface OperationResultMetadataMap {
248
257
  cache?: {
@@ -274,7 +283,9 @@ declare const retryExchange: (options?: RetryOptions) => Exchange;
274
283
  //#region src/exchanges/fragment.d.ts
275
284
  declare module '@mearie/core' {
276
285
  interface OperationMetadataMap {
277
- fragmentRef?: unknown;
286
+ fragment?: {
287
+ ref?: unknown;
288
+ };
278
289
  }
279
290
  }
280
291
  declare const fragmentExchange: () => Exchange;
@@ -351,4 +362,4 @@ declare class RequiredFieldError extends Error {
351
362
  */
352
363
  declare const stringify: (value: unknown) => string;
353
364
  //#endregion
354
- export { AggregatedError, type Artifact, type ArtifactKind, type CacheOptions, type CacheSnapshot, Client, type ClientOptions, type DataOf, type Exchange, ExchangeError, type ExchangeErrorExtensionsMap, type ExchangeExtensionMap, type ExchangeIO, type ExchangeResult, type FragmentOptions, type FragmentRefs, GraphQLError, type HttpOptions, type MutationOptions, type Operation, type OperationError, type OperationMetadata, type OperationMetadataMap, type OperationResult, type OperationResultMetadataMap, type QueryOptions, type RequiredAction, RequiredFieldError, type RetryOptions, type SchemaMeta, type SubscriptionClient, type SubscriptionExchangeOptions, type SubscriptionOptions, type VariablesOf, cacheExchange, createClient, dedupExchange, fragmentExchange, httpExchange, isAggregatedError, isExchangeError, isGraphQLError, requiredExchange, retryExchange, stringify, subscriptionExchange };
365
+ export { AggregatedError, type Artifact, type ArtifactKind, type CacheOperations, type CacheOptions, type CacheSnapshot, Client, type ClientOptions, type DataOf, type Exchange, ExchangeError, type ExchangeErrorExtensionsMap, type ExchangeExtensionMap, type ExchangeIO, type ExchangeResult, type FragmentOptions, type FragmentRefs, GraphQLError, type HttpOptions, type InvalidateTarget, type MutationOptions, type Operation, type OperationError, type OperationMetadata, type OperationMetadataMap, type OperationResult, type OperationResultMetadataMap, type QueryOptions, type RequiredAction, RequiredFieldError, type RetryOptions, type SchemaMeta, type SubscriptionClient, type SubscriptionExchangeOptions, type SubscriptionOptions, type VariablesOf, cacheExchange, createClient, dedupExchange, fragmentExchange, httpExchange, isAggregatedError, isExchangeError, isGraphQLError, requiredExchange, retryExchange, stringify, subscriptionExchange };
package/dist/index.d.mts CHANGED
@@ -68,8 +68,8 @@ type QueryOptions<T extends Artifact$1<'query'> = Artifact$1<'query'>> = {
68
68
  initialData?: DataOf$1<T>;
69
69
  metadata?: OperationMetadata;
70
70
  };
71
- type MutationOptions = {
72
- metadata?: OperationMetadata;
71
+ type MutationOptions<T extends Artifact$1<'mutation'> = Artifact$1<'mutation'>> = {
72
+ metadata?: OperationMetadata<T>;
73
73
  };
74
74
  type SubscriptionOptions = {
75
75
  metadata?: OperationMetadata;
@@ -93,31 +93,31 @@ declare class Client<TMeta extends SchemaMeta$1 = SchemaMeta$1> {
93
93
  get schema(): TMeta;
94
94
  get scalars(): ScalarsConfig<TMeta> | undefined;
95
95
  private createOperationKey;
96
- createOperation(artifact: Artifact$1, variables?: unknown, metadata?: OperationMetadata): Operation;
96
+ createOperation(artifact: Artifact$1, variables?: unknown, metadata?: Record<string, unknown>): Operation;
97
97
  executeOperation(operation: Operation): Source<OperationResult>;
98
98
  executeQuery<T extends Artifact$1<'query'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, QueryOptions<T>?] : [VariablesOf$1<T>, QueryOptions<T>?]): Source<OperationResult>;
99
- executeMutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions?] : [VariablesOf$1<T>, MutationOptions?]): Source<OperationResult>;
99
+ executeMutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions<T>?] : [VariablesOf$1<T>, MutationOptions<T>?]): Source<OperationResult>;
100
100
  executeSubscription<T extends Artifact$1<'subscription'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, SubscriptionOptions?] : [VariablesOf$1<T>, SubscriptionOptions?]): Source<OperationResult>;
101
101
  executeFragment<T extends Artifact$1<'fragment'>>(artifact: T, fragmentRef: FragmentRefs$1<T['name']> | FragmentRefs$1<T['name']>[], options?: FragmentOptions): Source<OperationResult>;
102
102
  query<T extends Artifact$1<'query'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, QueryOptions<T>?] : [VariablesOf$1<T>, QueryOptions<T>?]): Promise<DataOf$1<T>>;
103
- mutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions?] : [VariablesOf$1<T>, MutationOptions?]): Promise<DataOf$1<T>>;
103
+ mutation<T extends Artifact$1<'mutation'>>(artifact: T, ...[variables, options]: VariablesOf$1<T> extends undefined ? [undefined?, MutationOptions<T>?] : [VariablesOf$1<T>, MutationOptions<T>?]): Promise<DataOf$1<T>>;
104
104
  /**
105
105
  * Returns the extension registered by a named exchange.
106
106
  * @param name - The exchange name.
107
107
  * @returns The extension object provided by the exchange.
108
108
  */
109
- extension<TName extends keyof ExchangeExtensionMap>(name: TName): ExchangeExtensionMap[TName];
109
+ extension<TName extends keyof ExchangeExtensionMap<TMeta>>(name: TName): ExchangeExtensionMap<TMeta>[TName];
110
110
  extension(name: string): unknown;
111
- maybeExtension<TName extends keyof ExchangeExtensionMap>(name: TName): ExchangeExtensionMap[TName] | undefined;
111
+ maybeExtension<TName extends keyof ExchangeExtensionMap<TMeta>>(name: TName): ExchangeExtensionMap<TMeta>[TName] | undefined;
112
112
  maybeExtension(name: string): unknown;
113
113
  dispose(): void;
114
114
  }
115
115
  declare const createClient: <T extends SchemaMeta$1>(config: ClientOptions<T>) => Client<T>;
116
116
  //#endregion
117
117
  //#region src/exchange.d.ts
118
- interface OperationMetadataMap {}
118
+ interface OperationMetadataMap<T extends Artifact$1 = Artifact$1> {}
119
119
  interface OperationResultMetadataMap {}
120
- type OperationMetadata = { [K in keyof OperationMetadataMap]?: OperationMetadataMap[K] } & Record<string, unknown>;
120
+ type OperationMetadata<T extends Artifact$1 = Artifact$1> = { [K in keyof OperationMetadataMap<T>]?: OperationMetadataMap<T>[K] } & Record<string, unknown>;
121
121
  type BaseOperation = {
122
122
  key: string;
123
123
  metadata: OperationMetadataMap & Record<string, unknown>;
@@ -143,14 +143,14 @@ type ExchangeInput<TMeta extends SchemaMeta$1 = SchemaMeta$1> = {
143
143
  client: Client<TMeta>;
144
144
  };
145
145
  type ExchangeIO = (operations: Source<Operation>) => Source<OperationResult>;
146
- interface ExchangeExtensionMap {}
147
- type ExchangeResult<TName extends keyof ExchangeExtensionMap | (string & {}) = string> = {
146
+ interface ExchangeExtensionMap<TMeta extends SchemaMeta$1 = SchemaMeta$1> {}
147
+ type ExchangeResult<TName extends keyof ExchangeExtensionMap | (string & {}) = string, TMeta extends SchemaMeta$1 = SchemaMeta$1> = {
148
148
  name: TName;
149
149
  io: ExchangeIO;
150
- } & (TName extends keyof ExchangeExtensionMap ? {
151
- extension: ExchangeExtensionMap[TName];
150
+ } & (TName extends keyof ExchangeExtensionMap<TMeta> ? {
151
+ extension: ExchangeExtensionMap<TMeta>[TName];
152
152
  } : {});
153
- type Exchange<TName extends keyof ExchangeExtensionMap | (string & {}) = string> = <TMeta extends SchemaMeta$1 = SchemaMeta$1>(input: ExchangeInput<TMeta>) => ExchangeResult<TName>;
153
+ type Exchange<TName extends keyof ExchangeExtensionMap | (string & {}) = string> = <TMeta extends SchemaMeta$1 = SchemaMeta$1>(input: ExchangeInput<TMeta>) => ExchangeResult<TName, TMeta>;
154
154
  //#endregion
155
155
  //#region src/exchanges/http.d.ts
156
156
  declare module '@mearie/core' {
@@ -195,34 +195,38 @@ declare module '@mearie/core' {
195
195
  declare const dedupExchange: () => Exchange;
196
196
  //#endregion
197
197
  //#region src/cache/types.d.ts
198
- /**
199
- * Identifier for a single entity, supporting simple or composite keys.
200
- */
201
- type EntityId = string | number | Record<string, string | number>;
202
- /**
203
- * Target specification for cache invalidation operations.
204
- */
205
- type InvalidateTarget = {
206
- __typename: string;
207
- id: EntityId;
208
- } | {
209
- __typename: string;
210
- id: EntityId;
211
- field: string;
212
- args?: Record<string, unknown>;
213
- } | {
198
+ type EntityTypes<TMeta extends SchemaMeta$1> = NonNullable<TMeta[' $entityTypes']>;
199
+ type QueryFields<TMeta extends SchemaMeta$1> = NonNullable<TMeta[' $queryFields']>;
200
+ type KeyFieldsOf<E> = E extends {
201
+ keyFields: infer KF;
202
+ } ? KF : Record<string, unknown>;
203
+ type FieldsOf<E> = E extends {
204
+ fields: infer F extends string;
205
+ } ? F : string;
206
+ type EntityInvalidateTarget<Entities> = { [K in keyof Entities & string]: {
207
+ __typename: K;
208
+ } | ({
209
+ __typename: K;
210
+ } & KeyFieldsOf<Entities[K]>) | {
211
+ __typename: K;
212
+ $field: FieldsOf<Entities[K]>;
213
+ $args?: Record<string, unknown>;
214
+ } | ({
215
+ __typename: K;
216
+ $field: FieldsOf<Entities[K]>;
217
+ $args?: Record<string, unknown>;
218
+ } & KeyFieldsOf<Entities[K]>) }[keyof Entities & string];
219
+ type QueryInvalidateTarget<QF extends string> = {
214
220
  __typename: 'Query';
215
221
  } | {
216
222
  __typename: 'Query';
217
- field: string;
218
- args?: Record<string, unknown>;
219
- } | {
220
- __typename: string;
221
- } | {
222
- __typename: string;
223
- field: string;
224
- args?: Record<string, unknown>;
223
+ $field: QF;
224
+ $args?: Record<string, unknown>;
225
225
  };
226
+ /**
227
+ * Target specification for cache invalidation operations.
228
+ */
229
+ type InvalidateTarget<TMeta extends SchemaMeta$1 = SchemaMeta$1> = EntityInvalidateTarget<EntityTypes<TMeta>> | QueryInvalidateTarget<QueryFields<TMeta>>;
226
230
  /**
227
231
  * Opaque type representing a serializable cache snapshot.
228
232
  */
@@ -232,17 +236,22 @@ type CacheSnapshot = {
232
236
  /**
233
237
  * Operations available for programmatic cache manipulation.
234
238
  */
235
- type CacheOperations = {
239
+ type CacheOperations<TMeta extends SchemaMeta$1 = SchemaMeta$1> = {
236
240
  extract(): CacheSnapshot;
237
241
  hydrate(data: CacheSnapshot): void;
238
- invalidate(...targets: InvalidateTarget[]): void;
242
+ invalidate(...targets: InvalidateTarget<TMeta>[]): void;
239
243
  clear(): void;
240
244
  };
241
245
  //#endregion
242
246
  //#region src/exchanges/cache.d.ts
243
247
  declare module '@mearie/core' {
244
- interface ExchangeExtensionMap {
245
- cache: CacheOperations;
248
+ interface ExchangeExtensionMap<TMeta extends SchemaMeta$1> {
249
+ cache: CacheOperations<TMeta>;
250
+ }
251
+ interface OperationMetadataMap<T extends Artifact$1> {
252
+ cache?: {
253
+ optimisticResponse?: T extends Artifact$1<'mutation'> ? DataOf$1<T> : never;
254
+ };
246
255
  }
247
256
  interface OperationResultMetadataMap {
248
257
  cache?: {
@@ -274,7 +283,9 @@ declare const retryExchange: (options?: RetryOptions) => Exchange;
274
283
  //#region src/exchanges/fragment.d.ts
275
284
  declare module '@mearie/core' {
276
285
  interface OperationMetadataMap {
277
- fragmentRef?: unknown;
286
+ fragment?: {
287
+ ref?: unknown;
288
+ };
278
289
  }
279
290
  }
280
291
  declare const fragmentExchange: () => Exchange;
@@ -351,4 +362,4 @@ declare class RequiredFieldError extends Error {
351
362
  */
352
363
  declare const stringify: (value: unknown) => string;
353
364
  //#endregion
354
- export { AggregatedError, type Artifact, type ArtifactKind, type CacheOptions, type CacheSnapshot, Client, type ClientOptions, type DataOf, type Exchange, ExchangeError, type ExchangeErrorExtensionsMap, type ExchangeExtensionMap, type ExchangeIO, type ExchangeResult, type FragmentOptions, type FragmentRefs, GraphQLError, type HttpOptions, type MutationOptions, type Operation, type OperationError, type OperationMetadata, type OperationMetadataMap, type OperationResult, type OperationResultMetadataMap, type QueryOptions, type RequiredAction, RequiredFieldError, type RetryOptions, type SchemaMeta, type SubscriptionClient, type SubscriptionExchangeOptions, type SubscriptionOptions, type VariablesOf, cacheExchange, createClient, dedupExchange, fragmentExchange, httpExchange, isAggregatedError, isExchangeError, isGraphQLError, requiredExchange, retryExchange, stringify, subscriptionExchange };
365
+ export { AggregatedError, type Artifact, type ArtifactKind, type CacheOperations, type CacheOptions, type CacheSnapshot, Client, type ClientOptions, type DataOf, type Exchange, ExchangeError, type ExchangeErrorExtensionsMap, type ExchangeExtensionMap, type ExchangeIO, type ExchangeResult, type FragmentOptions, type FragmentRefs, GraphQLError, type HttpOptions, type InvalidateTarget, type MutationOptions, type Operation, type OperationError, type OperationMetadata, type OperationMetadataMap, type OperationResult, type OperationResultMetadataMap, type QueryOptions, type RequiredAction, RequiredFieldError, type RetryOptions, type SchemaMeta, type SubscriptionClient, type SubscriptionExchangeOptions, type SubscriptionOptions, type VariablesOf, cacheExchange, createClient, dedupExchange, fragmentExchange, httpExchange, isAggregatedError, isExchangeError, isGraphQLError, requiredExchange, retryExchange, stringify, subscriptionExchange };
package/dist/index.mjs CHANGED
@@ -317,6 +317,12 @@ const RootFieldKey = "__root";
317
317
  * @internal
318
318
  */
319
319
  const FragmentRefKey = "__fragmentRef";
320
+ /**
321
+ * Special key used to carry merged variable context (fragment args + operation variables)
322
+ * on fragment references. Used by readFragment to resolve variable-dependent field keys.
323
+ * @internal
324
+ */
325
+ const FragmentVarsKey = "__fragmentVars";
320
326
 
321
327
  //#endregion
322
328
  //#region src/cache/utils.ts
@@ -390,6 +396,14 @@ const isFragmentRef = (value) => {
390
396
  return typeof value === "object" && value !== null && FragmentRefKey in value;
391
397
  };
392
398
  /**
399
+ * Extracts the merged variable context for a specific fragment from a fragment reference.
400
+ * Returns the merged variables (fragment args + operation variables) if present, or an empty object.
401
+ * @internal
402
+ */
403
+ const getFragmentVars = (fragmentRef, fragmentName) => {
404
+ return fragmentRef[FragmentVarsKey]?.[fragmentName] ?? {};
405
+ };
406
+ /**
393
407
  * Type guard to check if a value is an array of fragment references.
394
408
  * @internal
395
409
  * @param value - Value to check.
@@ -500,33 +514,20 @@ const mergeFields = (target, source) => {
500
514
  const makeFieldKeyFromArgs = (field, args) => {
501
515
  return `${field}@${args && Object.keys(args).length > 0 ? stringify(args) : "{}"}`;
502
516
  };
503
- /**
504
- * Converts an EntityId to an EntityKey.
505
- * @internal
506
- * @param typename - The GraphQL typename of the entity.
507
- * @param id - The entity identifier (string, number, or composite key record).
508
- * @param keyFields - Optional ordered list of key field names for composite keys.
509
- * @returns An EntityKey.
510
- */
511
- const resolveEntityKey = (typename, id, keyFields) => {
512
- if (typeof id === "string" || typeof id === "number") return makeEntityKey(typename, [id]);
513
- return makeEntityKey(typename, keyFields ? keyFields.map((f) => id[f]) : Object.values(id));
514
- };
515
517
 
516
518
  //#endregion
517
519
  //#region src/cache/normalize.ts
518
- const SKIP = Symbol();
519
520
  const normalize = (schemaMeta, selections, storage, data, variables, accessor) => {
520
521
  const normalizeField = (storageKey, selections, value) => {
521
522
  if (isNullish(value)) return value;
522
523
  if (Array.isArray(value)) return value.map((item) => normalizeField(storageKey, selections, item));
523
524
  const data = value;
524
525
  const typename = data.__typename;
525
- const entityMeta = schemaMeta.entities[typename];
526
+ let entityMeta = schemaMeta.entities[typename];
526
527
  if (entityMeta) {
527
528
  const keys = entityMeta.keyFields.map((field) => data[field]);
528
- if (!keys.every((k) => k !== void 0 && k !== null)) return SKIP;
529
- storageKey = makeEntityKey(typename, keys);
529
+ if (keys.every((k) => k !== void 0 && k !== null)) storageKey = makeEntityKey(typename, keys);
530
+ else entityMeta = void 0;
530
531
  }
531
532
  const fields = {};
532
533
  for (const selection of selections) if (selection.kind === "Field") {
@@ -534,13 +535,11 @@ const normalize = (schemaMeta, selections, storage, data, variables, accessor) =
534
535
  const fieldValue = data[selection.alias ?? selection.name];
535
536
  const oldValue = storageKey === null ? void 0 : storage[storageKey]?.[fieldKey];
536
537
  if (storageKey !== null && (!selection.selections || isNullish(oldValue) || isNullish(fieldValue))) accessor?.(storageKey, fieldKey, oldValue, fieldValue);
537
- const normalized = selection.selections ? normalizeField(null, selection.selections, fieldValue) : fieldValue;
538
- if (normalized === SKIP) continue;
539
- fields[fieldKey] = normalized;
538
+ fields[fieldKey] = selection.selections ? normalizeField(null, selection.selections, fieldValue) : fieldValue;
540
539
  if (storageKey !== null && selection.selections && !isNullish(oldValue) && !isNullish(fieldValue) && !isEntityLink(fields[fieldKey]) && !isEqual(oldValue, fields[fieldKey])) accessor?.(storageKey, fieldKey, oldValue, fields[fieldKey]);
541
540
  } else if (selection.kind === "FragmentSpread" || selection.kind === "InlineFragment" && selection.on === typename) {
542
541
  const inner = normalizeField(storageKey, selection.selections, value);
543
- if (inner !== SKIP && !isEntityLink(inner)) mergeFields(fields, inner);
542
+ if (!isEntityLink(inner)) mergeFields(fields, inner);
544
543
  }
545
544
  if (entityMeta && storageKey !== null) {
546
545
  const existing = storage[storageKey];
@@ -595,6 +594,17 @@ const denormalize = (selections, storage, value, variables, accessor) => {
595
594
  else fields[name] = value;
596
595
  } else if (selection.kind === "FragmentSpread") if (storageKey !== null && storageKey !== RootFieldKey) {
597
596
  fields[FragmentRefKey] = storageKey;
597
+ if (selection.args) {
598
+ const resolvedArgs = resolveArguments(selection.args, variables);
599
+ const mergedVars = {
600
+ ...variables,
601
+ ...resolvedArgs
602
+ };
603
+ fields[FragmentVarsKey] = {
604
+ ...fields[FragmentVarsKey],
605
+ [selection.name]: mergedVars
606
+ };
607
+ }
598
608
  if (accessor) denormalize(selection.selections, storage, { [EntityLinkKey]: storageKey }, variables, accessor);
599
609
  } else mergeFields(fields, denormalizeField(storageKey, selection.selections, value));
600
610
  else if (selection.kind === "InlineFragment" && selection.on === data[typenameFieldKey]) mergeFields(fields, denormalizeField(storageKey, selection.selections, value));
@@ -618,9 +628,74 @@ var Cache = class {
618
628
  #subscriptions = /* @__PURE__ */ new Map();
619
629
  #memo = /* @__PURE__ */ new Map();
620
630
  #stale = /* @__PURE__ */ new Set();
631
+ #optimisticKeys = [];
632
+ #optimisticLayers = /* @__PURE__ */ new Map();
633
+ #storageView = null;
621
634
  constructor(schemaMetadata) {
622
635
  this.#schemaMeta = schemaMetadata;
623
636
  }
637
+ #getStorageView() {
638
+ if (this.#optimisticKeys.length === 0) return this.#storage;
639
+ if (this.#storageView) return this.#storageView;
640
+ const merged = { ...this.#storage };
641
+ for (const storageKey of Object.keys(this.#storage)) merged[storageKey] = { ...this.#storage[storageKey] };
642
+ for (const key of this.#optimisticKeys) {
643
+ const layer = this.#optimisticLayers.get(key);
644
+ if (!layer) continue;
645
+ for (const storageKey of Object.keys(layer.storage)) merged[storageKey] = merged[storageKey] ? {
646
+ ...merged[storageKey],
647
+ ...layer.storage[storageKey]
648
+ } : { ...layer.storage[storageKey] };
649
+ }
650
+ this.#storageView = merged;
651
+ return merged;
652
+ }
653
+ /**
654
+ * Writes an optimistic response to a separate cache layer.
655
+ * The optimistic data is immediately visible in reads but does not affect the base storage.
656
+ * @internal
657
+ * @param key - Unique key identifying this optimistic mutation (typically the operation key).
658
+ * @param artifact - GraphQL document artifact.
659
+ * @param variables - Operation variables.
660
+ * @param data - The optimistic response data.
661
+ */
662
+ writeOptimistic(key, artifact, variables, data) {
663
+ const layerStorage = { [RootFieldKey]: {} };
664
+ const dependencies = /* @__PURE__ */ new Set();
665
+ normalize(this.#schemaMeta, artifact.selections, layerStorage, data, variables, (storageKey, fieldKey) => {
666
+ dependencies.add(makeDependencyKey(storageKey, fieldKey));
667
+ });
668
+ this.#optimisticKeys.push(key);
669
+ this.#optimisticLayers.set(key, {
670
+ storage: layerStorage,
671
+ dependencies
672
+ });
673
+ this.#storageView = null;
674
+ const subscriptions = /* @__PURE__ */ new Set();
675
+ for (const depKey of dependencies) {
676
+ const ss = this.#subscriptions.get(depKey);
677
+ if (ss) for (const s of ss) subscriptions.add(s);
678
+ }
679
+ for (const subscription of subscriptions) subscription.listener();
680
+ }
681
+ /**
682
+ * Removes an optimistic layer and notifies affected subscribers.
683
+ * @internal
684
+ * @param key - The key of the optimistic layer to remove.
685
+ */
686
+ removeOptimistic(key) {
687
+ const layer = this.#optimisticLayers.get(key);
688
+ if (!layer) return;
689
+ this.#optimisticLayers.delete(key);
690
+ this.#optimisticKeys = this.#optimisticKeys.filter((k) => k !== key);
691
+ this.#storageView = null;
692
+ const subscriptions = /* @__PURE__ */ new Set();
693
+ for (const depKey of layer.dependencies) {
694
+ const ss = this.#subscriptions.get(depKey);
695
+ if (ss) for (const s of ss) subscriptions.add(s);
696
+ }
697
+ for (const subscription of subscriptions) subscription.listener();
698
+ }
624
699
  /**
625
700
  * Writes a query result to the cache, normalizing entities.
626
701
  * @param artifact - GraphQL document artifact.
@@ -653,7 +728,8 @@ var Cache = class {
653
728
  */
654
729
  readQuery(artifact, variables) {
655
730
  let stale = false;
656
- const { data, partial } = denormalize(artifact.selections, this.#storage, this.#storage[RootFieldKey], variables, (storageKey, fieldKey) => {
731
+ const storage = this.#getStorageView();
732
+ const { data, partial } = denormalize(artifact.selections, storage, storage[RootFieldKey], variables, (storageKey, fieldKey) => {
657
733
  if (this.#stale.has(storageKey) || this.#stale.has(makeDependencyKey(storageKey, fieldKey))) stale = true;
658
734
  });
659
735
  if (partial) return {
@@ -678,7 +754,8 @@ var Cache = class {
678
754
  */
679
755
  subscribeQuery(artifact, variables, listener) {
680
756
  const dependencies = /* @__PURE__ */ new Set();
681
- denormalize(artifact.selections, this.#storage, this.#storage[RootFieldKey], variables, (storageKey, fieldKey) => {
757
+ const storageView = this.#getStorageView();
758
+ denormalize(artifact.selections, storageView, storageView[RootFieldKey], variables, (storageKey, fieldKey) => {
682
759
  const dependencyKey = makeDependencyKey(storageKey, fieldKey);
683
760
  dependencies.add(dependencyKey);
684
761
  });
@@ -693,19 +770,22 @@ var Cache = class {
693
770
  */
694
771
  readFragment(artifact, fragmentRef) {
695
772
  const entityKey = fragmentRef[FragmentRefKey];
696
- if (!this.#storage[entityKey]) return {
773
+ const fragmentVars = getFragmentVars(fragmentRef, artifact.name);
774
+ const storageView = this.#getStorageView();
775
+ if (!storageView[entityKey]) return {
697
776
  data: null,
698
777
  stale: false
699
778
  };
700
779
  let stale = false;
701
- const { data, partial } = denormalize(artifact.selections, this.#storage, { [EntityLinkKey]: entityKey }, {}, (storageKey, fieldKey) => {
780
+ const { data, partial } = denormalize(artifact.selections, storageView, { [EntityLinkKey]: entityKey }, fragmentVars, (storageKey, fieldKey) => {
702
781
  if (this.#stale.has(storageKey) || this.#stale.has(makeDependencyKey(storageKey, fieldKey))) stale = true;
703
782
  });
704
783
  if (partial) return {
705
784
  data: null,
706
785
  stale: false
707
786
  };
708
- const key = makeMemoKey("fragment", artifact.name, entityKey);
787
+ const argsId = Object.keys(fragmentVars).length > 0 ? entityKey + stringify(fragmentVars) : entityKey;
788
+ const key = makeMemoKey("fragment", artifact.name, argsId);
709
789
  const prev = this.#memo.get(key);
710
790
  const result = prev === void 0 ? data : replaceEqualDeep(prev, data);
711
791
  this.#memo.set(key, result);
@@ -716,8 +796,10 @@ var Cache = class {
716
796
  }
717
797
  subscribeFragment(artifact, fragmentRef, listener) {
718
798
  const entityKey = fragmentRef[FragmentRefKey];
799
+ const fragmentVars = getFragmentVars(fragmentRef, artifact.name);
719
800
  const dependencies = /* @__PURE__ */ new Set();
720
- denormalize(artifact.selections, this.#storage, { [EntityLinkKey]: entityKey }, {}, (storageKey, fieldKey) => {
801
+ const storageView = this.#getStorageView();
802
+ denormalize(artifact.selections, storageView, { [EntityLinkKey]: entityKey }, fragmentVars, (storageKey, fieldKey) => {
721
803
  const dependencyKey = makeDependencyKey(storageKey, fieldKey);
722
804
  dependencies.add(dependencyKey);
723
805
  });
@@ -747,9 +829,11 @@ var Cache = class {
747
829
  }
748
830
  subscribeFragments(artifact, fragmentRefs, listener) {
749
831
  const dependencies = /* @__PURE__ */ new Set();
832
+ const storageView = this.#getStorageView();
750
833
  for (const ref of fragmentRefs) {
751
834
  const entityKey = ref[FragmentRefKey];
752
- denormalize(artifact.selections, this.#storage, { [EntityLinkKey]: entityKey }, {}, (storageKey, fieldKey) => {
835
+ const fragmentVars = getFragmentVars(ref, artifact.name);
836
+ denormalize(artifact.selections, storageView, { [EntityLinkKey]: entityKey }, fragmentVars, (storageKey, fieldKey) => {
753
837
  dependencies.add(makeDependencyKey(storageKey, fieldKey));
754
838
  });
755
839
  }
@@ -761,8 +845,8 @@ var Cache = class {
761
845
  */
762
846
  invalidate(...targets) {
763
847
  const subscriptions = /* @__PURE__ */ new Set();
764
- for (const target of targets) if (target.__typename === "Query") if ("field" in target) {
765
- const fieldKey = makeFieldKeyFromArgs(target.field, target.args);
848
+ for (const target of targets) if (target.__typename === "Query") if ("$field" in target) {
849
+ const fieldKey = makeFieldKeyFromArgs(target.$field, target.$args);
766
850
  const depKey = makeDependencyKey(RootFieldKey, fieldKey);
767
851
  this.#stale.add(depKey);
768
852
  this.#collectSubscriptions(RootFieldKey, fieldKey, subscriptions);
@@ -770,32 +854,39 @@ var Cache = class {
770
854
  this.#stale.add(RootFieldKey);
771
855
  this.#collectSubscriptions(RootFieldKey, void 0, subscriptions);
772
856
  }
773
- else if ("id" in target) {
774
- const entityKey = resolveEntityKey(target.__typename, target.id, this.#schemaMeta.entities[target.__typename]?.keyFields);
775
- if ("field" in target) {
776
- const fieldKey = makeFieldKeyFromArgs(target.field, target.args);
777
- this.#stale.add(makeDependencyKey(entityKey, fieldKey));
778
- this.#collectSubscriptions(entityKey, fieldKey, subscriptions);
779
- } else {
780
- this.#stale.add(entityKey);
781
- this.#collectSubscriptions(entityKey, void 0, subscriptions);
782
- }
783
- } else {
784
- const prefix = `${target.__typename}:`;
785
- for (const key of Object.keys(this.#storage)) if (key.startsWith(prefix)) {
786
- const entityKey = key;
787
- if ("field" in target) {
788
- const fieldKey = makeFieldKeyFromArgs(target.field, target.args);
857
+ else {
858
+ const keyFields = this.#schemaMeta.entities[target.__typename]?.keyFields;
859
+ if (keyFields && this.#hasKeyFields(target, keyFields)) {
860
+ const keyValues = keyFields.map((f) => target[f]);
861
+ const entityKey = makeEntityKey(target.__typename, keyValues);
862
+ if ("$field" in target) {
863
+ const fieldKey = makeFieldKeyFromArgs(target.$field, target.$args);
789
864
  this.#stale.add(makeDependencyKey(entityKey, fieldKey));
790
865
  this.#collectSubscriptions(entityKey, fieldKey, subscriptions);
791
866
  } else {
792
867
  this.#stale.add(entityKey);
793
868
  this.#collectSubscriptions(entityKey, void 0, subscriptions);
794
869
  }
870
+ } else {
871
+ const prefix = `${target.__typename}:`;
872
+ for (const key of Object.keys(this.#storage)) if (key.startsWith(prefix)) {
873
+ const entityKey = key;
874
+ if ("$field" in target) {
875
+ const fieldKey = makeFieldKeyFromArgs(target.$field, target.$args);
876
+ this.#stale.add(makeDependencyKey(entityKey, fieldKey));
877
+ this.#collectSubscriptions(entityKey, fieldKey, subscriptions);
878
+ } else {
879
+ this.#stale.add(entityKey);
880
+ this.#collectSubscriptions(entityKey, void 0, subscriptions);
881
+ }
882
+ }
795
883
  }
796
884
  }
797
885
  for (const subscription of subscriptions) subscription.listener();
798
886
  }
887
+ #hasKeyFields(target, keyFields) {
888
+ return keyFields.every((f) => f in target);
889
+ }
799
890
  #collectSubscriptions(storageKey, fieldKey, out) {
800
891
  if (fieldKey === void 0) {
801
892
  const prefix = `${storageKey}.`;
@@ -823,6 +914,7 @@ var Cache = class {
823
914
  }
824
915
  /**
825
916
  * Extracts a serializable snapshot of the cache storage and structural sharing state.
917
+ * Optimistic layers are excluded because they represent transient in-flight state.
826
918
  */
827
919
  extract() {
828
920
  return {
@@ -840,6 +932,7 @@ var Cache = class {
840
932
  ...fields
841
933
  };
842
934
  for (const [key, value] of Object.entries(memo)) this.#memo.set(key, value);
935
+ this.#storageView = null;
843
936
  }
844
937
  /**
845
938
  * Clears all cache data.
@@ -849,6 +942,9 @@ var Cache = class {
849
942
  this.#subscriptions.clear();
850
943
  this.#memo.clear();
851
944
  this.#stale.clear();
945
+ this.#optimisticKeys = [];
946
+ this.#optimisticLayers.clear();
947
+ this.#storageView = null;
852
948
  }
853
949
  };
854
950
 
@@ -881,10 +977,10 @@ const cacheExchange = (options = {}) => {
881
977
  },
882
978
  io: (ops$) => {
883
979
  const fragment$ = pipe(ops$, filter((op) => op.variant === "request" && op.artifact.kind === "fragment"), mergeMap((op) => {
884
- const fragmentRef = op.metadata?.fragmentRef;
980
+ const fragmentRef = op.metadata?.fragment?.ref;
885
981
  if (!fragmentRef) return fromValue({
886
982
  operation: op,
887
- errors: [new ExchangeError("Fragment operation missing fragmentRef in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "cache" })]
983
+ errors: [new ExchangeError("Fragment operation missing fragment.ref in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "cache" })]
888
984
  });
889
985
  if (isFragmentRefArray(fragmentRef)) {
890
986
  const trigger = makeSubject();
@@ -916,7 +1012,9 @@ const cacheExchange = (options = {}) => {
916
1012
  errors: []
917
1013
  })));
918
1014
  }));
919
- const nonCache$ = pipe(ops$, filter((op) => op.variant === "request" && (op.artifact.kind === "mutation" || op.artifact.kind === "subscription" || op.artifact.kind === "query" && fetchPolicy === "network-only")));
1015
+ const nonCache$ = pipe(ops$, filter((op) => op.variant === "request" && (op.artifact.kind === "mutation" || op.artifact.kind === "subscription" || op.artifact.kind === "query" && fetchPolicy === "network-only")), tap((op) => {
1016
+ if (op.artifact.kind === "mutation" && op.metadata?.cache?.optimisticResponse) cache.writeOptimistic(op.key, op.artifact, op.variables, op.metadata.cache.optimisticResponse);
1017
+ }));
920
1018
  const query$ = pipe(ops$, filter((op) => op.variant === "request" && op.artifact.kind === "query" && fetchPolicy !== "network-only"), share());
921
1019
  const refetch$ = makeSubject();
922
1020
  return merge(fragment$, pipe(query$, mergeMap((op) => {
@@ -959,9 +1057,18 @@ const cacheExchange = (options = {}) => {
959
1057
  }), filter(() => fetchPolicy === "cache-only" || fetchPolicy === "cache-and-network" || fetchPolicy === "cache-first")), pipe(merge(nonCache$, pipe(query$, filter((op) => {
960
1058
  const { data } = cache.readQuery(op.artifact, op.variables);
961
1059
  return fetchPolicy === "cache-and-network" || data === null;
962
- })), pipe(ops$, filter((op) => op.variant === "teardown")), refetch$.source), forward, tap((result) => {
1060
+ })), pipe(ops$, filter((op) => op.variant === "teardown")), refetch$.source), forward, mergeMap((result) => {
1061
+ if (result.operation.variant === "request" && result.operation.artifact.kind === "mutation" && result.operation.metadata?.cache?.optimisticResponse) cache.removeOptimistic(result.operation.key);
963
1062
  if (result.operation.variant === "request" && result.data) cache.writeQuery(result.operation.artifact, result.operation.variables, result.data);
964
- }), filter((result) => result.operation.variant !== "request" || result.operation.artifact.kind !== "query" || fetchPolicy === "network-only" || !!(result.errors && result.errors.length > 0))));
1063
+ if (result.operation.variant !== "request" || result.operation.artifact.kind !== "query" || fetchPolicy === "network-only" || !!(result.errors && result.errors.length > 0)) return fromValue(result);
1064
+ const { data } = cache.readQuery(result.operation.artifact, result.operation.variables);
1065
+ if (data !== null) return empty();
1066
+ return fromValue({
1067
+ operation: result.operation,
1068
+ data: void 0,
1069
+ errors: [new ExchangeError("Cache failed to denormalize the network response. This is likely a bug in the cache normalizer.", { exchangeName: "cache" })]
1070
+ });
1071
+ })));
965
1072
  }
966
1073
  };
967
1074
  };
@@ -1013,10 +1120,10 @@ const fragmentExchange = () => {
1013
1120
  name: "fragment",
1014
1121
  io: (ops$) => {
1015
1122
  return merge(pipe(ops$, filter((op) => op.variant === "request" && op.artifact.kind === "fragment"), map((op) => {
1016
- const fragmentRef = op.metadata.fragmentRef;
1123
+ const fragmentRef = op.metadata.fragment?.ref;
1017
1124
  if (!fragmentRef) return {
1018
1125
  operation: op,
1019
- errors: [new ExchangeError("Fragment operation missing fragmentRef in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "fragment" })]
1126
+ errors: [new ExchangeError("Fragment operation missing fragment.ref in metadata. This usually happens when the wrong fragment reference was passed.", { exchangeName: "fragment" })]
1020
1127
  };
1021
1128
  return {
1022
1129
  operation: op,
@@ -1402,7 +1509,7 @@ var Client = class {
1402
1509
  key: this.createOperationKey(),
1403
1510
  metadata: {
1404
1511
  ...options?.metadata,
1405
- fragmentRef
1512
+ fragment: { ref: fragmentRef }
1406
1513
  },
1407
1514
  artifact,
1408
1515
  variables: {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mearie/core",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Type-safe, zero-overhead GraphQL client",
5
5
  "keywords": [
6
6
  "graphql",
@@ -62,7 +62,7 @@
62
62
  "README.md"
63
63
  ],
64
64
  "dependencies": {
65
- "@mearie/shared": "0.2.2"
65
+ "@mearie/shared": "0.4.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "tsdown": "^0.20.3",