@isograph/react 0.5.2 → 0.5.4

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 (254) hide show
  1. package/.turbo/turbo-compile-libs.log +9 -6
  2. package/.turbo/turbo-tsc.log +5 -0
  3. package/dist/_virtual/{rolldown_runtime.js → rolldown_runtime.cjs} +10 -6
  4. package/dist/core/{FragmentReference.js → FragmentReference.cjs} +1 -1
  5. package/dist/core/{FragmentReference.d.ts → FragmentReference.d.cts} +5 -5
  6. package/dist/core/FragmentReference.d.cts.map +1 -0
  7. package/dist/core/FragmentReference.d.mts.map +1 -1
  8. package/dist/core/{IsographEnvironment.js → IsographEnvironment.cjs} +19 -9
  9. package/dist/core/{IsographEnvironment.d.ts → IsographEnvironment.d.cts} +19 -15
  10. package/dist/core/IsographEnvironment.d.cts.map +1 -0
  11. package/dist/core/IsographEnvironment.d.mts +9 -5
  12. package/dist/core/IsographEnvironment.d.mts.map +1 -1
  13. package/dist/core/IsographEnvironment.mjs +17 -7
  14. package/dist/core/IsographEnvironment.mjs.map +1 -1
  15. package/dist/core/{PromiseWrapper.d.ts → PromiseWrapper.d.cts} +1 -1
  16. package/dist/core/PromiseWrapper.d.cts.map +1 -0
  17. package/dist/core/PromiseWrapper.d.mts.map +1 -1
  18. package/dist/core/PromiseWrapper.mjs.map +1 -1
  19. package/dist/core/{areEqualWithDeepComparison.js → areEqualWithDeepComparison.cjs} +7 -7
  20. package/dist/core/areEqualWithDeepComparison.mjs +7 -7
  21. package/dist/core/areEqualWithDeepComparison.mjs.map +1 -1
  22. package/dist/core/{brand.d.ts → brand.d.cts} +2 -2
  23. package/dist/core/brand.d.cts.map +1 -0
  24. package/dist/core/brand.d.mts +1 -1
  25. package/dist/core/brand.d.mts.map +1 -1
  26. package/dist/core/{cache.js → cache.cjs} +16 -29
  27. package/dist/core/cache.d.cts +44 -0
  28. package/dist/core/cache.d.cts.map +1 -0
  29. package/dist/core/cache.d.mts +29 -4
  30. package/dist/core/cache.d.mts.map +1 -1
  31. package/dist/core/cache.mjs +9 -21
  32. package/dist/core/cache.mjs.map +1 -1
  33. package/dist/core/{check.js → check.cjs} +4 -4
  34. package/dist/core/{check.d.ts → check.d.cts} +4 -4
  35. package/dist/core/check.d.cts.map +1 -0
  36. package/dist/core/check.d.mts.map +1 -1
  37. package/dist/core/check.mjs.map +1 -1
  38. package/dist/core/{componentCache.js → componentCache.cjs} +2 -2
  39. package/dist/core/{entrypoint.d.ts → entrypoint.d.cts} +16 -9
  40. package/dist/core/entrypoint.d.cts.map +1 -0
  41. package/dist/core/entrypoint.d.mts +9 -2
  42. package/dist/core/entrypoint.d.mts.map +1 -1
  43. package/dist/core/entrypoint.mjs.map +1 -1
  44. package/dist/core/{garbageCollection.js → garbageCollection.cjs} +3 -3
  45. package/dist/core/{garbageCollection.d.ts → garbageCollection.d.cts} +4 -4
  46. package/dist/core/garbageCollection.d.cts.map +1 -0
  47. package/dist/core/garbageCollection.d.mts.map +1 -1
  48. package/dist/core/garbageCollection.mjs.map +1 -1
  49. package/dist/core/{getOrCreateCacheForArtifact.js → getOrCreateCacheForArtifact.cjs} +4 -4
  50. package/dist/core/getOrCreateCacheForArtifact.mjs.map +1 -1
  51. package/dist/core/{logging.d.ts → logging.d.cts} +9 -10
  52. package/dist/core/logging.d.cts.map +1 -0
  53. package/dist/core/logging.d.mts +0 -1
  54. package/dist/core/logging.d.mts.map +1 -1
  55. package/dist/core/{makeNetworkRequest.js → makeNetworkRequest.cjs} +21 -21
  56. package/dist/core/{makeNetworkRequest.d.ts → makeNetworkRequest.d.cts} +7 -7
  57. package/dist/core/makeNetworkRequest.d.cts.map +1 -0
  58. package/dist/core/makeNetworkRequest.d.mts.map +1 -1
  59. package/dist/core/makeNetworkRequest.mjs +10 -10
  60. package/dist/core/makeNetworkRequest.mjs.map +1 -1
  61. package/dist/core/{optimisticProxy.js → optimisticProxy.cjs} +2 -2
  62. package/dist/core/{optimisticProxy.d.ts → optimisticProxy.d.cts} +2 -3
  63. package/dist/core/optimisticProxy.d.cts.map +1 -0
  64. package/dist/core/optimisticProxy.d.mts +0 -1
  65. package/dist/core/optimisticProxy.d.mts.map +1 -1
  66. package/dist/core/optimisticProxy.mjs.map +1 -1
  67. package/dist/core/{read.js → read.cjs} +66 -63
  68. package/dist/core/{read.d.ts → read.d.cts} +4 -5
  69. package/dist/core/read.d.cts.map +1 -0
  70. package/dist/core/read.d.mts.map +1 -1
  71. package/dist/core/read.mjs +58 -55
  72. package/dist/core/read.mjs.map +1 -1
  73. package/dist/core/{reader.d.ts → reader.d.cts} +11 -9
  74. package/dist/core/reader.d.cts.map +1 -0
  75. package/dist/core/reader.d.mts +5 -3
  76. package/dist/core/reader.d.mts.map +1 -1
  77. package/dist/core/{startUpdate.js → startUpdate.cjs} +14 -14
  78. package/dist/core/startUpdate.mjs +6 -6
  79. package/dist/core/startUpdate.mjs.map +1 -1
  80. package/dist/core/{subscribe.js → subscribe.cjs} +3 -3
  81. package/dist/core/{subscribe.d.ts → subscribe.d.cts} +6 -6
  82. package/dist/core/subscribe.d.cts.map +1 -0
  83. package/dist/core/subscribe.d.mts.map +1 -1
  84. package/dist/core/subscribe.mjs.map +1 -1
  85. package/dist/core/{util.d.ts → util.d.cts} +1 -1
  86. package/dist/core/util.d.cts.map +1 -0
  87. package/dist/core/util.d.mts.map +1 -1
  88. package/dist/core/util.mjs.map +1 -1
  89. package/dist/core/{writeData.js → writeData.cjs} +6 -6
  90. package/dist/core/{writeData.d.ts → writeData.d.cts} +6 -6
  91. package/dist/core/writeData.d.cts.map +1 -0
  92. package/dist/core/writeData.d.mts +1 -1
  93. package/dist/core/writeData.d.mts.map +1 -1
  94. package/dist/core/writeData.mjs.map +1 -1
  95. package/dist/{index.js → index.cjs} +29 -29
  96. package/dist/index.d.cts +32 -0
  97. package/dist/index.d.mts +2 -2
  98. package/dist/loadable-hooks/useClientSideDefer.cjs +14 -0
  99. package/dist/loadable-hooks/{useClientSideDefer.d.ts → useClientSideDefer.d.cts} +4 -4
  100. package/dist/loadable-hooks/useClientSideDefer.d.cts.map +1 -0
  101. package/dist/loadable-hooks/useClientSideDefer.d.mts.map +1 -1
  102. package/dist/loadable-hooks/{useConnectionSpecPagination.js → useConnectionSpecPagination.cjs} +13 -16
  103. package/dist/loadable-hooks/{useConnectionSpecPagination.d.ts → useConnectionSpecPagination.d.cts} +4 -4
  104. package/dist/loadable-hooks/useConnectionSpecPagination.d.cts.map +1 -0
  105. package/dist/loadable-hooks/useConnectionSpecPagination.d.mts.map +1 -1
  106. package/dist/loadable-hooks/useConnectionSpecPagination.mjs.map +1 -1
  107. package/dist/loadable-hooks/{useImperativeExposedMutationField.d.ts → useImperativeExposedMutationField.d.cts} +1 -1
  108. package/dist/loadable-hooks/useImperativeExposedMutationField.d.cts.map +1 -0
  109. package/dist/loadable-hooks/useImperativeExposedMutationField.d.mts.map +1 -1
  110. package/dist/loadable-hooks/{useImperativeLoadableField.js → useImperativeLoadableField.cjs} +4 -5
  111. package/dist/loadable-hooks/{useImperativeLoadableField.d.ts → useImperativeLoadableField.d.cts} +4 -4
  112. package/dist/loadable-hooks/useImperativeLoadableField.d.cts.map +1 -0
  113. package/dist/loadable-hooks/useImperativeLoadableField.d.mts.map +1 -1
  114. package/dist/loadable-hooks/{useSkipLimitPagination.js → useSkipLimitPagination.cjs} +13 -16
  115. package/dist/loadable-hooks/{useSkipLimitPagination.d.ts → useSkipLimitPagination.d.cts} +4 -4
  116. package/dist/loadable-hooks/useSkipLimitPagination.d.cts.map +1 -0
  117. package/dist/loadable-hooks/useSkipLimitPagination.d.mts.map +1 -1
  118. package/dist/loadable-hooks/useSkipLimitPagination.mjs.map +1 -1
  119. package/dist/react/{FragmentReader.js → FragmentReader.cjs} +1 -1
  120. package/dist/react/{FragmentReader.d.ts → FragmentReader.d.cts} +5 -5
  121. package/dist/react/FragmentReader.d.cts.map +1 -0
  122. package/dist/react/FragmentReader.d.mts.map +1 -1
  123. package/dist/react/{FragmentRenderer.js → FragmentRenderer.cjs} +2 -2
  124. package/dist/react/{FragmentRenderer.d.ts → FragmentRenderer.d.cts} +5 -5
  125. package/dist/react/FragmentRenderer.d.cts.map +1 -0
  126. package/dist/react/FragmentRenderer.d.mts.map +1 -1
  127. package/dist/react/{IsographEnvironmentProvider.js → IsographEnvironmentProvider.cjs} +1 -1
  128. package/dist/react/{IsographEnvironmentProvider.d.ts → IsographEnvironmentProvider.d.cts} +2 -2
  129. package/dist/react/IsographEnvironmentProvider.d.cts.map +1 -0
  130. package/dist/react/IsographEnvironmentProvider.d.mts.map +1 -1
  131. package/dist/react/{LoadableFieldReader.js → LoadableFieldReader.cjs} +3 -3
  132. package/dist/react/{LoadableFieldReader.d.ts → LoadableFieldReader.d.cts} +5 -5
  133. package/dist/react/LoadableFieldReader.d.cts.map +1 -0
  134. package/dist/react/LoadableFieldReader.d.mts.map +1 -1
  135. package/dist/react/{LoadableFieldRenderer.js → LoadableFieldRenderer.cjs} +3 -3
  136. package/dist/react/{LoadableFieldRenderer.d.ts → LoadableFieldRenderer.d.cts} +5 -5
  137. package/dist/react/LoadableFieldRenderer.d.cts.map +1 -0
  138. package/dist/react/LoadableFieldRenderer.d.mts.map +1 -1
  139. package/dist/react/{RenderAfterCommit__DO_NOT_USE.js → RenderAfterCommit__DO_NOT_USE.cjs} +1 -2
  140. package/dist/react/{RenderAfterCommit__DO_NOT_USE.d.ts → RenderAfterCommit__DO_NOT_USE.d.cts} +1 -2
  141. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.cts.map +1 -0
  142. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.mts +0 -1
  143. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.mts.map +1 -1
  144. package/dist/react/{createIsographEnvironment.js → createIsographEnvironment.cjs} +2 -2
  145. package/dist/react/{createIsographEnvironment.d.ts → createIsographEnvironment.d.cts} +3 -3
  146. package/dist/react/createIsographEnvironment.d.cts.map +1 -0
  147. package/dist/react/createIsographEnvironment.d.mts +0 -1
  148. package/dist/react/createIsographEnvironment.d.mts.map +1 -1
  149. package/dist/react/{maybeUnwrapNetworkRequest.js → maybeUnwrapNetworkRequest.cjs} +1 -1
  150. package/dist/react/{useImperativeReference.js → useImperativeReference.cjs} +7 -8
  151. package/dist/react/{useImperativeReference.d.ts → useImperativeReference.d.cts} +5 -6
  152. package/dist/react/useImperativeReference.d.cts.map +1 -0
  153. package/dist/react/useImperativeReference.d.mts +0 -1
  154. package/dist/react/useImperativeReference.d.mts.map +1 -1
  155. package/dist/react/useLazyReference.cjs +18 -0
  156. package/dist/react/{useLazyReference.d.ts → useLazyReference.d.cts} +5 -6
  157. package/dist/react/useLazyReference.d.cts.map +1 -0
  158. package/dist/react/useLazyReference.d.mts +0 -1
  159. package/dist/react/useLazyReference.d.mts.map +1 -1
  160. package/dist/react/{useReadAndSubscribe.js → useReadAndSubscribe.cjs} +9 -10
  161. package/dist/react/{useReadAndSubscribe.d.ts → useReadAndSubscribe.d.cts} +4 -5
  162. package/dist/react/useReadAndSubscribe.d.cts.map +1 -0
  163. package/dist/react/useReadAndSubscribe.d.mts +0 -1
  164. package/dist/react/useReadAndSubscribe.d.mts.map +1 -1
  165. package/dist/react/useReadAndSubscribe.mjs.map +1 -1
  166. package/dist/react/{useRerenderOnChange.js → useRerenderOnChange.cjs} +3 -4
  167. package/dist/react/{useRerenderOnChange.d.ts → useRerenderOnChange.d.cts} +4 -4
  168. package/dist/react/useRerenderOnChange.d.cts.map +1 -0
  169. package/dist/react/useRerenderOnChange.d.mts.map +1 -1
  170. package/dist/react/{useResult.js → useResult.cjs} +7 -7
  171. package/dist/react/{useResult.d.ts → useResult.d.cts} +3 -3
  172. package/dist/react/useResult.d.cts.map +1 -0
  173. package/dist/react/useResult.d.mts.map +1 -1
  174. package/package.json +9 -9
  175. package/src/core/IsographEnvironment.ts +47 -22
  176. package/src/core/cache.ts +76 -55
  177. package/src/core/entrypoint.ts +18 -2
  178. package/src/core/getOrCreateCacheForArtifact.ts +2 -2
  179. package/src/core/makeNetworkRequest.ts +10 -12
  180. package/src/core/read.ts +21 -19
  181. package/src/core/reader.ts +9 -5
  182. package/src/core/writeData.ts +4 -4
  183. package/src/index.ts +2 -1
  184. package/src/tests/__isograph/Economist/__link/output_type.ts +2 -1
  185. package/src/tests/__isograph/Node/asEconomist/resolver_reader.ts +4 -3
  186. package/src/tests/__isograph/Query/linkedUpdate/normalization_ast.ts +12 -0
  187. package/src/tests/__isograph/Query/linkedUpdate/resolver_reader.ts +9 -3
  188. package/src/tests/__isograph/Query/meName/normalization_ast.ts +3 -0
  189. package/src/tests/__isograph/Query/meName/resolver_reader.ts +5 -3
  190. package/src/tests/__isograph/Query/meNameSuccessor/normalization_ast.ts +8 -0
  191. package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +8 -3
  192. package/src/tests/__isograph/Query/nodeField/normalization_ast.ts +3 -0
  193. package/src/tests/__isograph/Query/nodeField/raw_response_type.ts +1 -1
  194. package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +5 -3
  195. package/src/tests/__isograph/Query/normalizeUndefinedField/normalization_ast.ts +3 -0
  196. package/src/tests/__isograph/Query/normalizeUndefinedField/resolver_reader.ts +5 -3
  197. package/src/tests/__isograph/Query/startUpdate/normalization_ast.ts +6 -0
  198. package/src/tests/__isograph/Query/startUpdate/resolver_reader.ts +6 -3
  199. package/src/tests/__isograph/Query/subquery/normalization_ast.ts +4 -0
  200. package/src/tests/__isograph/Query/subquery/raw_response_type.ts +1 -1
  201. package/src/tests/__isograph/Query/subquery/resolver_reader.ts +6 -3
  202. package/src/tests/garbageCollection.test.ts +11 -11
  203. package/src/tests/normalizeData.test.ts +11 -3
  204. package/src/tests/optimisticProxy.test.ts +23 -23
  205. package/src/tests/startUpdate.test.ts +2 -2
  206. package/tsconfig.json +5 -4
  207. package/tsconfig.package.json +8 -0
  208. package/tsconfig.test.json +12 -0
  209. package/tsdown.config.ts +8 -0
  210. package/vitest.config.ts +1 -1
  211. package/dist/core/FragmentReference.d.ts.map +0 -1
  212. package/dist/core/IsographEnvironment.d.ts.map +0 -1
  213. package/dist/core/PromiseWrapper.d.ts.map +0 -1
  214. package/dist/core/brand.d.ts.map +0 -1
  215. package/dist/core/cache.d.ts +0 -20
  216. package/dist/core/cache.d.ts.map +0 -1
  217. package/dist/core/check.d.ts.map +0 -1
  218. package/dist/core/entrypoint.d.ts.map +0 -1
  219. package/dist/core/garbageCollection.d.ts.map +0 -1
  220. package/dist/core/logging.d.ts.map +0 -1
  221. package/dist/core/makeNetworkRequest.d.ts.map +0 -1
  222. package/dist/core/optimisticProxy.d.ts.map +0 -1
  223. package/dist/core/read.d.ts.map +0 -1
  224. package/dist/core/reader.d.ts.map +0 -1
  225. package/dist/core/subscribe.d.ts.map +0 -1
  226. package/dist/core/util.d.ts.map +0 -1
  227. package/dist/core/writeData.d.ts.map +0 -1
  228. package/dist/index.d.ts +0 -32
  229. package/dist/loadable-hooks/useClientSideDefer.d.ts.map +0 -1
  230. package/dist/loadable-hooks/useClientSideDefer.js +0 -15
  231. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +0 -1
  232. package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +0 -1
  233. package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +0 -1
  234. package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +0 -1
  235. package/dist/react/FragmentReader.d.ts.map +0 -1
  236. package/dist/react/FragmentRenderer.d.ts.map +0 -1
  237. package/dist/react/IsographEnvironmentProvider.d.ts.map +0 -1
  238. package/dist/react/LoadableFieldReader.d.ts.map +0 -1
  239. package/dist/react/LoadableFieldRenderer.d.ts.map +0 -1
  240. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts.map +0 -1
  241. package/dist/react/createIsographEnvironment.d.ts.map +0 -1
  242. package/dist/react/useImperativeReference.d.ts.map +0 -1
  243. package/dist/react/useLazyReference.d.ts.map +0 -1
  244. package/dist/react/useLazyReference.js +0 -19
  245. package/dist/react/useReadAndSubscribe.d.ts.map +0 -1
  246. package/dist/react/useRerenderOnChange.d.ts.map +0 -1
  247. package/dist/react/useResult.d.ts.map +0 -1
  248. package/src/tests/tsconfig.json +0 -21
  249. package/tsconfig.pkg.json +0 -16
  250. /package/dist/core/{PromiseWrapper.js → PromiseWrapper.cjs} +0 -0
  251. /package/dist/core/{entrypoint.js → entrypoint.cjs} +0 -0
  252. /package/dist/core/{logging.js → logging.cjs} +0 -0
  253. /package/dist/core/{util.js → util.cjs} +0 -0
  254. /package/dist/loadable-hooks/{useImperativeExposedMutationField.js → useImperativeExposedMutationField.cjs} +0 -0
