@isograph/react 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/.turbo/turbo-compile-libs.log +9 -2
  2. package/dist/_virtual/rolldown_runtime.js +25 -0
  3. package/dist/core/FragmentReference.d.mts +38 -0
  4. package/dist/core/FragmentReference.d.mts.map +1 -0
  5. package/dist/core/FragmentReference.d.ts +31 -29
  6. package/dist/core/FragmentReference.d.ts.map +1 -1
  7. package/dist/core/FragmentReference.js +7 -5
  8. package/dist/core/FragmentReference.mjs +10 -0
  9. package/dist/core/FragmentReference.mjs.map +1 -0
  10. package/dist/core/IsographEnvironment.d.mts +89 -0
  11. package/dist/core/IsographEnvironment.d.mts.map +1 -0
  12. package/dist/core/IsographEnvironment.d.ts +76 -79
  13. package/dist/core/IsographEnvironment.d.ts.map +1 -1
  14. package/dist/core/IsographEnvironment.js +60 -82
  15. package/dist/core/IsographEnvironment.mjs +67 -0
  16. package/dist/core/IsographEnvironment.mjs.map +1 -0
  17. package/dist/core/PromiseWrapper.d.mts +36 -0
  18. package/dist/core/PromiseWrapper.d.mts.map +1 -0
  19. package/dist/core/PromiseWrapper.d.ts +26 -23
  20. package/dist/core/PromiseWrapper.d.ts.map +1 -1
  21. package/dist/core/PromiseWrapper.js +45 -43
  22. package/dist/core/PromiseWrapper.mjs +49 -0
  23. package/dist/core/PromiseWrapper.mjs.map +1 -0
  24. package/dist/core/areEqualWithDeepComparison.js +56 -108
  25. package/dist/core/areEqualWithDeepComparison.mjs +62 -0
  26. package/dist/core/areEqualWithDeepComparison.mjs.map +1 -0
  27. package/dist/core/brand.d.mts +19 -0
  28. package/dist/core/brand.d.mts.map +1 -0
  29. package/dist/core/brand.d.ts +6 -6
  30. package/dist/core/brand.d.ts.map +1 -1
  31. package/dist/core/cache.d.mts +20 -0
  32. package/dist/core/cache.d.mts.map +1 -0
  33. package/dist/core/cache.d.ts +18 -37
  34. package/dist/core/cache.d.ts.map +1 -1
  35. package/dist/core/cache.js +203 -537
  36. package/dist/core/cache.mjs +237 -0
  37. package/dist/core/cache.mjs.map +1 -0
  38. package/dist/core/check.d.mts +28 -0
  39. package/dist/core/check.d.mts.map +1 -0
  40. package/dist/core/check.d.ts +21 -19
  41. package/dist/core/check.d.ts.map +1 -1
  42. package/dist/core/check.js +80 -127
  43. package/dist/core/check.mjs +84 -0
  44. package/dist/core/check.mjs.map +1 -0
  45. package/dist/core/componentCache.js +9 -35
  46. package/dist/core/componentCache.mjs +12 -0
  47. package/dist/core/componentCache.mjs.map +1 -0
  48. package/dist/core/entrypoint.d.mts +99 -0
  49. package/dist/core/entrypoint.d.mts.map +1 -0
  50. package/dist/core/entrypoint.d.ts +83 -78
  51. package/dist/core/entrypoint.d.ts.map +1 -1
  52. package/dist/core/entrypoint.js +6 -5
  53. package/dist/core/entrypoint.mjs +8 -0
  54. package/dist/core/entrypoint.mjs.map +1 -0
  55. package/dist/core/garbageCollection.d.mts +18 -0
  56. package/dist/core/garbageCollection.d.mts.map +1 -0
  57. package/dist/core/garbageCollection.d.ts +15 -16
  58. package/dist/core/garbageCollection.d.ts.map +1 -1
  59. package/dist/core/garbageCollection.js +76 -115
  60. package/dist/core/garbageCollection.mjs +89 -0
  61. package/dist/core/garbageCollection.mjs.map +1 -0
  62. package/dist/core/getOrCreateCacheForArtifact.js +37 -0
  63. package/dist/core/getOrCreateCacheForArtifact.mjs +38 -0
  64. package/dist/core/getOrCreateCacheForArtifact.mjs.map +1 -0
  65. package/dist/core/logging.d.mts +95 -0
  66. package/dist/core/logging.d.mts.map +1 -0
  67. package/dist/core/logging.d.ts +66 -61
  68. package/dist/core/logging.d.ts.map +1 -1
  69. package/dist/core/logging.js +17 -18
  70. package/dist/core/logging.mjs +20 -0
  71. package/dist/core/logging.mjs.map +1 -0
  72. package/dist/core/makeNetworkRequest.d.mts +13 -0
  73. package/dist/core/makeNetworkRequest.d.mts.map +1 -0
  74. package/dist/core/makeNetworkRequest.d.ts +12 -10
  75. package/dist/core/makeNetworkRequest.d.ts.map +1 -1
  76. package/dist/core/makeNetworkRequest.js +180 -264
  77. package/dist/core/makeNetworkRequest.mjs +195 -0
  78. package/dist/core/makeNetworkRequest.mjs.map +1 -0
  79. package/dist/core/optimisticProxy.d.mts +43 -0
  80. package/dist/core/optimisticProxy.d.mts.map +1 -0
  81. package/dist/core/optimisticProxy.d.ts +37 -53
  82. package/dist/core/optimisticProxy.d.ts.map +1 -1
  83. package/dist/core/optimisticProxy.js +245 -371
  84. package/dist/core/optimisticProxy.mjs +268 -0
  85. package/dist/core/optimisticProxy.mjs.map +1 -0
  86. package/dist/core/read.d.mts +29 -0
  87. package/dist/core/read.d.mts.map +1 -0
  88. package/dist/core/read.d.ts +23 -28
  89. package/dist/core/read.d.ts.map +1 -1
  90. package/dist/core/read.js +435 -650
  91. package/dist/core/read.mjs +456 -0
  92. package/dist/core/read.mjs.map +1 -0
  93. package/dist/core/reader.d.mts +89 -0
  94. package/dist/core/reader.d.mts.map +1 -0
  95. package/dist/core/reader.d.ts +78 -77
  96. package/dist/core/reader.d.ts.map +1 -1
  97. package/dist/core/startUpdate.js +115 -152
  98. package/dist/core/startUpdate.mjs +125 -0
  99. package/dist/core/startUpdate.mjs.map +1 -0
  100. package/dist/core/subscribe.d.mts +12 -0
  101. package/dist/core/subscribe.d.mts.map +1 -0
  102. package/dist/core/subscribe.d.ts +12 -0
  103. package/dist/core/subscribe.d.ts.map +1 -0
  104. package/dist/core/subscribe.js +79 -0
  105. package/dist/core/subscribe.mjs +79 -0
  106. package/dist/core/subscribe.mjs.map +1 -0
  107. package/dist/core/util.d.mts +27 -0
  108. package/dist/core/util.d.mts.map +1 -0
  109. package/dist/core/util.d.ts +21 -17
  110. package/dist/core/util.d.ts.map +1 -1
  111. package/dist/core/util.js +22 -2
  112. package/dist/core/util.mjs +21 -0
  113. package/dist/core/util.mjs.map +1 -0
  114. package/dist/core/writeData.d.mts +11 -0
  115. package/dist/core/writeData.d.mts.map +1 -0
  116. package/dist/core/writeData.d.ts +11 -0
  117. package/dist/core/writeData.d.ts.map +1 -0
  118. package/dist/core/writeData.js +41 -0
  119. package/dist/core/writeData.mjs +42 -0
  120. package/dist/core/writeData.mjs.map +1 -0
  121. package/dist/index.d.mts +32 -0
  122. package/dist/index.d.ts +32 -29
  123. package/dist/index.js +70 -69
  124. package/dist/index.mjs +31 -0
  125. package/dist/loadable-hooks/useClientSideDefer.d.mts +12 -0
  126. package/dist/loadable-hooks/useClientSideDefer.d.mts.map +1 -0
  127. package/dist/loadable-hooks/useClientSideDefer.d.ts +9 -12
  128. package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -1
  129. package/dist/loadable-hooks/useClientSideDefer.js +13 -44
  130. package/dist/loadable-hooks/useClientSideDefer.mjs +14 -0
  131. package/dist/loadable-hooks/useClientSideDefer.mjs.map +1 -0
  132. package/dist/loadable-hooks/useConnectionSpecPagination.d.mts +33 -0
  133. package/dist/loadable-hooks/useConnectionSpecPagination.d.mts.map +1 -0
  134. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +26 -22
  135. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -1
  136. package/dist/loadable-hooks/useConnectionSpecPagination.js +133 -172
  137. package/dist/loadable-hooks/useConnectionSpecPagination.mjs +134 -0
  138. package/dist/loadable-hooks/useConnectionSpecPagination.mjs.map +1 -0
  139. package/dist/loadable-hooks/useImperativeExposedMutationField.d.mts +8 -0
  140. package/dist/loadable-hooks/useImperativeExposedMutationField.d.mts.map +1 -0
  141. package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts +6 -3
  142. package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +1 -1
  143. package/dist/loadable-hooks/useImperativeExposedMutationField.js +9 -12
  144. package/dist/loadable-hooks/useImperativeExposedMutationField.mjs +11 -0
  145. package/dist/loadable-hooks/useImperativeExposedMutationField.mjs.map +1 -0
  146. package/dist/loadable-hooks/useImperativeLoadableField.d.mts +19 -0
  147. package/dist/loadable-hooks/useImperativeLoadableField.d.mts.map +1 -0
  148. package/dist/loadable-hooks/useImperativeLoadableField.d.ts +15 -11
  149. package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -1
  150. package/dist/loadable-hooks/useImperativeLoadableField.js +16 -12
  151. package/dist/loadable-hooks/useImperativeLoadableField.mjs +17 -0
  152. package/dist/loadable-hooks/useImperativeLoadableField.mjs.map +1 -0
  153. package/dist/loadable-hooks/useSkipLimitPagination.d.mts +24 -0
  154. package/dist/loadable-hooks/useSkipLimitPagination.d.mts.map +1 -0
  155. package/dist/loadable-hooks/useSkipLimitPagination.d.ts +19 -15
  156. package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -1
  157. package/dist/loadable-hooks/useSkipLimitPagination.js +118 -160
  158. package/dist/loadable-hooks/useSkipLimitPagination.mjs +119 -0
  159. package/dist/loadable-hooks/useSkipLimitPagination.mjs.map +1 -0
  160. package/dist/react/FragmentReader.d.mts +18 -0
  161. package/dist/react/FragmentReader.d.mts.map +1 -0
  162. package/dist/react/FragmentReader.d.ts +16 -8
  163. package/dist/react/FragmentReader.d.ts.map +1 -1
  164. package/dist/react/FragmentReader.js +8 -7
  165. package/dist/react/FragmentReader.mjs +10 -0
  166. package/dist/react/FragmentReader.mjs.map +1 -0
  167. package/dist/react/FragmentRenderer.d.mts +20 -0
  168. package/dist/react/FragmentRenderer.d.mts.map +1 -0
  169. package/dist/react/FragmentRenderer.d.ts +18 -14
  170. package/dist/react/FragmentRenderer.d.ts.map +1 -1
  171. package/dist/react/FragmentRenderer.js +11 -33
  172. package/dist/react/FragmentRenderer.mjs +12 -0
  173. package/dist/react/FragmentRenderer.mjs.map +1 -0
  174. package/dist/react/IsographEnvironmentProvider.d.mts +17 -0
  175. package/dist/react/IsographEnvironmentProvider.d.mts.map +1 -0
  176. package/dist/react/IsographEnvironmentProvider.d.ts +15 -9
  177. package/dist/react/IsographEnvironmentProvider.d.ts.map +1 -1
  178. package/dist/react/IsographEnvironmentProvider.js +15 -39
  179. package/dist/react/IsographEnvironmentProvider.mjs +17 -0
  180. package/dist/react/IsographEnvironmentProvider.mjs.map +1 -0
  181. package/dist/react/LoadableFieldReader.d.mts +21 -0
  182. package/dist/react/LoadableFieldReader.d.mts.map +1 -0
  183. package/dist/react/LoadableFieldReader.d.ts +15 -12
  184. package/dist/react/LoadableFieldReader.d.ts.map +1 -1
  185. package/dist/react/LoadableFieldReader.js +13 -47
  186. package/dist/react/LoadableFieldReader.mjs +14 -0
  187. package/dist/react/LoadableFieldReader.mjs.map +1 -0
  188. package/dist/react/LoadableFieldRenderer.d.mts +22 -0
  189. package/dist/react/LoadableFieldRenderer.d.mts.map +1 -0
  190. package/dist/react/LoadableFieldRenderer.d.ts +16 -13
  191. package/dist/react/LoadableFieldRenderer.d.ts.map +1 -1
  192. package/dist/react/LoadableFieldRenderer.js +13 -70
  193. package/dist/react/LoadableFieldRenderer.mjs +14 -0
  194. package/dist/react/LoadableFieldRenderer.mjs.map +1 -0
  195. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.mts +18 -0
  196. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.mts.map +1 -0
  197. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts +11 -3
  198. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts.map +1 -1
  199. package/dist/react/RenderAfterCommit__DO_NOT_USE.js +17 -13
  200. package/dist/react/RenderAfterCommit__DO_NOT_USE.mjs +18 -0
  201. package/dist/react/RenderAfterCommit__DO_NOT_USE.mjs.map +1 -0
  202. package/dist/react/createIsographEnvironment.d.mts +9 -0
  203. package/dist/react/createIsographEnvironment.d.mts.map +1 -0
  204. package/dist/react/createIsographEnvironment.d.ts +8 -0
  205. package/dist/react/createIsographEnvironment.d.ts.map +1 -0
  206. package/dist/react/createIsographEnvironment.js +10 -0
  207. package/dist/react/createIsographEnvironment.mjs +11 -0
  208. package/dist/react/createIsographEnvironment.mjs.map +1 -0
  209. package/dist/react/maybeUnwrapNetworkRequest.js +11 -0
  210. package/dist/react/maybeUnwrapNetworkRequest.mjs +12 -0
  211. package/dist/react/maybeUnwrapNetworkRequest.mjs.map +1 -0
  212. package/dist/react/useImperativeReference.d.mts +15 -0
  213. package/dist/react/useImperativeReference.d.mts.map +1 -0
  214. package/dist/react/useImperativeReference.d.ts +13 -8
  215. package/dist/react/useImperativeReference.d.ts.map +1 -1
  216. package/dist/react/useImperativeReference.js +34 -30
  217. package/dist/react/useImperativeReference.mjs +35 -0
  218. package/dist/react/useImperativeReference.mjs.map +1 -0
  219. package/dist/react/useLazyReference.d.mts +13 -0
  220. package/dist/react/useLazyReference.d.mts.map +1 -0
  221. package/dist/react/useLazyReference.d.ts +11 -6
  222. package/dist/react/useLazyReference.d.ts.map +1 -1
  223. package/dist/react/useLazyReference.js +17 -40
  224. package/dist/react/useLazyReference.mjs +18 -0
  225. package/dist/react/useLazyReference.mjs.map +1 -0
  226. package/dist/react/useReadAndSubscribe.d.mts +20 -0
  227. package/dist/react/useReadAndSubscribe.d.mts.map +1 -0
  228. package/dist/react/useReadAndSubscribe.d.ts +14 -9
  229. package/dist/react/useReadAndSubscribe.d.ts.map +1 -1
  230. package/dist/react/useReadAndSubscribe.js +57 -37
  231. package/dist/react/useReadAndSubscribe.mjs +59 -0
  232. package/dist/react/useReadAndSubscribe.mjs.map +1 -0
  233. package/dist/react/useRerenderOnChange.d.mts +12 -0
  234. package/dist/react/useRerenderOnChange.d.mts.map +1 -0
  235. package/dist/react/useRerenderOnChange.d.ts +10 -6
  236. package/dist/react/useRerenderOnChange.d.ts.map +1 -1
  237. package/dist/react/useRerenderOnChange.js +16 -20
  238. package/dist/react/useRerenderOnChange.mjs +17 -0
  239. package/dist/react/useRerenderOnChange.mjs.map +1 -0
  240. package/dist/react/useResult.d.mts +8 -0
  241. package/dist/react/useResult.d.mts.map +1 -0
  242. package/dist/react/useResult.d.ts +7 -5
  243. package/dist/react/useResult.d.ts.map +1 -1
  244. package/dist/react/useResult.js +27 -40
  245. package/dist/react/useResult.mjs +30 -0
  246. package/dist/react/useResult.mjs.map +1 -0
  247. package/package.json +17 -9
  248. package/src/core/FragmentReference.ts +3 -3
  249. package/src/core/IsographEnvironment.ts +29 -16
  250. package/src/core/areEqualWithDeepComparison.ts +2 -18
  251. package/src/core/cache.ts +18 -383
  252. package/src/core/check.ts +9 -16
  253. package/src/core/componentCache.ts +10 -47
  254. package/src/core/entrypoint.ts +15 -3
  255. package/src/core/garbageCollection.ts +21 -10
  256. package/src/core/getOrCreateCacheForArtifact.ts +86 -0
  257. package/src/core/logging.ts +10 -10
  258. package/src/core/makeNetworkRequest.ts +16 -23
  259. package/src/core/optimisticProxy.ts +28 -47
  260. package/src/core/read.ts +21 -38
  261. package/src/core/reader.ts +8 -11
  262. package/src/core/startUpdate.ts +2 -6
  263. package/src/core/subscribe.ts +189 -0
  264. package/src/core/util.ts +26 -0
  265. package/src/core/writeData.ts +79 -0
  266. package/src/index.ts +5 -4
  267. package/src/loadable-hooks/useClientSideDefer.ts +4 -4
  268. package/src/loadable-hooks/useConnectionSpecPagination.ts +20 -18
  269. package/src/loadable-hooks/useImperativeLoadableField.ts +3 -3
  270. package/src/loadable-hooks/useSkipLimitPagination.ts +20 -18
  271. package/src/react/IsographEnvironmentProvider.tsx +2 -1
  272. package/src/react/LoadableFieldReader.tsx +2 -4
  273. package/src/react/LoadableFieldRenderer.tsx +2 -4
  274. package/src/react/createIsographEnvironment.ts +23 -0
  275. package/src/react/maybeUnwrapNetworkRequest.ts +17 -0
  276. package/src/react/useImperativeReference.ts +5 -4
  277. package/src/react/useLazyReference.ts +7 -8
  278. package/src/react/useReadAndSubscribe.ts +53 -5
  279. package/src/react/useRerenderOnChange.ts +3 -3
  280. package/src/react/useResult.ts +6 -24
  281. package/src/tests/__isograph/Economist/__link/output_type.ts +2 -0
  282. package/src/tests/garbageCollection.test.ts +3 -6
  283. package/src/tests/meNameSuccessor.ts +1 -1
  284. package/src/tests/nodeQuery.ts +2 -2
  285. package/src/tests/normalizeData.test.ts +5 -3
  286. package/src/tests/optimisticProxy.test.ts +7 -5
  287. package/src/tests/startUpdate.test.ts +5 -7
  288. package/vitest.config.ts +5 -0
  289. package/dist/core/areEqualWithDeepComparison.d.ts +0 -3
  290. package/dist/core/areEqualWithDeepComparison.d.ts.map +0 -1
  291. package/dist/core/brand.js +0 -2
  292. package/dist/core/componentCache.d.ts +0 -5
  293. package/dist/core/componentCache.d.ts.map +0 -1
  294. package/dist/core/reader.js +0 -2
  295. package/dist/core/startUpdate.d.ts +0 -9
  296. package/dist/core/startUpdate.d.ts.map +0 -1
  297. package/dist/index.d.ts.map +0 -1
