@isograph/react 0.4.3 → 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 (327) hide show
  1. package/.turbo/turbo-compile-libs.log +10 -3
  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 -27
  6. package/dist/core/FragmentReference.d.ts.map +1 -1
  7. package/dist/core/FragmentReference.js +8 -6
  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 +77 -72
  13. package/dist/core/IsographEnvironment.d.ts.map +1 -1
  14. package/dist/core/IsographEnvironment.js +62 -59
  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 +27 -18
  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 +18 -1
  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 -34
  34. package/dist/core/cache.d.ts.map +1 -1
  35. package/dist/core/cache.js +210 -516
  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 +24 -18
  41. package/dist/core/check.d.ts.map +1 -1
  42. package/dist/core/check.js +80 -124
  43. package/dist/core/check.mjs +84 -0
  44. package/dist/core/check.mjs.map +1 -0
  45. package/dist/core/componentCache.js +10 -34
  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 -68
  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 -10
  58. package/dist/core/garbageCollection.d.ts.map +1 -1
  59. package/dist/core/garbageCollection.js +82 -99
  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 +78 -60
  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 -8
  75. package/dist/core/makeNetworkRequest.d.ts.map +1 -1
  76. package/dist/core/makeNetworkRequest.js +188 -195
  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 +43 -0
  82. package/dist/core/optimisticProxy.d.ts.map +1 -0
  83. package/dist/core/optimisticProxy.js +273 -0
  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 -27
  89. package/dist/core/read.d.ts.map +1 -1
  90. package/dist/core/read.js +438 -618
  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 -74
  96. package/dist/core/reader.d.ts.map +1 -1
  97. package/dist/core/startUpdate.js +118 -156
  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 -68
  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 +10 -8
  128. package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -1
  129. package/dist/loadable-hooks/useClientSideDefer.js +14 -12
  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 +27 -21
  135. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -1
  136. package/dist/loadable-hooks/useConnectionSpecPagination.js +133 -158
  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 -7
  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 -13
  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 +20 -11
  184. package/dist/react/LoadableFieldReader.d.ts.map +1 -1
  185. package/dist/react/LoadableFieldReader.js +13 -8
  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 +21 -12
  191. package/dist/react/LoadableFieldRenderer.d.ts.map +1 -1
  192. package/dist/react/LoadableFieldRenderer.js +13 -35
  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 -7
  215. package/dist/react/useImperativeReference.d.ts.map +1 -1
  216. package/dist/react/useImperativeReference.js +34 -32
  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 -5
  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 -39
  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 -39
  245. package/dist/react/useResult.mjs +30 -0
  246. package/dist/react/useResult.mjs.map +1 -0
  247. package/package.json +26 -19
  248. package/src/core/FragmentReference.ts +13 -7
  249. package/src/core/IsographEnvironment.ts +80 -21
  250. package/src/core/PromiseWrapper.ts +14 -7
  251. package/src/core/areEqualWithDeepComparison.ts +2 -18
  252. package/src/core/brand.ts +18 -0
  253. package/src/core/cache.ts +62 -332
  254. package/src/core/check.ts +30 -26
  255. package/src/core/componentCache.ts +11 -44
  256. package/src/core/entrypoint.ts +50 -9
  257. package/src/core/garbageCollection.ts +81 -28
  258. package/src/core/getOrCreateCacheForArtifact.ts +86 -0
  259. package/src/core/logging.ts +25 -13
  260. package/src/core/makeNetworkRequest.ts +320 -94
  261. package/src/core/optimisticProxy.ts +544 -0
  262. package/src/core/read.ts +251 -198
  263. package/src/core/reader.ts +18 -17
  264. package/src/core/startUpdate.ts +47 -36
  265. package/src/core/subscribe.ts +189 -0
  266. package/src/core/util.ts +26 -0
  267. package/src/core/writeData.ts +79 -0
  268. package/src/index.ts +6 -4
  269. package/src/loadable-hooks/useClientSideDefer.ts +80 -30
  270. package/src/loadable-hooks/useConnectionSpecPagination.ts +54 -35
  271. package/src/loadable-hooks/useImperativeLoadableField.ts +5 -5
  272. package/src/loadable-hooks/useSkipLimitPagination.ts +22 -21
  273. package/src/react/FragmentReader.tsx +3 -1
  274. package/src/react/FragmentRenderer.tsx +8 -1
  275. package/src/react/IsographEnvironmentProvider.tsx +2 -1
  276. package/src/react/LoadableFieldReader.tsx +125 -16
  277. package/src/react/LoadableFieldRenderer.tsx +124 -16
  278. package/src/react/createIsographEnvironment.ts +23 -0
  279. package/src/react/maybeUnwrapNetworkRequest.ts +17 -0
  280. package/src/react/useImperativeReference.ts +25 -15
  281. package/src/react/useLazyReference.ts +20 -10
  282. package/src/react/useReadAndSubscribe.ts +53 -12
  283. package/src/react/useRerenderOnChange.ts +3 -3
  284. package/src/react/useResult.ts +15 -35
  285. package/src/tests/__isograph/Node/asEconomist/resolver_reader.ts +1 -1
  286. package/src/tests/__isograph/Query/linkedUpdate/entrypoint.ts +3 -1
  287. package/src/tests/__isograph/Query/linkedUpdate/raw_response_type.ts +13 -0
  288. package/src/tests/__isograph/Query/linkedUpdate/resolver_reader.ts +1 -1
  289. package/src/tests/__isograph/Query/meName/entrypoint.ts +3 -1
  290. package/src/tests/__isograph/Query/meName/raw_response_type.ts +7 -0
  291. package/src/tests/__isograph/Query/meName/resolver_reader.ts +1 -1
  292. package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +3 -1
  293. package/src/tests/__isograph/Query/meNameSuccessor/raw_response_type.ts +14 -0
  294. package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +1 -1
  295. package/src/tests/__isograph/Query/nodeField/entrypoint.ts +3 -1
  296. package/src/tests/__isograph/Query/nodeField/raw_response_type.ts +7 -0
  297. package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +1 -1
  298. package/src/tests/__isograph/Query/normalizeUndefinedField/entrypoint.ts +33 -0
  299. package/src/tests/__isograph/Query/normalizeUndefinedField/normalization_ast.ts +25 -0
  300. package/src/tests/__isograph/Query/normalizeUndefinedField/output_type.ts +3 -0
  301. package/src/tests/__isograph/Query/normalizeUndefinedField/param_type.ts +9 -0
  302. package/src/tests/__isograph/Query/normalizeUndefinedField/query_text.ts +6 -0
  303. package/src/tests/__isograph/Query/normalizeUndefinedField/raw_response_type.ts +7 -0
  304. package/src/tests/__isograph/Query/normalizeUndefinedField/resolver_reader.ts +38 -0
  305. package/src/tests/__isograph/Query/startUpdate/entrypoint.ts +3 -1
  306. package/src/tests/__isograph/Query/startUpdate/raw_response_type.ts +8 -0
  307. package/src/tests/__isograph/Query/startUpdate/resolver_reader.ts +1 -1
  308. package/src/tests/__isograph/Query/subquery/entrypoint.ts +3 -1
  309. package/src/tests/__isograph/Query/subquery/raw_response_type.ts +9 -0
  310. package/src/tests/__isograph/Query/subquery/resolver_reader.ts +1 -1
  311. package/src/tests/__isograph/iso.ts +11 -1
  312. package/src/tests/garbageCollection.test.ts +10 -10
  313. package/src/tests/meNameSuccessor.ts +7 -4
  314. package/src/tests/nodeQuery.ts +6 -4
  315. package/src/tests/normalizeData.test.ts +94 -18
  316. package/src/tests/optimisticProxy.test.ts +862 -0
  317. package/src/tests/startUpdate.test.ts +11 -11
  318. package/vitest.config.ts +5 -0
  319. package/dist/core/areEqualWithDeepComparison.d.ts +0 -3
  320. package/dist/core/areEqualWithDeepComparison.d.ts.map +0 -1
  321. package/dist/core/brand.js +0 -2
  322. package/dist/core/componentCache.d.ts +0 -5
  323. package/dist/core/componentCache.d.ts.map +0 -1
  324. package/dist/core/reader.js +0 -2
  325. package/dist/core/startUpdate.d.ts +0 -8
  326. package/dist/core/startUpdate.d.ts.map +0 -1
  327. package/dist/index.d.ts.map +0 -1