package/src/core/cache.ts CHANGED
@@ -13,7 +13,7 @@ import type {
13
13
  } from './FragmentReference';
14
14
  import {
15
15
  type DataId,
16
- type DataTypeValue,
16
+ type DataTypeValueLinked,
17
17
  getLink,
18
18
  type IsographEnvironment,
19
19
  ROOT_ID,
@@ -46,18 +46,30 @@ export function getOrCreateItemInSuspenseCache<
46
46
  return environment.fragmentCache[index];
47
47
  }
48
48
 
49
- export type NetworkResponseScalarValue = string | number | boolean;
50
- export type NetworkResponseValue =
51
- | NetworkResponseScalarValue
49
+ export type NetworkResponsePlural<T> =
52
50
  | null
53
- | NetworkResponseObject
54
- | readonly (NetworkResponseObject | null)[]
55
- | readonly (NetworkResponseScalarValue | null)[];
51
+ | T
52
+ | readonly T[]
53
+ | readonly (null | T)[];
54
+ export type NetworkResponseScalarValue = string | number | boolean | unknown;
55
+
56
+ export type NetworkResponseValue =
57
+ | NetworkResponsePlural<NetworkResponseScalarValue>
58
+ | NetworkResponsePlural<NetworkResponseObject>;
56
59
 