package/src/core/read.ts CHANGED
@@ -1,28 +1,28 @@
1
- import { CleanupFn, type ItemCleanupPair } from '@isograph/disposable-types';
1
+ import type { CleanupFn, ItemCleanupPair } from '@isograph/disposable-types';
2
2
  import {
3
3
  getParentRecordKey,
4
4
  insertEmptySetIfMissing,
5
5
  onNextChangeToRecord,
6
6
  type EncounteredIds,
7
7
  } from './cache';
8
- import { FetchOptions } from './check';
8
+ import type { FetchOptions } from './check';
9
9
  import { getOrCreateCachedComponent } from './componentCache';
10
- import {
10
+ import type {
11
11
  IsographEntrypoint,
12
+ ReaderWithRefetchQueries,
12
13
  RefetchQueryNormalizationArtifactWrapper,
13
- type ReaderWithRefetchQueries,
14
14
  } from './entrypoint';
15
- import {
15
+ import type {
16
16
  ExtractData,
17
17
  FragmentReference,
18
+ UnknownTReadFromStore,
18
19
  Variables,
19
- type UnknownTReadFromStore,
20
20
  } from './FragmentReference';
21
+ import type { IsographEnvironment } from './IsographEnvironment';
21
22
  import {
22
23
  assertLink,
23
24
  getOrLoadIsographArtifact,
24
25
  getOrLoadReaderWithRefetchQueries,
25
- IsographEnvironment,
26
26
  type DataTypeValue,
27
27
  type StoreLink,
28
28
  type StoreRecord,
@@ -30,25 +30,25 @@ import {
30
30
  import { logMessage } from './logging';
31
31
  import { maybeMakeNetworkRequest } from './makeNetworkRequest';
32
32
  import { getStoreRecordProxy } from './optimisticProxy';
33
+ import type { PromiseWrapper } from './PromiseWrapper';
33
34
  import {
34
35
  getPromiseState,
35
36
  NOT_SET,
36
- PromiseWrapper,
37
37
  readPromise,
38
38
  wrapPromise,
39
39
  wrapResolvedValue,
40
40
  } from './PromiseWrapper';
41
- import {
41
+ import type {
42
+ LoadablySelectedField,
42
43
  ReaderAst,
43
- type LoadablySelectedField,
44
- type ReaderClientPointer,
45
- type ReaderImperativelyLoadedField,
46
- type ReaderLinkedField,
47
- type ReaderNonLoadableResolverField,
48
- type ReaderScalarField,
44
+ ReaderClientPointer,
45
+ ReaderImperativelyLoadedField,
46
+ ReaderLinkedField,
47
+ ReaderNonLoadableResolverField,
48
+ ReaderScalarField,
49
49
  } from './reader';
50
50
  import { getOrCreateCachedStartUpdate } from './startUpdate';
51
- import { Arguments } from './util';
51
+ import type { Arguments } from './util';
52
52
 
53
53
  export type WithEncounteredRecords<T> = {
54
54
  readonly encounteredRecords: EncounteredIds;
@@ -164,7 +164,7 @@ function readData<TReadFromStore>(
164
164
  };
165
165
  }
166
166
 
167
- if (storeRecord === null) {
167
+ if (storeRecord == null) {
168
168
  return {
169
169
  kind: 'Success',
170
170
  data: null as any,
@@ -266,13 +266,6 @@ function readData<TReadFromStore>(
266
266
  target[field.alias] = data.data;
267
267
  break;
268
268
  }
269
-
270
- default: {
271
- // Ensure we have covered all variants
272
- let _: never = field;
273
- _;
274
- throw new Error('Unexpected case.');
275
- }
276
269
  }
277
270
  }
278
271
  return {
@@ -528,11 +521,6 @@ function writeQueryArgsToVariables(
528
521
  targetVariables[name] = argType.value;
529
522
  break;
530
523
  }
531
- default: {
532
- const _: never = argType;
533
- _;
534
- throw new Error('Unexpected case');
535
- }
536
524
  }
537
525
  }
538
526
  }
@@ -620,11 +608,6 @@ export function readResolverFieldData(
620
608
  ),
621
609
  };
622
610
  }
623
- default: {
624
- let _: never = field.readerArtifact;
625
- _;
626
- throw new Error('Unexpected kind');
627
- }
628
611
  }
629
612
  }