package/src/core/cache.ts CHANGED
@@ -1,43 +1,33 @@
1
- import {
2
- Factory,
3
- ItemCleanupPair,
4
- ParentCache,
5
- } from '@isograph/react-disposable-state';
6
- import {
7
- IsographEntrypoint,
1
+ import { type Factory, ParentCache } from '@isograph/react-disposable-state';
2
+ import type {
3
+ NormalizationAstNodes,
8
4
  NormalizationInlineFragment,
9
5
  NormalizationLinkedField,
10
6
  NormalizationScalarField,
11
- type NormalizationAst,
12
- type NormalizationAstLoader,
13
- type NormalizationAstNodes,
14
- } from '../core/entrypoint';
15
- import { mergeObjectsUsingReaderAst } from './areEqualWithDeepComparison';
16
- import { FetchOptions } from './check';
17
- import {
18
- ExtractParameters,
7
+ } from './entrypoint';
8
+ import type {
19
9
  FragmentReference,
10
+ UnknownTReadFromStore,
20
11
  Variables,
21
- type UnknownTReadFromStore,
22
- type VariableValue,
12
+ VariableValue,
23
13
  } from './FragmentReference';
24
14
  import {
25
- DataId,
26
- DataTypeValue,
27
- FragmentSubscription,
15
+ type DataId,
16
+ type DataTypeValue,
28
17
  getLink,
29
- ROOT_ID,
30
- StoreLink,
31
- StoreRecord,
32
18
  type IsographEnvironment,
19
+ ROOT_ID,
20
+ type StoreLink,
21
+ type StoreRecord,
33
22
  type TypeName,
34
23
  } from './IsographEnvironment';
35
24
  import { logMessage } from './logging';
36
- import { maybeMakeNetworkRequest } from './makeNetworkRequest';
37
- import { wrapPromise, wrapResolvedValue } from './PromiseWrapper';
38
- import { readButDoNotEvaluate, WithEncounteredRecords } from './read';
39
- import { ReaderLinkedField, ReaderScalarField, type ReaderAst } from './reader';
40
- import { Argument, ArgumentValue } from './util';
25
+ import {
26
+ getMutableStoreRecordProxy,
27
+ type StoreLayerWithData,
28
+ } from './optimisticProxy';
29
+ import type { ReaderLinkedField, ReaderScalarField } from './reader';
30
+ import { type Argument, type ArgumentValue, isArray, stableCopy } from './util';
41
31
 
42
32
  export const TYPENAME_FIELD_NAME = '__typename';
43
33
 
@@ -56,111 +46,31 @@ export function getOrCreateItemInSuspenseCache<
56
46
  return environment.fragmentCache[index];
57
47
  }