57
60
  export type NetworkResponseObject = {
58
61
  // N.B. undefined is here to support optional id's, but
59
62
  // undefined should not *actually* be present in the network response.
60
- readonly [index: string]: undefined | NetworkResponseValue;
63
+ readonly [key: ScalarNetworkResponseKey]:
64
+ | undefined
65
+ | NetworkResponsePlural<NetworkResponseScalarValue>;
66
+ readonly [key: LinkedNetworkResponseKey]:
67
+ | undefined
68
+ | NetworkResponsePlural<NetworkResponseObject>;
69
+ readonly [key: NetworkResponseKey]:
70
+ | undefined
71
+ | NetworkResponsePlural<NetworkResponseScalarValue>
72
+ | NetworkResponsePlural<NetworkResponseObject>;
61
73
  readonly id?: DataId;
62
74
  readonly __typename?: TypeName;
63
75
  };
@@ -233,12 +245,8 @@ function normalizeScalarField(
233
245
  return existingValue === undefined || existingValue != null;
234
246
  }
235
247
 
236
- if (isScalarOrEmptyArray(networkResponseData)) {
237
- targetStoreRecord[parentRecordKey] = networkResponseData;
238
- return existingValue !== networkResponseData;
239
- } else {
240
- throw new Error('Unexpected object array when normalizing scalar');
241
- }
248
+ targetStoreRecord[parentRecordKey] = networkResponseData;
249
+ return existingValue !== networkResponseData;
242
250
  }