630
613
 
@@ -667,7 +650,7 @@ export function readLinkedFieldData(
667
650
  const storeRecordName = getParentRecordKey(field, variables);
668
651
  let value = storeRecord[storeRecordName];
669
652
 
670
- if (field.condition) {
653
+ if (field.condition != null) {
671
654
  const data = readData(field.condition.readerAst, root);
672
655
  if (data.kind === 'MissingData') {
673
656
  return {
@@ -736,7 +719,7 @@ export function readLinkedFieldData(
736
719
  JSON.stringify(item),
737
720
  recordLink: root,
738
721
  };
739
- } else if (link === null) {
722
+ } else if (link == null) {
740
723
  results.push(null);
741
724
  continue;
742
725
  }
@@ -827,7 +810,7 @@ export function readLinkedFieldData(
827
810
  } else {
828
811
  link = altLink;
829
812
  }
830
- } else if (link === null) {
813
+ } else if (link == null) {
831
814
  return {
832
815
  kind: 'Success',
833
816
  data: null,
@@ -869,7 +852,7 @@ export function readLinkedFieldData(
869
852
  function isClientPointer(
870
853
  field: ReaderLinkedField,
871
854
  ): field is ReaderClientPointer {
872
- return field.refetchQueryIndex !== null;
855
+ return field.refetchQueryIndex != null;
873
856
  }
874
857
 
875
858
  export function readClientPointerData(
@@ -1,22 +1,19 @@
1
- import { Factory } from '@isograph/disposable-types';
2
- import { FetchOptions } from './check';
3
- import {
1
+ import type { Factory } from '@isograph/disposable-types';
2
+ import type { FetchOptions } from './check';
3
+ import type {
4
4
  IsographEntrypoint,
5
5
  IsographEntrypointLoader,
6
6
  RefetchQueryNormalizationArtifact,
7
7
  RefetchQueryNormalizationArtifactWrapper,
8
8
  } from './entrypoint';
9
- import {
10
- ExtractParameters,
11
- FragmentReference,
12
- type UnknownTReadFromStore,
13
- } from './FragmentReference';
14
- import {
9
+ import type { ExtractParameters, FragmentReference } from './FragmentReference';
10
+ import { type UnknownTReadFromStore } from './FragmentReference';
11
+ import type {
15
12
  ComponentOrFieldName,
16
13
  IsographEnvironment,
17
- type StoreLink,
18
14
  } from './IsographEnvironment';
19
- import { Arguments } from './util';
15
+ import { type StoreLink } from './IsographEnvironment';
16
+ import type { Arguments } from './util';
20
17
 
21
18
  export type TopLevelReaderArtifact<
22
19
  TReadFromStore extends UnknownTReadFromStore,
@@ -1,5 +1,4 @@
1
1
  import {
2
- callSubscriptions,
3
2
  getParentRecordKey,
4
3
  insertEmptySetIfMissing,
5
4
  type EncounteredIds,
@@ -37,6 +36,7 @@ import {
37
36
  type ReadDataResultSuccess,
38
37
  } from './read';
39
38
  import type { ReaderAst } from './reader';
39
+ import { callSubscriptions } from './subscribe';
40
40
 
41
41
  export function getOrCreateCachedStartUpdate<
42
42
  TReadFromStore extends UnknownTReadFromStore,
@@ -161,7 +161,7 @@ function defineCachedProperty<T>(
161
161
  }
162
162
  return value.value;
163
163
  },
164
- ...(set && {
164
+ ...(set != null && {
165
165
  set: (newValue) => {
166
166
  set(newValue);
167
167
  mutableState.lastInvalidated++;
@@ -335,10 +335,6 @@ function readUpdatableData<TReadFromStore extends UnknownTReadFromStore>(
335
335
  target[field.alias] = root;
336
336
  break;
337
337
  }
338
- default: {
339
- field satisfies never;
340
- throw new Error('Unexpected case.');
341
- }
342
338
  }
343
339
  }
344
340
 
@@ -0,0 +1,189 @@
1
+ import { mergeObjectsUsingReaderAst } from './areEqualWithDeepComparison';
2
+ import type { EncounteredIds } from './cache';
3
+ import type {
4
+ FragmentReference,
5
+ UnknownTReadFromStore,
6
+ } from './FragmentReference';
7
+ import type {
8
+ FragmentSubscription,
9
+ IsographEnvironment,
10
+ } from './IsographEnvironment';
11
+ import { logMessage } from './logging';
12
+ import { type WithEncounteredRecords, readButDoNotEvaluate } from './read';
13
+ import type { ReaderAst } from './reader';
14
+
15
+ export function subscribe<TReadFromStore extends UnknownTReadFromStore>(
16
+ environment: IsographEnvironment,
17
+ encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
18
+ fragmentReference: FragmentReference<TReadFromStore, any>,
19
+ callback: (
20
+ newEncounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
21
+ ) => void,
22
+ readerAst: ReaderAst<TReadFromStore>,
23
+ ): () => void {
24
+ const fragmentSubscription: FragmentSubscription<TReadFromStore> = {
25
+ kind: 'FragmentSubscription',
26
+ callback,
27
+ encounteredDataAndRecords,
28
+ fragmentReference,
29
+ readerAst,
30
+ };
31
+
32
+ // subscribe is called in an effect. (We should actually subscribe during the
33
+ // initial render.) Because it's called in an effect, we might have missed some
34
+ // changes since the initial render! So, at this point, we re-read and call the
35
+ // subscription (i.e. re-render) if the fragment data has changed.
36
+ callSubscriptionIfDataChanged(environment, fragmentSubscription);
37
+
38
+ environment.subscriptions.add(fragmentSubscription);
39
+ return () => environment.subscriptions.delete(fragmentSubscription);
40
+ }
41
+
42
+ // Calls to readButDoNotEvaluate can suspend (i.e. throw a promise).
43
+ // Maybe in the future, they will be able to throw errors.
44
+ //
45
+ // That's probably okay to ignore. We don't, however, want to prevent
46
+ // updating other subscriptions if one subscription had missing data.
47
+ function logAnyError(
48
+ environment: IsographEnvironment,
49
+ context: any,
50
+ f: () => void,
51
+ ) {
52
+ try {
53
+ f();
54
+ } catch (e) {
55
+ logMessage(environment, () => ({
56
+ kind: 'ErrorEncounteredInWithErrorHandling',
57
+ error: e,
58
+ context,
59
+ }));
60
+ }
61
+ }
62
+
63
+ export function callSubscriptions(
64
+ environment: IsographEnvironment,
65
+ recordsEncounteredWhenNormalizing: EncounteredIds,
66
+ ) {
67
+ environment.subscriptions.forEach((subscription) =>
68
+ logAnyError(environment, { situation: 'calling subscriptions' }, () => {
69
+ switch (subscription.kind) {
70
+ case 'FragmentSubscription': {
71
+ // TODO if there are multiple components subscribed to the same
72
+ // fragment, we will call readButNotEvaluate multiple times. We
73
+ // should fix that.
74
+ if (
75
+ hasOverlappingIds(
76
+ recordsEncounteredWhenNormalizing,
77
+ subscription.encounteredDataAndRecords.encounteredRecords,
78
+ )
79
+ ) {
80
+ callSubscriptionIfDataChanged(environment, subscription);
81
+ }
82
+ return;
83
+ }
84
+ case 'AnyRecords': {
85
+ logAnyError(
86
+ environment,
87
+ { situation: 'calling AnyRecords callback' },
88
+ () => subscription.callback(),
89
+ );
90
+ return;
91
+ }
92
+ case 'AnyChangesToRecord': {
93
+ if (
94
+ recordsEncounteredWhenNormalizing
95
+ .get(subscription.recordLink.__typename)
96
+ ?.has(subscription.recordLink.__link) != null
97
+ ) {
98
+ logAnyError(
99
+ environment,
100
+ { situation: 'calling AnyChangesToRecord callback' },
101
+ () => subscription.callback(),
102
+ );
103
+ }
104
+ return;
105
+ }
106
+ }
107
+ }),
108
+ );
109
+ }
110
+
111
+ function callSubscriptionIfDataChanged<
112
+ TReadFromStore extends UnknownTReadFromStore,
113
+ >(
114
+ environment: IsographEnvironment,
115
+ subscription: FragmentSubscription<TReadFromStore>,
116
+ ) {
117
+ const newEncounteredDataAndRecords = readButDoNotEvaluate(
118
+ environment,
119
+ subscription.fragmentReference,
120
+ // Is this wrong?
121
+ // Reasons to think no:
122
+ // - we are only updating the read-out value, and the network
123
+ // options only affect whether we throw.
124
+ // - the component will re-render, and re-throw on its own, anyway.
125
+ //
126
+ // Reasons to think not:
127
+ // - it seems more efficient to suspend here and not update state,
128
+ // if we expect that the component will just throw anyway
129
+ // - consistency
130
+ // - it's also weird, this is called from makeNetworkRequest, where
131
+ // we don't currently pass network request options
132
+ {
133
+ suspendIfInFlight: false,
134
+ throwOnNetworkError: false,
135
+ },
136
+ );
137
+
138
+ const mergedItem = mergeObjectsUsingReaderAst(
139
+ subscription.readerAst,
140
+ subscription.encounteredDataAndRecords.item,
141
+ newEncounteredDataAndRecords.item,
142
+ );
143
+
144
+ logMessage(environment, () => ({
145
+ kind: 'DeepEqualityCheck',
146
+ fragmentReference: subscription.fragmentReference,
147
+ old: subscription.encounteredDataAndRecords.item,
148
+ new: newEncounteredDataAndRecords.item,
149
+ deeplyEqual: mergedItem === subscription.encounteredDataAndRecords.item,
150
+ }));
151
+
152
+ if (mergedItem !== subscription.encounteredDataAndRecords.item) {
153
+ logAnyError(
154
+ environment,
155
+ { situation: 'calling FragmentSubscription callback' },
156
+ () => {
157
+ subscription.callback(newEncounteredDataAndRecords);
158
+ },
159
+ );
160
+ subscription.encounteredDataAndRecords = newEncounteredDataAndRecords;
161
+ }
162
+ }
163
+
164
+ function hasOverlappingIds(
165
+ ids1: EncounteredIds,
166
+ ids2: EncounteredIds,
167
+ ): boolean {
168
+ for (const [typeName, set1] of ids1.entries()) {
169
+ const set2 = ids2.get(typeName);
170
+ if (set2 === undefined) {
171
+ continue;
172
+ }
173
+
174
+ if (isNotDisjointFrom(set1, set2)) {
175
+ return true;
176
+ }
177
+ }
178
+ return false;
179
+ }
180
+
181
+ // TODO use a polyfill library
182
+ function isNotDisjointFrom<T>(set1: Set<T>, set2: Set<T>): boolean {
183
+ for (const id of set1) {
184
+ if (set2.has(id)) {
185
+ return true;
186
+ }
187
+ }
188
+ return false;
189
+ }
package/src/core/util.ts CHANGED
@@ -31,3 +31,29 @@ export type ArgumentValue =
31
31
  readonly kind: 'Object';
32
32
  readonly value: Arguments;
33
33
  };
34
+
35
+ export function isArray(value: unknown): value is readonly unknown[] {
36
+ return Array.isArray(value);
37
+ }
38
+
39
+ /**
40
+ * Creates a copy of the provided value, ensuring any nested objects have their
41
+ * keys sorted such that equivalent values would have identical JSON.stringify
42
+ * results.
43
+ */
44
+ export function stableCopy<T>(value: T): T {
45
+ if (value == null || typeof value !== 'object') {
46
+ return value;
47
+ }
48
+ if (isArray(value)) {
49
+ // @ts-ignore
50
+ return value.map(stableCopy);
51
+ }
52
+ const keys = Object.keys(value).sort();
53
+ const stable: { [index: string]: any } = {};
54
+ for (let i = 0; i < keys.length; i++) {
55
+ // @ts-ignore
56
+ stable[keys[i]] = stableCopy(value[keys[i]]);
57
+ }
58
+ return stable as any;
59
+ }
@@ -0,0 +1,79 @@
1
+ import type { ItemCleanupPair } from '@isograph/isograph-disposable-types/dist';
2
+ import { callSubscriptions } from './subscribe';
3
+ import {
4
+ type NetworkResponseObject,
5
+ type EncounteredIds,
6
+ normalizeData,
7
+ } from './cache';
8
+ import type { IsographEntrypoint, NormalizationAst } from './entrypoint';
9
+ import type {
10
+ UnknownTReadFromStore,
11
+ ExtractParameters,
12
+ FragmentReference,
13
+ } from './FragmentReference';
14
+ import {
15
+ type IsographEnvironment,
16
+ ROOT_ID,
17
+ getOrLoadReaderWithRefetchQueries,
18
+ } from './IsographEnvironment';
19
+ import { logMessage } from './logging';
20
+ import { retainQueryWithoutMakingNetworkRequest } from './makeNetworkRequest';
21
+ import { addNetworkResponseStoreLayer } from './optimisticProxy';
22
+
23
+ export function writeData<
24
+ TReadFromStore extends UnknownTReadFromStore,
25
+ TRawResponseType extends NetworkResponseObject,
26
+ TClientFieldValue,
27
+ >(
28
+ environment: IsographEnvironment,
29
+ entrypoint: IsographEntrypoint<
30
+ TReadFromStore,
31
+ TClientFieldValue,
32
+ NormalizationAst,
33
+ TRawResponseType
34
+ >,
35
+ data: TRawResponseType,
36
+ variables: ExtractParameters<TReadFromStore>,
37
+ ): ItemCleanupPair<FragmentReference<TReadFromStore, TClientFieldValue>> {
38
+ const encounteredIds: EncounteredIds = new Map();
39
+ environment.store = addNetworkResponseStoreLayer(environment.store);
40
+ normalizeData(
41
+ environment,
42
+ environment.store,
43
+ entrypoint.networkRequestInfo.normalizationAst.selections,
44
+ data,
45
+ variables,
46
+ { __link: ROOT_ID, __typename: entrypoint.concreteType },
47
+ encounteredIds,
48
+ );
49
+ logMessage(environment, () => ({
50
+ kind: 'AfterNormalization',
51
+ store: environment.store,
52
+ encounteredIds,
53
+ }));
54
+
55
+ callSubscriptions(environment, encounteredIds);
56
+
57
+ const { fieldName, readerArtifactKind, readerWithRefetchQueries } =
58
+ getOrLoadReaderWithRefetchQueries(
59
+ environment,
60
+ entrypoint.readerWithRefetchQueries,
61
+ );
62
+ const [networkRequest, disposeNetworkRequest] =
63
+ retainQueryWithoutMakingNetworkRequest(environment, entrypoint, variables);
64
+
65
+ return [
66
+ {
67
+ kind: 'FragmentReference',
68
+ readerWithRefetchQueries,
69
+ fieldName,
70
+ readerArtifactKind,
71
+ root: { __link: ROOT_ID, __typename: entrypoint.concreteType },
72
+ variables,
73
+ networkRequest,
74
+ },
75
+ () => {
76
+ disposeNetworkRequest();
77
+ },
78
+ ];
79
+ }
package/src/index.ts CHANGED
@@ -18,15 +18,14 @@ export {
18
18
  NOT_SET,
19
19
  } from './core/PromiseWrapper';
20
20
  export {
21
- callSubscriptions,
22
- subscribe,
23
21
  normalizeData,
24
- writeData,
25
22
  type NetworkResponseObject,
26
23
  type NetworkResponseValue,
27
24
  type NetworkResponseScalarValue,
28
25
  type EncounteredIds,
29
26
  } from './core/cache';
27
+ export { callSubscriptions, subscribe } from './core/subscribe';
28
+ export { writeData } from './core/writeData';
30
29
  export { makeNetworkRequest } from './core/makeNetworkRequest';
31
30
  export {
32
31
  ROOT_ID,
@@ -40,7 +39,6 @@ export {
40
39
  type Link,
41
40
  type StoreRecord,
42
41
  type CacheMap,
43
- createIsographEnvironment,
44
42
  createIsographStore,
45
43
  type FieldCache,
46
44
  type Subscriptions,
@@ -86,7 +84,9 @@ export {
86
84
  type RefetchQueryNormalizationArtifactWrapper,
87
85
  type ExtractProps,
88
86
  type ExtractReadFromStore,
87
+ type ExtractClientFieldValue,
89
88
  type ExtractResolverResult,
89
+ type FragmentReferenceOfEntrypoint,
90
90
  type NetworkRequestInfo,
91
91
  type NormalizationInlineFragment,
92
92
  type ReaderWithRefetchQueries,
@@ -157,6 +157,7 @@ export {
157
157
  export { useLazyReference } from './react/useLazyReference';
158
158
  export { useRerenderOnChange } from './react/useRerenderOnChange';
159
159
  export { RenderAfterCommit__DO_NOT_USE } from './react/RenderAfterCommit__DO_NOT_USE';
160
+ export { createIsographEnvironment } from './react/createIsographEnvironment';
160
161
 
161
162
  export { useClientSideDefer } from './loadable-hooks/useClientSideDefer';
162
163
  export {
@@ -1,12 +1,12 @@
1
1
  import { useLazyDisposableState } from '@isograph/react-disposable-state';
2
2
  import { getOrCreateItemInSuspenseCache } from '../core/cache';
3
- import { FetchOptions } from '../core/check';
4
- import {
3
+ import type { FetchOptions } from '../core/check';
4
+ import type {
5
5
  ExtractParameters,
6
6
  FragmentReference,
7
- type UnknownTReadFromStore,
8
7
  } from '../core/FragmentReference';
9
- import { LoadableField } from '../core/reader';
8
+ import { type UnknownTReadFromStore } from '../core/FragmentReference';
9
+ import type { LoadableField } from '../core/reader';
10
10
  import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
11
11
 
12
12
  type ArgsWithoutProvidedArgs<
@@ -1,29 +1,27 @@
1
- import { ItemCleanupPair } from '@isograph/disposable-types';
1
+ import type { ItemCleanupPair } from '@isograph/disposable-types';
2
2
  import {
3
3
  UNASSIGNED_STATE,
4
4
  useUpdatableDisposableState,
5
5
  } from '@isograph/react-disposable-state';
6
- import {
7
- createReferenceCountedPointer,
8
- ReferenceCountedPointer,
9
- } from '@isograph/reference-counted-pointer';
6
+ import type { ReferenceCountedPointer } from '@isograph/reference-counted-pointer';
7
+ import { createReferenceCountedPointer } from '@isograph/reference-counted-pointer';
10
8
  import { useState } from 'react';
11
9
  import { subscribeToAnyChange } from '../core/cache';
12
- import { FetchOptions } from '../core/check';
13
- import {
10
+ import type { FetchOptions } from '../core/check';
11
+ import type {
14
12
  FragmentReference,
15
- type UnknownTReadFromStore,
13
+ UnknownTReadFromStore,
16
14
  } from '../core/FragmentReference';
17
15
  import { getPromiseState, readPromise } from '../core/PromiseWrapper';
18
16
  import {
19
17
  readButDoNotEvaluate,
20
18
  type WithEncounteredRecords,
21
19
  } from '../core/read';
22
- import { LoadableField, type ReaderAst } from '../core/reader';
20
+ import type { LoadableField, ReaderAst } from '../core/reader';
23
21
  import { getOrCreateCachedStartUpdate } from '../core/startUpdate';
24
22
  import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
23
+ import { maybeUnwrapNetworkRequest } from '../react/maybeUnwrapNetworkRequest';
25
24
  import { useSubscribeToMultiple } from '../react/useReadAndSubscribe';
26
- import { maybeUnwrapNetworkRequest } from '../react/useResult';
27
25
 
28
26
  export type UsePaginationReturnValue<
29
27
  TReadFromStore extends UnknownTReadFromStore,
@@ -264,7 +262,7 @@ export function useConnectionSpecPagination<
264
262
  const mostRecentFragmentReference =
265
263
  mostRecentItem?.[0].getItemIfNotDisposed();
266
264
 
267
- if (mostRecentItem && mostRecentFragmentReference === null) {
265
+ if (mostRecentItem != null && mostRecentFragmentReference == null) {
268
266
  throw new Error(
269
267
  'FragmentReference is unexpectedly disposed. \
270
268
  This is indicative of a bug in Isograph.',
@@ -272,11 +270,15 @@ export function useConnectionSpecPagination<
272
270
  }
273
271
 
274
272
  const networkRequestStatus =
275
- mostRecentFragmentReference &&
276
- getPromiseState(mostRecentFragmentReference.networkRequest);
273
+ mostRecentFragmentReference != null
274
+ ? {
275
+ mostRecentFragmentReference,
276
+ state: getPromiseState(mostRecentFragmentReference.networkRequest),
277
+ }
278
+ : null;
277
279
 
278
280
  const slicedFragmentReferences =
279
- networkRequestStatus?.kind === 'Ok'
281
+ networkRequestStatus?.state?.kind === 'Ok'
280
282
  ? loadedReferences
281
283
  : loadedReferences.slice(0, loadedReferences.length - 1);
282
284
 
@@ -306,7 +308,7 @@ export function useConnectionSpecPagination<
306
308
  subscribeCompletedFragmentReferences(completedFragmentReferences),
307
309
  );
308
310
 
309
- if (!networkRequestStatus) {
311
+ if (networkRequestStatus == null) {
310
312
  if (initialState?.hasNextPage ?? true) {
311
313
  return {
312
314
  kind: 'HasMoreRecords',
@@ -321,7 +323,7 @@ export function useConnectionSpecPagination<
321
323
  }
322
324
  }
323
325
 
324
- switch (networkRequestStatus.kind) {
326
+ switch (networkRequestStatus.state.kind) {
325
327
  case 'Pending': {
326
328
  const unsubscribe = subscribeToAnyChange(environment, () => {
327
329
  unsubscribe();
@@ -334,11 +336,11 @@ export function useConnectionSpecPagination<
334
336
  return {
335
337
  results: results.edges,
336
338
  kind: 'Pending',
337
- pendingFragment: mostRecentFragmentReference,
339
+ pendingFragment: networkRequestStatus.mostRecentFragmentReference,
338
340
  };
339
341
  }
340
342
  case 'Err': {
341
- throw networkRequestStatus.error;
343
+ throw networkRequestStatus.state.error;
342
344
  }
343
345
  case 'Ok': {
344
346
  const results = readCompletedFragmentReferences(
@@ -2,12 +2,12 @@ import {
2
2
  UNASSIGNED_STATE,
3
3
  useUpdatableDisposableState,
4
4
  } from '@isograph/react-disposable-state';
5
- import { FetchOptions } from '../core/check';
6
- import {
5
+ import type { FetchOptions } from '../core/check';
6
+ import type {
7
7
  ExtractParameters,
8
8
  FragmentReference,
9
9
  } from '../core/FragmentReference';
10
- import { LoadableField } from '../core/reader';
10
+ import type { LoadableField } from '../core/reader';
11
11
 
12
12
  export type UseImperativeLoadableFieldReturn<
13
13
  TReadFromStore extends { data: object; parameters: object },