58
48
 
59
- /**
60
- * Creates a copy of the provided value, ensuring any nested objects have their
61
- * keys sorted such that equivalent values would have identical JSON.stringify
62
- * results.
63
- */
64
- export function stableCopy<T>(value: T): T {
65
- if (!value || typeof value !== 'object') {
66
- return value;
67
- }
68
- if (Array.isArray(value)) {
69
- // @ts-ignore
70
- return value.map(stableCopy);
71
- }
72
- const keys = Object.keys(value).sort();
73
- const stable: { [index: string]: any } = {};
74
- for (let i = 0; i < keys.length; i++) {
75
- // @ts-ignore
76
- stable[keys[i]] = stableCopy(value[keys[i]]);
77
- }
78
- return stable as any;
79
- }
80
-
81
- export function getOrCreateCacheForArtifact<
82
- TReadFromStore extends UnknownTReadFromStore,
83
- TClientFieldValue,
84
- TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
85
- >(
86
- environment: IsographEnvironment,
87
- entrypoint: IsographEntrypoint<
88
- TReadFromStore,
89
- TClientFieldValue,
90
- TNormalizationAst
91
- >,
92
- variables: ExtractParameters<TReadFromStore>,
93
- fetchOptions?: FetchOptions<TClientFieldValue>,
94
- ): ParentCache<FragmentReference<TReadFromStore, TClientFieldValue>> {
95
- let cacheKey = '';
96
- switch (entrypoint.networkRequestInfo.operation.kind) {
97
- case 'Operation':
98
- cacheKey =
99
- entrypoint.networkRequestInfo.operation.text +
100
- JSON.stringify(stableCopy(variables));
101
- break;
102
- case 'PersistedOperation':
103
- cacheKey =
104
- entrypoint.networkRequestInfo.operation.operationId +
105
- JSON.stringify(stableCopy(variables));
106
- break;
107
- }
108
- const factory = () => {
109
- const readerWithRefetchQueries =
110
- entrypoint.readerWithRefetchQueries.kind ===
111
- 'ReaderWithRefetchQueriesLoader'
112
- ? wrapPromise(entrypoint.readerWithRefetchQueries.loader())
113
- : wrapResolvedValue(entrypoint.readerWithRefetchQueries);
114
- const [networkRequest, disposeNetworkRequest] = maybeMakeNetworkRequest(
115
- environment,
116
- entrypoint,
117
- variables,
118
- readerWithRefetchQueries,
119
- fetchOptions ?? null,
120
- );
121
-
122
- const itemCleanupPair: ItemCleanupPair<
123
- FragmentReference<TReadFromStore, TClientFieldValue>
124
- > = [
125
- {
126
- kind: 'FragmentReference',
127
- readerWithRefetchQueries,
128
- root: { __link: ROOT_ID, __typename: entrypoint.concreteType },
129
- variables,
130
- networkRequest: networkRequest,
131
- },
132
- disposeNetworkRequest,
133
- ];
134
- return itemCleanupPair;
135
- };
136
- return getOrCreateItemInSuspenseCache(environment, cacheKey, factory);
137
- }
138
-
139
49
  export type NetworkResponseScalarValue = string | number | boolean;