243
251
 
244
252
  /**
@@ -264,15 +272,6 @@ function normalizeLinkedField(
264
272
  return existingValue === undefined || existingValue != null;
265
273
  }
266
274
 
267
- if (
268
- isScalarOrEmptyArray(networkResponseData) &&
269
- !isNullOrEmptyArray(networkResponseData)
270
- ) {
271
- throw new Error(
272
- 'Unexpected scalar network response when normalizing a linked field',
273
- );
274
- }
275
-
276
275
  if (isArray(networkResponseData)) {
277
276
  // TODO check astNode.plural or the like
278
277
  const dataIds: (StoreLink | null)[] = [];
@@ -371,7 +370,7 @@ function normalizeInlineFragment(
371
370
  }
372
371
 
373
372
  function dataIdsAreTheSame(
374
- existingValue: DataTypeValue,
373
+ existingValue: DataTypeValueLinked,
375
374
  newDataIds: (StoreLink | null)[],
376
375
  ): boolean {
377
376
  if (isArray(existingValue)) {
@@ -437,36 +436,29 @@ function normalizeNetworkResponseObject(
437
436
  return newStoreRecordId;
438
437
  }
439
438
 
440
- function isScalarOrEmptyArray(
441
- data: NetworkResponseValue,
442
- ): data is
443
- | NetworkResponseScalarValue
444
- | readonly (NetworkResponseScalarValue | null)[] {
445
- // N.B. empty arrays count as empty arrays of scalar fields.
446
- if (isArray(data)) {
447
- return data.every((x) => isScalarOrEmptyArray(x));
448
- }
449
- const isScalarValue =
450
- data == null ||
451
- typeof data === 'string' ||
452
- typeof data === 'number' ||
453
- typeof data === 'boolean';
454
- return isScalarValue;
455
- }
456
-
457
- function isNullOrEmptyArray(
458
- data: unknown,
459
- ): data is readonly never[] | null[] | null {
460
- if (isArray(data)) {
461
- if (data.length === 0) {
462
- return true;
463
- }
464
- return data.every((x) => isNullOrEmptyArray(x));
465
- }
439
+ export type ParentRecordKey = string;
466
440
 
467
- return data == null;
468
- }
441
+ /**
442
+ * these don't actually start with the different prefixes, but they let
443
+ * us use multiple indexes, e.g.
444
+ * {
445
+ * readonly [key: `NOT_AN_ACTUAL_TYPE_LinkedParentRecordKey_${string} `]: ...
446
+ * readonly [key: `NOT_AN_ACTUAL_TYPE_ScalarParentRecordKey_${string} `]: ...
447
+ * }
448
+ */
449
+ export type LinkedParentRecordKey =
450
+ `NOT_AN_ACTUAL_TYPE_LinkedParentRecordKey_${string}`;
451
+ export type ScalarParentRecordKey =
452
+ `NOT_AN_ACTUAL_TYPE_ScalarParentRecordKey_${string}`;
469
453
 