140
50
  export type NetworkResponseValue =
141
51
  | NetworkResponseScalarValue
142
52
  | null
143
53
  | NetworkResponseObject
144
- | (NetworkResponseObject | null)[]
145
- | (NetworkResponseScalarValue | null)[];
54
+ | readonly (NetworkResponseObject | null)[]
55
+ | readonly (NetworkResponseScalarValue | null)[];
146
56
 
147
57
  export type NetworkResponseObject = {
148
58
  // N.B. undefined is here to support optional id's, but
149
59
  // undefined should not *actually* be present in the network response.
150
- [index: string]: undefined | NetworkResponseValue;
151
- id?: DataId;
152
- __typename?: TypeName;
60
+ readonly [index: string]: undefined | NetworkResponseValue;
61
+ readonly id?: DataId;
62
+ readonly __typename?: TypeName;
153
63
  };
154
64
 
155
65
  export function normalizeData(
156
66
  environment: IsographEnvironment,
67
+ storeLayer: StoreLayerWithData,
157
68
  normalizationAst: NormalizationAstNodes,
158
69
  networkResponse: NetworkResponseObject,
159
70
  variables: Variables,
160
71
  root: StoreLink,
72
+ encounteredIds: EncounteredIds,
161
73
  ): EncounteredIds {
162
- const encounteredIds: EncounteredIds = new Map();
163
-
164
74
  logMessage(environment, () => ({
165
75
  kind: 'AboutToNormalize',
166
76
  normalizationAst,
@@ -168,11 +78,11 @@ export function normalizeData(
168
78
  variables,
169
79
  }));
170
80
 
171
- const recordsById = (environment.store[root.__typename] ??= {});
172
- const newStoreRecord = (recordsById[root.__link] ??= {});
81
+ const newStoreRecord = getMutableStoreRecordProxy(storeLayer, root);
173
82
 
174
83
  normalizeDataIntoRecord(
175
84
  environment,
85
+ storeLayer,
176
86
  normalizationAst,
177
87
  networkResponse,
178
88
  newStoreRecord,
@@ -181,13 +91,6 @@ export function normalizeData(
181
91
  encounteredIds,
182
92
  );
183
93
 
184
- logMessage(environment, () => ({
185
- kind: 'AfterNormalization',
186
- store: environment.store,
187
- encounteredIds,
188
- }));
189
-
190
- callSubscriptions(environment, encounteredIds);
191
94
  return encounteredIds;
192
95
  }
193
96
 
@@ -217,27 +120,6 @@ export function subscribeToAnyChangesToRecord(
217
120
  return () => environment.subscriptions.delete(subscription);
218
121
  }
219
122
 
220
- // TODO we should re-read and call callback if the value has changed
221
- export function subscribe<TReadFromStore extends UnknownTReadFromStore>(
222
- environment: IsographEnvironment,
223
- encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
224
- fragmentReference: FragmentReference<TReadFromStore, any>,
225
- callback: (
226
- newEncounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
227
- ) => void,
228
- readerAst: ReaderAst<TReadFromStore>,
229
- ): () => void {
230
- const fragmentSubscription: FragmentSubscription<TReadFromStore> = {
231
- kind: 'FragmentSubscription',
232
- callback,
233
- encounteredDataAndRecords,
234
- fragmentReference,
235
- readerAst,
236
- };
237
- environment.subscriptions.add(fragmentSubscription);
238
- return () => environment.subscriptions.delete(fragmentSubscription);
239
- }
240
-
241
123
  export function onNextChangeToRecord(
242
124
  environment: IsographEnvironment,
243
125
  recordLink: StoreLink,
@@ -254,160 +136,13 @@ export function onNextChangeToRecord(
254
136
  });
255
137
  }
256
138
 
257
- // Calls to readButDoNotEvaluate can suspend (i.e. throw a promise).
258
- // Maybe in the future, they will be able to throw errors.
259
- //
260
- // That's probably okay to ignore. We don't, however, want to prevent
261
- // updating other subscriptions if one subscription had missing data.
262
- function logAnyError(
263
- environment: IsographEnvironment,
264
- context: any,
265
- f: () => void,
266
- ) {
267
- try {
268
- f();
269
- } catch (e) {
270
- logMessage(environment, () => ({
271
- kind: 'ErrorEncounteredInWithErrorHandling',
272
- error: e,
273
- context,
274
- }));
275
- }
276
- }
277
-
278
- export function callSubscriptions(
279
- environment: IsographEnvironment,
280
- recordsEncounteredWhenNormalizing: EncounteredIds,
281
- ) {
282
- environment.subscriptions.forEach((subscription) =>
283
- logAnyError(environment, { situation: 'calling subscriptions' }, () => {
284
- switch (subscription.kind) {
285
- case 'FragmentSubscription': {
286
- // TODO if there are multiple components subscribed to the same
287
- // fragment, we will call readButNotEvaluate multiple times. We
288
- // should fix that.
289
- if (
290
- hasOverlappingIds(
291
- recordsEncounteredWhenNormalizing,
292
- subscription.encounteredDataAndRecords.encounteredRecords,
293
- )
294
- ) {
295
- const newEncounteredDataAndRecords = readButDoNotEvaluate(
296
- environment,
297
- subscription.fragmentReference,
298
- // Is this wrong?
299
- // Reasons to think no:
300
- // - we are only updating the read-out value, and the network
301
- // options only affect whether we throw.
302
- // - the component will re-render, and re-throw on its own, anyway.
303
- //
304
- // Reasons to think not:
305
- // - it seems more efficient to suspend here and not update state,
306
- // if we expect that the component will just throw anyway
307
- // - consistency
308
- // - it's also weird, this is called from makeNetworkRequest, where
309
- // we don't currently pass network request options
310
- {
311
- suspendIfInFlight: false,
312
- throwOnNetworkError: false,
313
- },
314
- );
315
-
316
- const mergedItem = mergeObjectsUsingReaderAst(
317
- subscription.readerAst,
318
- subscription.encounteredDataAndRecords.item,
319
- newEncounteredDataAndRecords.item,
320
- );
321
-
322
- logMessage(environment, () => ({
323
- kind: 'DeepEqualityCheck',
324
- fragmentReference: subscription.fragmentReference,
325
- old: subscription.encounteredDataAndRecords.item,
326
- new: newEncounteredDataAndRecords.item,
327
- deeplyEqual:
328
- mergedItem === subscription.encounteredDataAndRecords.item,
329
- }));
330
-
331
- if (mergedItem !== subscription.encounteredDataAndRecords.item) {
332
- logAnyError(
333
- environment,
334
- { situation: 'calling FragmentSubscription callback' },
335
- () => {
336
- subscription.callback(newEncounteredDataAndRecords);
337
- },
338
- );
339
- subscription.encounteredDataAndRecords =
340
- newEncounteredDataAndRecords;
341
- }
342
- }
343
- return;
344
- }
345
- case 'AnyRecords': {
346
- logAnyError(
347
- environment,
348
- { situation: 'calling AnyRecords callback' },
349
- () => subscription.callback(),
350
- );
351
- return;
352
- }
353
- case 'AnyChangesToRecord': {
354
- if (
355
- recordsEncounteredWhenNormalizing
356
- .get(subscription.recordLink.__typename)
357
- ?.has(subscription.recordLink.__link)
358
- ) {
359
- logAnyError(
360
- environment,
361
- { situation: 'calling AnyChangesToRecord callback' },
362
- () => subscription.callback(),
363
- );
364
- }
365
- return;
366
- }
367
- default: {
368
- // Ensure we have covered all variants
369
- const _: never = subscription;
370
- _;
371
- throw new Error('Unexpected case');
372
- }
373
- }
374
- }),
375
- );
376
- }
377
-
378
- function hasOverlappingIds(
379
- ids1: EncounteredIds,
380
- ids2: EncounteredIds,
381
- ): boolean {
382
- for (const [typeName, set1] of ids1.entries()) {
383
- const set2 = ids2.get(typeName);
384
- if (set2 === undefined) {
385
- continue;
386
- }
387
-
388
- if (isNotDisjointFrom(set1, set2)) {
389
- return true;
390
- }
391
- }
392
- return false;
393
- }
394
-
395
- // TODO use a polyfill library
396
- function isNotDisjointFrom<T>(set1: Set<T>, set2: Set<T>): boolean {
397
- for (const id of set1) {
398
- if (set2.has(id)) {
399
- return true;
400
- }
401
- }
402
- return false;
403
- }
404
-
405
139
  export type EncounteredIds = Map<TypeName, Set<DataId>>;
406
140
  /**
407
141
  * Mutate targetParentRecord according to the normalizationAst and networkResponseParentRecord.
408
142
  */
409
143
  function normalizeDataIntoRecord(
410
144
  environment: IsographEnvironment,
145
+ storeLayer: StoreLayerWithData,
411
146
  normalizationAst: NormalizationAstNodes,
412
147
  networkResponseParentRecord: NetworkResponseObject,
413
148
  targetParentRecord: StoreRecord,
@@ -432,6 +167,7 @@ function normalizeDataIntoRecord(
432
167
  case 'Linked': {
433
168
  const linkedFieldResultedInChange = normalizeLinkedField(
434
169
  environment,
170
+ storeLayer,
435
171
  normalizationNode,
436
172
  networkResponseParentRecord,
437
173
  targetParentRecord,
@@ -446,6 +182,7 @@ function normalizeDataIntoRecord(
446
182
  case 'InlineFragment': {
447
183
  const inlineFragmentResultedInChange = normalizeInlineFragment(
448
184
  environment,
185
+ storeLayer,
449
186
  normalizationNode,
450
187
  networkResponseParentRecord,
451
188
  targetParentRecord,
@@ -457,12 +194,6 @@ function normalizeDataIntoRecord(
457
194
  recordHasBeenUpdated || inlineFragmentResultedInChange;
458
195
  break;
459
196
  }
460
- default: {
461
- // Ensure we have covered all variants
462
- let _: never = normalizationNode;
463
- _;
464
- throw new Error('Unexpected normalization node kind');
465
- }
466
197
  }
467
198
  }
468
199
  if (recordHasBeenUpdated) {
@@ -495,12 +226,14 @@ function normalizeScalarField(
495
226
  const networkResponseKey = getNetworkResponseKey(astNode);
496
227
  const networkResponseData = networkResponseParentRecord[networkResponseKey];
497
228
  const parentRecordKey = getParentRecordKey(astNode, variables);
229
+ const existingValue = targetStoreRecord[parentRecordKey];
498
230
 
499
- if (
500
- networkResponseData == null ||
501
- isScalarOrEmptyArray(networkResponseData)
502
- ) {
503
- const existingValue = targetStoreRecord[parentRecordKey];
231
+ if (networkResponseData == null) {
232
+ targetStoreRecord[parentRecordKey] = null;
233
+ return existingValue === undefined || existingValue != null;
234
+ }
235
+
236
+ if (isScalarOrEmptyArray(networkResponseData)) {
504
237
  targetStoreRecord[parentRecordKey] = networkResponseData;
505
238
  return existingValue !== networkResponseData;
506
239
  } else {
@@ -513,6 +246,7 @@ function normalizeScalarField(
513
246
  */
514
247
  function normalizeLinkedField(
515
248
  environment: IsographEnvironment,
249
+ storeLayer: StoreLayerWithData,
516
250
  astNode: NormalizationLinkedField,
517
251
  networkResponseParentRecord: NetworkResponseObject,
518
252
  targetParentRecord: StoreRecord,
@@ -527,7 +261,7 @@ function normalizeLinkedField(
527
261
 
528
262
  if (networkResponseData == null) {
529
263
  targetParentRecord[parentRecordKey] = null;
530
- return existingValue !== null;
264
+ return existingValue === undefined || existingValue != null;
531
265
  }
532
266
 
533
267
  if (
@@ -539,7 +273,7 @@ function normalizeLinkedField(
539
273
  );
540
274
  }
541
275
 
542
- if (Array.isArray(networkResponseData)) {
276
+ if (isArray(networkResponseData)) {
543
277
  // TODO check astNode.plural or the like
544
278
  const dataIds: (StoreLink | null)[] = [];
545
279
  for (let i = 0; i < networkResponseData.length; i++) {
@@ -550,6 +284,7 @@ function normalizeLinkedField(
550
284
  }
551
285
  const newStoreRecordId = normalizeNetworkResponseObject(
552
286
  environment,
287
+ storeLayer,
553
288
  astNode,
554
289
  networkResponseObject,
555
290
  targetParentRecordLink,
@@ -576,6 +311,7 @@ function normalizeLinkedField(
576
311
  } else {
577
312
  const newStoreRecordId = normalizeNetworkResponseObject(
578
313
  environment,
314
+ storeLayer,
579
315
  astNode,
580
316
  networkResponseData,
581
317
  targetParentRecordLink,
@@ -609,6 +345,7 @@ function normalizeLinkedField(
609
345
  */
610
346
  function normalizeInlineFragment(
611
347
  environment: IsographEnvironment,
348
+ storeLayer: StoreLayerWithData,
612
349
  astNode: NormalizationInlineFragment,
613
350
  networkResponseParentRecord: NetworkResponseObject,
614
351
  targetParentRecord: StoreRecord,
@@ -620,6 +357,7 @@ function normalizeInlineFragment(
620
357
  if (networkResponseParentRecord[TYPENAME_FIELD_NAME] === typeToRefineTo) {
621
358
  const hasBeenModified = normalizeDataIntoRecord(
622
359
  environment,
360
+ storeLayer,
623
361
  astNode.selections,
624
362
  networkResponseParentRecord,
625
363
  targetParentRecord,
@@ -636,7 +374,7 @@ function dataIdsAreTheSame(
636
374
  existingValue: DataTypeValue,
637
375
  newDataIds: (StoreLink | null)[],
638
376
  ): boolean {
639
- if (Array.isArray(existingValue)) {
377
+ if (isArray(existingValue)) {
640
378
  if (newDataIds.length !== existingValue.length) {
641
379
  return false;
642
380
  }
@@ -657,6 +395,7 @@ function dataIdsAreTheSame(
657
395
 
658
396
  function normalizeNetworkResponseObject(
659
397
  environment: IsographEnvironment,
398
+ storeLayer: StoreLayerWithData,
660
399
  astNode: NormalizationLinkedField,
661
400
  networkResponseData: NetworkResponseObject,
662
401
  targetParentRecordLink: StoreLink,
@@ -681,15 +420,16 @@ function normalizeNetworkResponseObject(
681
420
  );
682
421
  }
683
422
 
684
- const recordsById = (environment.store[__typename] ??= {});
685
- const newStoreRecord = (recordsById[newStoreRecordId] ??= {});
423
+ const link = { __link: newStoreRecordId, __typename };
424
+ const newStoreRecord = getMutableStoreRecordProxy(storeLayer, link);
686
425
 
687
426
  normalizeDataIntoRecord(
688
427
  environment,
428
+ storeLayer,
689
429
  astNode.selections,
690
430
  networkResponseData,
691
431
  newStoreRecord,
692
- { __link: newStoreRecordId, __typename: __typename },
432
+ link,
693
433
  variables,
694
434
  mutableEncounteredIds,
695
435
  );
@@ -698,30 +438,33 @@ function normalizeNetworkResponseObject(
698
438
  }
699
439
 
700
440
  function isScalarOrEmptyArray(
701
- data: NonNullable<NetworkResponseValue>,
702
- ): data is NetworkResponseScalarValue | (NetworkResponseScalarValue | null)[] {
441
+ data: NetworkResponseValue,
442
+ ): data is
443
+ | NetworkResponseScalarValue
444
+ | readonly (NetworkResponseScalarValue | null)[] {
703
445
  // N.B. empty arrays count as empty arrays of scalar fields.
704
- if (Array.isArray(data)) {
705
- // This is maybe fixed in a new version of Typescript??
706
- return (data as any).every((x: any) => isScalarOrEmptyArray(x));
446
+ if (isArray(data)) {
447
+ return data.every((x) => isScalarOrEmptyArray(x));
707
448
  }
708
449
  const isScalarValue =
709
- data === null ||
450
+ data == null ||
710
451
  typeof data === 'string' ||
711
452
  typeof data === 'number' ||
712
453
  typeof data === 'boolean';
713
454
  return isScalarValue;
714
455
  }
715
456
 
716
- function isNullOrEmptyArray(data: unknown): data is never[] | null[] | null {
717
- if (Array.isArray(data)) {
457
+ function isNullOrEmptyArray(
458
+ data: unknown,
459
+ ): data is readonly never[] | null[] | null {
460
+ if (isArray(data)) {
718
461
  if (data.length === 0) {
719
462
  return true;
720
463
  }
721
464
  return data.every((x) => isNullOrEmptyArray(x));
722
465
  }
723
466
 
724
- return data === null;
467
+ return data == null;
725
468
  }
726
469
 
727
470
  export function getParentRecordKey(
@@ -771,13 +514,6 @@ function getStoreKeyChunkForArgumentValue(
771
514
  case 'Enum': {
772
515
  return argumentValue.value;
773
516
  }
774
- default: {
775
- // TODO configure eslint to allow unused vars starting with _
776
- // Ensure we have covered all variants
777
- const _: never = argumentValue;
778
- _;
779
- throw new Error('Unexpected case');
780
- }
781
517
  }
782
518
  }
783
519
 
@@ -838,12 +574,6 @@ function getArgumentValueChunk(argumentValue: ArgumentValue): string {
838
574
  case 'Enum': {
839
575
  return 'e_' + argumentValue.value;
840
576
  }
841
- default: {
842
- // Ensure we have covered all variants
843
- let _: never = argumentValue;
844
- _;
845
- throw new Error('Unexpected case');
846
- }
847
577
  }
848
578
  }
849
579