454
+ export function getParentRecordKey(
455
+ astNode: NormalizationLinkedField | ReaderLinkedField,
456
+ variables: Variables,
457
+ ): LinkedParentRecordKey;
458
+ export function getParentRecordKey(
459
+ astNode: NormalizationScalarField | ReaderScalarField,
460
+ variables: Variables,
461
+ ): ScalarParentRecordKey;
470
462
  export function getParentRecordKey(
471
463
  astNode:
472
464
  | NormalizationLinkedField
@@ -474,7 +466,7 @@ export function getParentRecordKey(
474
466
  | ReaderLinkedField
475
467
  | ReaderScalarField,
476
468
  variables: Variables,
477
- ): string {
469
+ ): ParentRecordKey {
478
470
  let parentRecordKey = astNode.fieldName;
479
471
  const fieldParameters = astNode.arguments;
480
472
  if (fieldParameters != null) {
@@ -528,9 +520,30 @@ function getStoreKeyChunkForArgument(argument: Argument, variables: Variables) {
528
520
  return `${FIRST_SPLIT_KEY}${argumentName}${SECOND_SPLIT_KEY}${chunk}`;
529
521
  }
530
522
 
523
+ export type NetworkResponseKey = string;
524
+
525
+ /**
526
+ * these don't actually start with the different prefixes, but they let
527
+ * us use multiple indexes, e.g.
528
+ * {
529
+ * readonly [key: `NOT_AN_ACTUAL_TYPE_LinkedNetworkResponseKey_${string} `]: ...
530
+ * readonly [key: `NOT_AN_ACTUAL_TYPE_ScalarNetworkResponseKey_${string} `]: ...
531
+ * }
532
+ */
533
+ export type LinkedNetworkResponseKey =
534
+ `NOT_AN_ACTUAL_TYPE_LinkedNetworkResponseKey_${string}`;
535
+ export type ScalarNetworkResponseKey =
536
+ `NOT_AN_ACTUAL_TYPE_ScalarNetworkResponseKey_${string}`;
537
+
538
+ function getNetworkResponseKey(
539
+ astNode: NormalizationLinkedField,
540
+ ): LinkedNetworkResponseKey;
541
+ function getNetworkResponseKey(
542
+ astNode: NormalizationScalarField,
543
+ ): ScalarNetworkResponseKey;
531
544
  function getNetworkResponseKey(
532
545
  astNode: NormalizationLinkedField | NormalizationScalarField,
533
- ): string {
546
+ ): NetworkResponseKey {
534
547
  let networkResponseKey = astNode.fieldName;
535
548
  const fieldParameters = astNode.arguments;
536
549
 
@@ -590,9 +603,17 @@ function getDataIdOfNetworkResponse(
590
603
  variables: Variables,
591
604
  index: number | null,
592
605
  ): DataId {
606
+ const __typename =
607
+ astNode.concreteType ?? dataToNormalize[TYPENAME_FIELD_NAME];
608
+ if (__typename == null) {
609
+ throw new Error(
610
+ 'Unexpected missing __typename in network response when normalizing a linked field. ' +
611
+ 'This is indicative of a bug in Isograph.',
612
+ );
613
+ }
593
614
  // If we are dealing with nested Query, use __ROOT as id
594
615
  // TODO do not hard code this value here
595
- if (astNode.concreteType === 'Query') {
616
+ if (__typename === 'Query') {
596
617
  return ROOT_ID;
597
618
  }
598
619
 
@@ -22,6 +22,20 @@ export type ReaderWithRefetchQueries<
22
22
  readonly nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[];
23
23
  };
24
24
 
25
+ export type RawReaderWithRefetchQueries<
26
+ TReadFromStore extends UnknownTReadFromStore,
27
+ TClientFieldValue,
28
+ > = {
29
+ readonly kind: 'ReaderWithRefetchQueries';
30
+ readonly readerArtifact: () => TopLevelReaderArtifact<
31
+ TReadFromStore,
32
+ TClientFieldValue,
33
+ // TODO don't type this as any
34
+ any
35
+ >;
36
+ readonly nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[];
37
+ };
38
+
25
39
  export type ReaderWithRefetchQueriesLoader<
26
40
  TReadFromStore extends UnknownTReadFromStore,
27
41
  TClientFieldValue,
@@ -32,7 +46,7 @@ export type ReaderWithRefetchQueriesLoader<
32
46
  | 'EagerReaderArtifact'
33
47
  | 'ComponentReaderArtifact';
34
48
  readonly loader: () => Promise<
35
- ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>
49
+ RawReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>
36
50
  >;
37
51
  };
38
52
 
@@ -69,7 +83,7 @@ export type IsographEntrypoint<
69
83
  readonly kind: 'Entrypoint';
70
84
  readonly networkRequestInfo: NetworkRequestInfo<TNormalizationAst>;
71
85
  readonly readerWithRefetchQueries:
72
- | ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>
86
+ | RawReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>
73
87
  | ReaderWithRefetchQueriesLoader<TReadFromStore, TClientFieldValue>;
74
88
  readonly concreteType: TypeName;
75
89
  /**
@@ -124,12 +138,14 @@ export type NormalizationAstLoader = {
124
138
 
125
139
  export type NormalizationScalarField = {
126
140
  readonly kind: 'Scalar';
141
+ readonly isFallible: boolean;
127
142
  readonly fieldName: string;
128
143
  readonly arguments: Arguments | null;
129
144
  };
130
145
 
131
146
  export type NormalizationLinkedField = {
132
147
  readonly kind: 'Linked';
148
+ readonly isFallible: boolean;
133
149
  readonly fieldName: string;
134
150
  readonly arguments: Arguments | null;
135
151
  readonly selections: NormalizationAstNodes;
@@ -1,5 +1,5 @@
1
- import type { ItemCleanupPair } from '@isograph/isograph-disposable-types/dist';
2
- import type { ParentCache } from '@isograph/isograph-react-disposable-state/dist';
1
+ import type { ItemCleanupPair } from '@isograph/disposable-types';
2
+ import type { ParentCache } from '@isograph/react-disposable-state';
3
3
  import {
4
4
  type NetworkResponseObject,
5
5
  getOrCreateItemInSuspenseCache,
@@ -395,20 +395,18 @@ function readDataForOnComplete<
395
395
  suspendIfInFlight: false,
396
396
  throwOnNetworkError: false,
397
397
  };
398
- const resolvedReaderWithRefetchQueries =
399
- readerWithRefetchQueries as ReaderWithRefetchQueries<
400
- TReadFromStore,
401
- TClientFieldValue
402
- >;
398
+ if (readerWithRefetchQueries == null) {
399
+ throw new Error(
400
+ 'Expected readerWithRefetchQueries to be not null. This is indicative of a bug in Isograph.',
401
+ );
402
+ }
403
403
 
404
404
  const fragment: FragmentReference<TReadFromStore, TClientFieldValue> = {
405
405
  kind: 'FragmentReference',
406
406
  // TODO this smells.
407
- readerWithRefetchQueries: wrapResolvedValue(
408
- resolvedReaderWithRefetchQueries,
409
- ),
410
- fieldName: resolvedReaderWithRefetchQueries.readerArtifact.fieldName,
411
- readerArtifactKind: resolvedReaderWithRefetchQueries.readerArtifact.kind,
407
+ readerWithRefetchQueries: wrapResolvedValue(readerWithRefetchQueries),
408
+ fieldName: readerWithRefetchQueries.readerArtifact.fieldName,
409
+ readerArtifactKind: readerWithRefetchQueries.readerArtifact.kind,
412
410
  root,
413
411
  variables,
414
412
  networkRequest: fakeNetworkRequest,
@@ -418,7 +416,7 @@ function readDataForOnComplete<
418
416
  fragment,
419
417
  fakeNetworkRequestOptions,
420
418
  ).item;
421
- const readerArtifact = resolvedReaderWithRefetchQueries.readerArtifact;
419
+ const readerArtifact = readerWithRefetchQueries.readerArtifact;
422
420
  switch (readerArtifact.kind) {
423
421
  case 'ComponentReaderArtifact': {
424
422
  // @ts-expect-error We should find a way to encode this in the type system:
@@ -432,7 +430,7 @@ function readDataForOnComplete<
432
430
  kind: 'ReaderWithRefetchQueries',
433
431
  readerArtifact: readerArtifact,
434
432
  nestedRefetchQueries:
435
- resolvedReaderWithRefetchQueries.nestedRefetchQueries,
433
+ readerWithRefetchQueries.nestedRefetchQueries,
436
434
  }),
437
435
  fieldName: readerArtifact.fieldName,
438
436
  readerArtifactKind: readerArtifact.kind,
package/src/core/read.ts CHANGED
@@ -18,12 +18,14 @@ import type {
18
18
  UnknownTReadFromStore,
19
19
  Variables,
20
20
  } from './FragmentReference';
21
- import type { IsographEnvironment } from './IsographEnvironment';
21
+ import type {
22
+ DataTypeValueScalar,
23
+ IsographEnvironment,
24
+ } from './IsographEnvironment';
22
25
  import {
23
26
  assertLink,
24
27
  getOrLoadIsographArtifact,
25
28
  getOrLoadReaderWithRefetchQueries,
26
- type DataTypeValue,
27
29
  type StoreLink,
28
30
  type StoreRecord,
29
31
  } from './IsographEnvironment';
@@ -548,25 +550,25 @@ export function readResolverFieldData(
548
550
 
549
551
  const readerWithRefetchQueries = {
550
552
  kind: 'ReaderWithRefetchQueries',
551
- readerArtifact: field.readerArtifact,
553
+ readerArtifact: field.readerArtifact(),
552
554
  nestedRefetchQueries: resolverRefetchQueries,
553
555
  } satisfies ReaderWithRefetchQueries<any, any>;
554
556
 
555
557
  const fragment = {
556
558
  kind: 'FragmentReference',
557
559
  readerWithRefetchQueries: wrapResolvedValue(readerWithRefetchQueries),
558
- fieldName: field.readerArtifact.fieldName,
559
- readerArtifactKind: field.readerArtifact.kind,
560
+ fieldName: readerWithRefetchQueries.readerArtifact.fieldName,
561
+ readerArtifactKind: readerWithRefetchQueries.readerArtifact.kind,
560
562
  root,
561
563
  variables: generateChildVariableMap(variables, field.arguments),
562
564
  networkRequest,
563
565
  } satisfies FragmentReference<any, any>;
564
566
 
565
- switch (field.readerArtifact.kind) {
567
+ switch (readerWithRefetchQueries.readerArtifact.kind) {
566
568
  case 'EagerReaderArtifact': {
567
569
  const data = readData(
568
570
  environment,
569
- field.readerArtifact.readerAst,
571
+ readerWithRefetchQueries.readerArtifact.readerAst,
570
572
  root,
571
573
  generateChildVariableMap(variables, field.arguments),
572
574
  resolverRefetchQueries,
@@ -585,7 +587,7 @@ export function readResolverFieldData(
585
587
  const firstParameter = {
586
588
  data: data.data,
587
589
  parameters: variables,
588
- startUpdate: field.readerArtifact.hasUpdatable
590
+ startUpdate: readerWithRefetchQueries.readerArtifact.hasUpdatable
589
591
  ? getOrCreateCachedStartUpdate(
590
592
  environment,
591
593
  fragment,
@@ -595,7 +597,7 @@ export function readResolverFieldData(
595
597
  };
596
598
  return {
597
599
  kind: 'Success',
598
- data: field.readerArtifact.resolver(firstParameter),
600
+ data: readerWithRefetchQueries.readerArtifact.resolver(firstParameter),
599
601
  };
600
602
  }
601
603
  case 'ComponentReaderArtifact': {
@@ -616,9 +618,7 @@ export function readScalarFieldData(
616
618
  storeRecord: StoreRecord,
617
619
  root: StoreLink,
618
620
  variables: Variables,
619
- ): ReadDataResult<
620
- string | number | boolean | StoreLink | readonly DataTypeValue[] | null
621
- > {
621
+ ): ReadDataResult<DataTypeValueScalar> {
622
622
  const storeRecordName = getParentRecordKey(field, variables);
623
623
  const value = storeRecord[storeRecordName];
624
624
  // TODO consider making scalars into discriminated unions. This probably has
@@ -651,7 +651,8 @@ export function readLinkedFieldData(
651
651
  let value = storeRecord[storeRecordName];
652
652
 
653
653
  if (field.condition != null) {
654
- const data = readData(field.condition.readerAst, root);
654
+ const condition = field.condition();
655
+ const data = readData(condition.readerAst, root);
655
656
  if (data.kind === 'MissingData') {
656
657
  return {
657
658
  kind: 'MissingData',
@@ -664,7 +665,7 @@ export function readLinkedFieldData(
664
665
 
665
666
  const readerWithRefetchQueries = {
666
667
  kind: 'ReaderWithRefetchQueries',
667
- readerArtifact: field.condition,
668
+ readerArtifact: condition,
668
669
  // TODO this is wrong
669
670
  // should map field.condition.usedRefetchQueries
670
671
  // but it doesn't exist
@@ -675,8 +676,8 @@ export function readLinkedFieldData(
675
676
  kind: 'FragmentReference',
676
677
  readerWithRefetchQueries: wrapResolvedValue(readerWithRefetchQueries),
677
678
  root,
678
- fieldName: field.condition.fieldName,
679
- readerArtifactKind: field.condition.kind,
679
+ fieldName: condition.fieldName,
680
+ readerArtifactKind: condition.kind,
680
681
  variables: generateChildVariableMap(
681
682
  variables,
682
683
  // TODO this is wrong
@@ -687,10 +688,10 @@ export function readLinkedFieldData(
687
688
  networkRequest,
688
689
  } satisfies FragmentReference<any, any>;
689
690
 
690
- const condition = field.condition.resolver({
691
+ const link = condition.resolver({
691
692
  data: data.data,
692
693
  parameters: {},
693
- ...(field.condition.hasUpdatable
694
+ ...(condition.hasUpdatable
694
695
  ? {
695
696
  startUpdate: getOrCreateCachedStartUpdate(
696
697
  environment,
@@ -700,7 +701,7 @@ export function readLinkedFieldData(
700
701
  }
701
702
  : undefined),
702
703
  });
703
- value = condition;
704
+ value = link;
704
705
  }
705
706
 
706
707
  if (Array.isArray(value)) {
@@ -870,6 +871,7 @@ export function readClientPointerData(
870
871
  [
871
872
  {
872
873
  kind: 'Scalar',
874
+ isFallible: false,
873
875
  fieldName: 'id',
874
876
  alias: null,
875
877
  arguments: null,
@@ -88,6 +88,7 @@ export type ReaderAst<TReadFromStore> = ReadonlyArray<ReaderAstNode>;
88
88
 
89
89
  export type ReaderScalarField = {
90
90
  readonly kind: 'Scalar';
91
+ readonly isFallible: boolean;
91
92
  readonly fieldName: string;
92
93
  readonly alias: string | null;
93
94
  readonly arguments: Arguments | null;
@@ -101,14 +102,17 @@ export type ReaderLinkField = {
101
102
 
102
103
  export type ReaderLinkedField = {
103
104
  readonly kind: 'Linked';
105
+ readonly isFallible: boolean;
104
106
  readonly fieldName: string;
105
107
  readonly alias: string | null;
106
108
  readonly selections: ReaderAst<unknown>;
107
109
  readonly arguments: Arguments | null;
108
- readonly condition: EagerReaderArtifact<
109
- { data: any; parameters: any; startUpdate?: StartUpdate<any> },
110
- StoreLink | null | (StoreLink | null)[] | StoreLink[]
111
- > | null;
110
+ readonly condition:
111
+ | (() => EagerReaderArtifact<
112
+ { data: any; parameters: any; startUpdate?: StartUpdate<any> },
113
+ StoreLink | null | (StoreLink | null)[] | StoreLink[]
114
+ >)
115
+ | null;
112
116
  readonly isUpdatable: boolean;
113
117
  /**
114
118
  * If refetchQueryIndex != null, then the linked field is a client pointer.
@@ -124,7 +128,7 @@ export type ReaderNonLoadableResolverField = {
124
128
  readonly kind: 'Resolver';
125
129
  readonly alias: string;
126
130
  // TODO don't type this as any
127
- readonly readerArtifact: TopLevelReaderArtifact<any, any, any>;
131
+ readonly readerArtifact: () => TopLevelReaderArtifact<any, any, any>;
128
132
  readonly arguments: Arguments | null;
129
133
  readonly usedRefetchQueries: number[];
130
134
  };
@@ -1,15 +1,14 @@
1
- import type { ItemCleanupPair } from '@isograph/isograph-disposable-types/dist';
2
- import { callSubscriptions } from './subscribe';
1
+ import type { ItemCleanupPair } from '@isograph/disposable-types';
3
2
  import {
4
- type NetworkResponseObject,
5
3
  type EncounteredIds,
4
+ type NetworkResponseObject,
6
5
  normalizeData,
7
6
  } from './cache';
8
7
  import type { IsographEntrypoint, NormalizationAst } from './entrypoint';
9
8
  import type {
10
- UnknownTReadFromStore,
11
9
  ExtractParameters,
12
10
  FragmentReference,
11
+ UnknownTReadFromStore,
13
12
  } from './FragmentReference';
14
13
  import {
15
14
  type IsographEnvironment,
@@ -19,6 +18,7 @@ import {
19
18
  import { logMessage } from './logging';
20
19
  import { retainQueryWithoutMakingNetworkRequest } from './makeNetworkRequest';
21
20
  import { addNetworkResponseStoreLayer } from './optimisticProxy';
21
+ import { callSubscriptions } from './subscribe';
22
22
 
23
23
  export function writeData<
24
24
  TReadFromStore extends UnknownTReadFromStore,
package/src/index.ts CHANGED
@@ -30,7 +30,8 @@ export { makeNetworkRequest } from './core/makeNetworkRequest';
30
30
  export {
31
31
  ROOT_ID,
32
32
  type DataId,
33
- type DataTypeValue,
33
+ type DataTypeValueLinked,
34
+ type DataTypeValueScalar,
34
35
  type IsographEnvironment,
35
36
  type IsographNetworkFunction,
36
37
  type BaseStoreLayerData as IsographStore,
@@ -1,2 +1,3 @@
1
1
  import type { Link } from '@isograph/react';
2
- export type Economist____link__output_type = Link<"Economist">;
2
+ export type Economist____link__output_type =
3
+ | Link<"Economist">;
@@ -3,6 +3,7 @@ import type { EagerReaderArtifact, ReaderAst, Link } from '@isograph/react';
3
3
  const readerAst: ReaderAst<{ data: any, parameters: Record<PropertyKey, never> }> = [
4
4
  {
5
5
  kind: "Scalar",
6
+ isFallible: false,
6
7
  fieldName: "__typename",
7
8
  alias: null,
8
9
  arguments: null,
@@ -14,15 +15,15 @@ const readerAst: ReaderAst<{ data: any, parameters: Record<PropertyKey, never> }
14
15
  },
15
16
  ];
16
17
 
17
- const artifact: EagerReaderArtifact<
18
+ const artifact = (): EagerReaderArtifact<
18
19
  { data: any, parameters: Record<PropertyKey, never> },
19
20
  Link<"Economist"> | null
20
- > = {
21
+ > => ({
21
22
  kind: "EagerReaderArtifact",
22
23
  fieldName: "asEconomist",
23
24
  resolver: ({ data }) => data.__typename === "Economist" ? data.__link : null,
24
25
  readerAst,
25
26
  hasUpdatable: false,
26
- };
27
+ });
27
28
 
28
29
  export default artifact;
@@ -4,6 +4,7 @@ const normalizationAst: NormalizationAst = {
4
4
  selections: [
5
5
  {
6
6
  kind: "Linked",
7
+ isFallible: true,
7
8
  fieldName: "node",
8
9
  arguments: [
9
10
  [
@@ -15,11 +16,13 @@ const normalizationAst: NormalizationAst = {
15
16
  selections: [
16
17
  {
17
18
  kind: "Scalar",
19
+ isFallible: false,
18
20
  fieldName: "__typename",
19
21
  arguments: null,
20
22
  },
21
23
  {
22
24
  kind: "Scalar",
25
+ isFallible: false,
23
26
  fieldName: "id",
24
27
  arguments: null,
25
28
  },
@@ -29,16 +32,19 @@ const normalizationAst: NormalizationAst = {
29
32
  selections: [
30
33
  {
31
34
  kind: "Scalar",
35
+ isFallible: false,
32
36
  fieldName: "__typename",
33
37
  arguments: null,
34
38
  },
35
39
  {
36
40
  kind: "Scalar",
41
+ isFallible: false,
37
42
  fieldName: "id",
38
43
  arguments: null,
39
44
  },
40
45
  {
41
46
  kind: "Scalar",
47
+ isFallible: false,
42
48
  fieldName: "name",
43
49
  arguments: null,
44
50
  },
@@ -48,6 +54,7 @@ const normalizationAst: NormalizationAst = {
48
54
  },
49
55
  {
50
56
  kind: "Linked",
57
+ isFallible: true,
51
58
  fieldName: "node",
52
59
  arguments: [
53
60
  [
@@ -59,11 +66,13 @@ const normalizationAst: NormalizationAst = {
59
66
  selections: [
60
67
  {
61
68
  kind: "Scalar",
69
+ isFallible: false,
62
70
  fieldName: "__typename",
63
71
  arguments: null,
64
72
  },
65
73
  {
66
74
  kind: "Scalar",
75
+ isFallible: false,
67
76
  fieldName: "id",
68
77
  arguments: null,
69
78
  },
@@ -73,16 +82,19 @@ const normalizationAst: NormalizationAst = {
73
82
  selections: [
74
83
  {
75
84
  kind: "Scalar",
85
+ isFallible: false,
76
86
  fieldName: "__typename",
77
87
  arguments: null,
78
88
  },
79
89
  {
80
90
  kind: "Scalar",
91
+ isFallible: false,
81
92
  fieldName: "id",
82
93
  arguments: null,
83
94
  },
84
95
  {
85
96
  kind: "Scalar",
97
+ isFallible: false,
86
98
  fieldName: "name",
87
99
  arguments: null,
88
100
  },