@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
@@ -0,0 +1,862 @@
1
+ import { beforeEach, describe, expect, test, vi } from 'vitest';
2
+
3
+ import { type EncounteredIds } from '../core/cache';
4
+ import {
5
+ createIsographStore,
6
+ type IsographEnvironment,
7
+ type StoreLayerData,
8
+ } from '../core/IsographEnvironment';
9
+ import {
10
+ addNetworkResponseStoreLayer as addNetworkResponseStoreLayerInner,
11
+ addOptimisticUpdaterStoreLayer as addOptimisticStoreLayerInner,
12
+ addStartUpdateStoreLayer as addStartUpdateStoreLayerInner,
13
+ getStoreRecordProxy,
14
+ revertOptimisticStoreLayerAndMaybeReplace,
15
+ type OptimisticStoreLayer,
16
+ type StoreLayer,
17
+ } from '../core/optimisticProxy';
18
+ import { callSubscriptions } from '../core/subscribe';
19
+ import { createIsographEnvironment } from '../react/createIsographEnvironment';
20
+
21
+ vi.mock(import('../core/subscribe'), { spy: true });
22
+
23
+ const CHANGES = new Map([['Query', new Set(['__ROOT'])]]);
24
+ const NO_CHANGES = new Map();
25
+
26
+ describe('optimisticLayer', () => {
27
+ let environment: ReturnType<typeof createIsographEnvironment>;
28
+
29
+ beforeEach(() => {
30
+ vi.clearAllMocks();
31
+ const networkFunction = vi
32
+ .fn()
33
+ .mockRejectedValue(new Error('Fetch failed'));
34
+ environment = createIsographEnvironment(
35
+ createIsographStore(),
36
+ networkFunction,
37
+ );
38
+ addNetworkResponseStoreLayer(environment, 0);
39
+ });
40
+
41
+ describe('addNetworkResponseStoreLayer', () => {
42
+ test('has parent BaseStoreLayer', () => {
43
+ expect(environment.store).toMatchObject({
44
+ kind: 'BaseStoreLayer',
45
+ });
46
+ });
47
+
48
+ test('merge', () => {
49
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
50
+ addNetworkResponseStoreLayer(environment, 3);
51
+ addNetworkResponseStoreLayer(environment, 4);
52
+
53
+ expect(environment.store).toMatchObject({
54
+ kind: 'NetworkResponseStoreLayer',
55
+ parentStoreLayer: {
56
+ kind: 'OptimisticUpdaterStoreLayer',
57
+ parentStoreLayer: {
58
+ kind: 'BaseStoreLayer',
59
+ },
60
+ },
61
+ });
62
+
63
+ expect(
64
+ getStoreRecordProxy(environment.store, {
65
+ __link: '__ROOT',
66
+ __typename: 'Query',
67
+ })?.counter,
68
+ ).toBe(4);
69
+ });
70
+ });
71
+
72
+ describe('addStartUpdateStoreLayer', () => {
73
+ test('merge', () => {
74
+ addOptimisticStoreLayer(environment, () => 1);
75
+ addStartUpdateStoreLayer(environment, (counter) => counter + 1);
76
+ addStartUpdateStoreLayer(environment, (counter) => counter + 1);
77
+
78
+ expect(environment.store).toMatchObject({
79
+ kind: 'StartUpdateStoreLayer',
80
+ parentStoreLayer: {
81
+ kind: 'OptimisticUpdaterStoreLayer',
82
+ parentStoreLayer: {
83
+ kind: 'BaseStoreLayer',
84
+ },
85
+ },
86
+ });
87
+ expect(
88
+ getStoreRecordProxy(environment.store, {
89
+ __link: '__ROOT',
90
+ __typename: 'Query',
91
+ })?.counter,
92
+ ).toBe(3);
93
+ });
94
+ });
95
+
96
+ describe('addOptimisticStoreLayer', () => {
97
+ test('add tree nodes', () => {
98
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
99
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
100
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
101
+
102
+ expect(
103
+ getStoreRecordProxy(environment.store, {
104
+ __link: '__ROOT',
105
+ __typename: 'Query',
106
+ })?.counter,
107
+ ).toBe(3);
108
+ });
109
+ });
110
+
111
+ describe('replaceOptimisticStoreLayerWithNetworkResponseStoreLayer', () => {
112
+ describe('subscriptions', () => {
113
+ test('calls if network response differs', () => {
114
+ const revert = addOptimisticStoreLayer(environment, () => 1);
115
+
116
+ revert(2);
117
+
118
+ expect(callSubscriptions).toHaveBeenCalledTimes(1);
119
+ expect(callSubscriptions).toHaveBeenNthCalledWith(
120
+ 1,
121
+ expect.anything(),
122
+ CHANGES,
123
+ );
124
+ });
125
+
126
+ test("doesn't call subscriptions if no changes", () => {
127
+ const revert = addOptimisticStoreLayer(environment, () => 1);
128
+
129
+ revert(1);
130
+
131
+ expect(callSubscriptions).toHaveBeenCalledTimes(1);
132
+ expect(callSubscriptions).toHaveBeenNthCalledWith(
133
+ 1,
134
+ expect.anything(),
135
+ NO_CHANGES,
136
+ );
137
+ });
138
+
139
+ test('calls subscriptions if nodes update different fields', () => {
140
+ const node = addOptimisticStoreLayerInner(
141
+ environment.store,
142
+ (storeLayer) => {
143
+ ignoreReadonly(storeLayer).data = {
144
+ Query: {
145
+ __ROOT: {
146
+ surname: 'foo',
147
+ },
148
+ },
149
+ };
150
+ return CHANGES;
151
+ },
152
+ );
153
+ environment.store = node;
154
+ environment.store = addNetworkResponseStoreLayerInner(
155
+ environment.store,
156
+ );
157
+ ignoreReadonly(environment.store).data = {
158
+ Query: {
159
+ __ROOT: {
160
+ name: 'foo',
161
+ },
162
+ },
163
+ };
164
+
165
+ revertOptimisticStoreLayerAndMaybeReplace(
166
+ environment,
167
+ node,
168
+ (storeLayer) => {
169
+ ignoreReadonly(storeLayer).data = {
170
+ Query: { __ROOT: { surname: 'bar' } },
171
+ };
172
+ return CHANGES;
173
+ },
174
+ );
175
+
176
+ expect(callSubscriptions).toHaveBeenCalledTimes(1);
177
+ expect(callSubscriptions).toHaveBeenNthCalledWith(
178
+ 1,
179
+ expect.anything(),
180
+ CHANGES,
181
+ );
182
+ });
183
+
184
+ test('calls subscriptions if reverted unrelated field', () => {
185
+ const node = addOptimisticStoreLayerInner(
186
+ environment.store,
187
+ (storeLayer) => {
188
+ ignoreReadonly(storeLayer).data = {
189
+ Pet: { 1: { surname: 'foo' } },
190
+ };
191
+ return new Map([['Pet', new Set(['1'])]]);
192
+ },
193
+ );
194
+ environment.store = node;
195
+
196
+ environment.store = addNetworkResponseStoreLayerInner(
197
+ environment.store,
198
+ );
199
+ ignoreReadonly(environment.store).data = {
200
+ Query: { __ROOT: { name: 'foo' } },
201
+ };
202
+
203
+ revertOptimisticStoreLayerAndMaybeReplace(
204
+ environment,
205
+ node,
206
+ (storeLayer) => {
207
+ ignoreReadonly(storeLayer).data = {};
208
+ return new Map();
209
+ },
210
+ );
211
+
212
+ expect(callSubscriptions).toHaveBeenCalledTimes(1);
213
+ expect(callSubscriptions).toHaveBeenNthCalledWith(
214
+ 1,
215
+ expect.anything(),
216
+ new Map([['Pet', new Set(['1'])]]),
217
+ );
218
+ });
219
+ });
220
+
221
+ describe('with parent BaseStoreLayer', () => {
222
+ test('merges ', () => {
223
+ const revert = addOptimisticStoreLayer(
224
+ environment,
225
+ (counter) => counter + 1,
226
+ );
227
+
228
+ revert(5);
229
+
230
+ expect(environment.store).toMatchObject({
231
+ kind: 'BaseStoreLayer',
232
+ });
233
+
234
+ expect(
235
+ getStoreRecordProxy(environment.store, {
236
+ __link: '__ROOT',
237
+ __typename: 'Query',
238
+ })?.counter,
239
+ ).toBe(5);
240
+ });
241
+
242
+ test('merges children', () => {
243
+ const revert = addOptimisticStoreLayer(
244
+ environment,
245
+ (counter) => counter + 1,
246
+ );
247
+ addNetworkResponseStoreLayer(environment, 12);
248
+
249
+ revert(5);
250
+
251
+ expect(environment.store).toMatchObject({
252
+ kind: 'BaseStoreLayer',
253
+ });
254
+
255
+ expect(
256
+ getStoreRecordProxy(environment.store, {
257
+ __link: '__ROOT',
258
+ __typename: 'Query',
259
+ })?.counter,
260
+ ).toBe(12);
261
+ });
262
+
263
+ test('merges children and stops at optimistic child node', () => {
264
+ const revert = addOptimisticStoreLayer(
265
+ environment,
266
+ (counter) => counter + 1,
267
+ );
268
+ addStartUpdateStoreLayer(environment, (counter) => counter + 1);
269
+ addNetworkResponseStoreLayer(environment, 12);
270
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
271
+
272
+ revert(4);
273
+
274
+ expect(environment.store).toMatchObject({
275
+ kind: 'OptimisticUpdaterStoreLayer',
276
+ parentStoreLayer: {
277
+ kind: 'BaseStoreLayer',
278
+ },
279
+ });
280
+ expect(
281
+ getStoreRecordProxy(environment.store, {
282
+ __link: '__ROOT',
283
+ __typename: 'Query',
284
+ })?.counter,
285
+ ).toBe(13);
286
+ });
287
+
288
+ test('reexecutes updates while merging children', () => {
289
+ const revert = addOptimisticStoreLayer(
290
+ environment,
291
+ (counter) => counter + 1,
292
+ );
293
+ addStartUpdateStoreLayer(environment, (counter) => counter * 2);
294
+ addStartUpdateStoreLayer(environment, (counter) => counter + 7);
295
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
296
+
297
+ revert(4);
298
+
299
+ expect(environment.store).toMatchObject({
300
+ kind: 'OptimisticUpdaterStoreLayer',
301
+ parentStoreLayer: {
302
+ kind: 'BaseStoreLayer',
303
+ },
304
+ });
305
+ expect(
306
+ getStoreRecordProxy(environment.store, {
307
+ __link: '__ROOT',
308
+ __typename: 'Query',
309
+ })?.counter,
310
+ ).toBe(16);
311
+ });
312
+
313
+ test('stops at optimistic child node', () => {
314
+ const revert = addOptimisticStoreLayer(
315
+ environment,
316
+ (counter) => counter + 1,
317
+ );
318
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
319
+
320
+ revert(5);
321
+
322
+ expect(environment.store).toMatchObject({
323
+ kind: 'OptimisticUpdaterStoreLayer',
324
+ parentStoreLayer: {
325
+ kind: 'BaseStoreLayer',
326
+ },
327
+ });
328
+
329
+ expect(
330
+ getStoreRecordProxy(environment.store, {
331
+ __link: '__ROOT',
332
+ __typename: 'Query',
333
+ })?.counter,
334
+ ).toBe(6);
335
+ });
336
+ });
337
+
338
+ describe('adjacent with NetworkResponseStoreLayer', () => {
339
+ test('merges with parent NetworkResponseStoreLayer', () => {
340
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
341
+ addNetworkResponseStoreLayer(environment, 10);
342
+ const revert = addOptimisticStoreLayer(
343
+ environment,
344
+ (counter) => counter + 1,
345
+ );
346
+ addNetworkResponseStoreLayer(environment, 12);
347
+ revert(5);
348
+
349
+ expect(environment.store).toMatchObject({
350
+ kind: 'NetworkResponseStoreLayer',
351
+ parentStoreLayer: {
352
+ kind: 'OptimisticUpdaterStoreLayer',
353
+ parentStoreLayer: {
354
+ kind: 'BaseStoreLayer',
355
+ },
356
+ },
357
+ });
358
+
359
+ expect(
360
+ getStoreRecordProxy(environment.store, {
361
+ __link: '__ROOT',
362
+ __typename: 'Query',
363
+ })?.counter,
364
+ ).toBe(12);
365
+ });
366
+
367
+ test('merges child NetworkResponseStoreLayer', () => {
368
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
369
+ const revert = addOptimisticStoreLayer(
370
+ environment,
371
+ (counter) => counter + 1,
372
+ );
373
+ addNetworkResponseStoreLayer(environment, 12);
374
+ revert(5);
375
+
376
+ expect(environment.store).toMatchObject({
377
+ kind: 'NetworkResponseStoreLayer',
378
+ parentStoreLayer: {
379
+ kind: 'OptimisticUpdaterStoreLayer',
380
+ parentStoreLayer: {
381
+ kind: 'BaseStoreLayer',
382
+ },
383
+ },
384
+ });
385
+
386
+ expect(
387
+ getStoreRecordProxy(environment.store, {
388
+ __link: '__ROOT',
389
+ __typename: 'Query',
390
+ })?.counter,
391
+ ).toBe(12);
392
+ });
393
+
394
+ test('merges between two NetworkResponseStoreLayers', () => {
395
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
396
+ addNetworkResponseStoreLayer(environment, 10);
397
+ const revert = addOptimisticStoreLayer(
398
+ environment,
399
+ (counter) => counter + 1,
400
+ );
401
+ addNetworkResponseStoreLayer(environment, 12);
402
+ revert(5);
403
+
404
+ expect(environment.store).toMatchObject({
405
+ kind: 'NetworkResponseStoreLayer',
406
+ parentStoreLayer: {
407
+ kind: 'OptimisticUpdaterStoreLayer',
408
+ parentStoreLayer: {
409
+ kind: 'BaseStoreLayer',
410
+ },
411
+ },
412
+ });
413
+
414
+ expect(
415
+ getStoreRecordProxy(environment.store, {
416
+ __link: '__ROOT',
417
+ __typename: 'Query',
418
+ })?.counter,
419
+ ).toBe(12);
420
+ });
421
+ });
422
+
423
+ describe('has parent OptimisticStoreLayer', () => {
424
+ test('replaces self with network response', () => {
425
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
426
+ const revert = addOptimisticStoreLayer(
427
+ environment,
428
+ (counter) => counter + 1,
429
+ );
430
+
431
+ revert(5);
432
+
433
+ expect(environment.store).toMatchObject({
434
+ kind: 'NetworkResponseStoreLayer',
435
+ parentStoreLayer: {
436
+ kind: 'OptimisticUpdaterStoreLayer',
437
+ parentStoreLayer: {
438
+ kind: 'BaseStoreLayer',
439
+ },
440
+ },
441
+ });
442
+
443
+ expect(
444
+ getStoreRecordProxy(environment.store, {
445
+ __link: '__ROOT',
446
+ __typename: 'Query',
447
+ })?.counter,
448
+ ).toBe(5);
449
+ });
450
+ test("doesn't merge child nodes if has parent nodes", () => {
451
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
452
+ const revert = addOptimisticStoreLayer(
453
+ environment,
454
+ (counter) => counter + 1,
455
+ );
456
+ addStartUpdateStoreLayer(environment, (counter) => counter + 1);
457
+
458
+ revert(5);
459
+
460
+ expect(environment.store).toMatchObject({
461
+ kind: 'StartUpdateStoreLayer',
462
+ parentStoreLayer: {
463
+ kind: 'NetworkResponseStoreLayer',
464
+ parentStoreLayer: {
465
+ kind: 'OptimisticUpdaterStoreLayer',
466
+ parentStoreLayer: {
467
+ kind: 'BaseStoreLayer',
468
+ },
469
+ },
470
+ },
471
+ });
472
+
473
+ expect(
474
+ getStoreRecordProxy(environment.store, {
475
+ __link: '__ROOT',
476
+ __typename: 'Query',
477
+ })?.counter,
478
+ ).toBe(6);
479
+ });
480
+ });
481
+
482
+ describe('network error', () => {
483
+ describe('subscriptions', () => {
484
+ test('calls if network response differs', () => {
485
+ const revert = addOptimisticStoreLayer(environment, () => 1);
486
+
487
+ revert(null);
488
+
489
+ expect(callSubscriptions).toHaveBeenCalledTimes(1);
490
+ expect(callSubscriptions).toHaveBeenNthCalledWith(
491
+ 1,
492
+ expect.anything(),
493
+ CHANGES,
494
+ );
495
+ });
496
+
497
+ test('calls subscriptions if reverted unrelated field', () => {
498
+ const node = addOptimisticStoreLayerInner(
499
+ environment.store,
500
+ (storeLayer) => {
501
+ ignoreReadonly(storeLayer).data = {
502
+ Pet: { 1: { surname: 'foo' } },
503
+ };
504
+ return new Map([['Pet', new Set(['1'])]]);
505
+ },
506
+ );
507
+ environment.store = node;
508
+
509
+ environment.store = addNetworkResponseStoreLayerInner(
510
+ environment.store,
511
+ );
512
+ ignoreReadonly(environment.store).data = {
513
+ Query: { __ROOT: { name: 'foo' } },
514
+ };
515
+
516
+ revert(environment, node, null);
517
+
518
+ expect(callSubscriptions).toHaveBeenCalledTimes(1);
519
+ expect(callSubscriptions).toHaveBeenNthCalledWith(
520
+ 1,
521
+ expect.anything(),
522
+ new Map([['Pet', new Set(['1'])]]),
523
+ );
524
+ });
525
+ });
526
+
527
+ describe('with parent BaseStoreLayer', () => {
528
+ test('removes self ', () => {
529
+ const revert = addOptimisticStoreLayer(
530
+ environment,
531
+ (counter) => counter + 1,
532
+ );
533
+
534
+ revert(null);
535
+
536
+ expect(environment.store).toMatchObject({
537
+ kind: 'BaseStoreLayer',
538
+ });
539
+
540
+ expect(
541
+ getStoreRecordProxy(environment.store, {
542
+ __link: '__ROOT',
543
+ __typename: 'Query',
544
+ })?.counter,
545
+ ).toBe(0);
546
+ });
547
+
548
+ test('merges children', () => {
549
+ const revert = addOptimisticStoreLayer(
550
+ environment,
551
+ (counter) => counter + 1,
552
+ );
553
+ addNetworkResponseStoreLayer(environment, 12);
554
+
555
+ revert(null);
556
+
557
+ expect(environment.store).toMatchObject({
558
+ kind: 'BaseStoreLayer',
559
+ });
560
+
561
+ expect(
562
+ getStoreRecordProxy(environment.store, {
563
+ __link: '__ROOT',
564
+ __typename: 'Query',
565
+ })?.counter,
566
+ ).toBe(12);
567
+ });
568
+
569
+ test('merges children and stops at optimistic child node', () => {
570
+ const revert = addOptimisticStoreLayer(
571
+ environment,
572
+ (counter) => counter + 1,
573
+ );
574
+ addStartUpdateStoreLayer(environment, (counter) => counter + 1);
575
+ addNetworkResponseStoreLayer(environment, 12);
576
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
577
+
578
+ revert(null);
579
+
580
+ expect(environment.store).toMatchObject({
581
+ kind: 'OptimisticUpdaterStoreLayer',
582
+ parentStoreLayer: {
583
+ kind: 'BaseStoreLayer',
584
+ },
585
+ });
586
+ expect(
587
+ getStoreRecordProxy(environment.store, {
588
+ __link: '__ROOT',
589
+ __typename: 'Query',
590
+ })?.counter,
591
+ ).toBe(13);
592
+ });
593
+
594
+ test('reexecutes updates while merging children', () => {
595
+ const revert = addOptimisticStoreLayer(
596
+ environment,
597
+ (counter) => counter + 1,
598
+ );
599
+ addStartUpdateStoreLayer(environment, (counter) => counter + 2);
600
+ addStartUpdateStoreLayer(environment, (counter) => counter * 7);
601
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
602
+
603
+ revert(null);
604
+
605
+ expect(environment.store).toMatchObject({
606
+ kind: 'OptimisticUpdaterStoreLayer',
607
+ parentStoreLayer: {
608
+ kind: 'BaseStoreLayer',
609
+ },
610
+ });
611
+ expect(
612
+ getStoreRecordProxy(environment.store, {
613
+ __link: '__ROOT',
614
+ __typename: 'Query',
615
+ })?.counter,
616
+ ).toBe(15);
617
+ });
618
+
619
+ test('stops at optimistic child node', () => {
620
+ const revert = addOptimisticStoreLayer(
621
+ environment,
622
+ (counter) => counter + 1,
623
+ );
624
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
625
+
626
+ revert(null);
627
+
628
+ expect(environment.store).toMatchObject({
629
+ kind: 'OptimisticUpdaterStoreLayer',
630
+ parentStoreLayer: {
631
+ kind: 'BaseStoreLayer',
632
+ },
633
+ });
634
+
635
+ expect(
636
+ getStoreRecordProxy(environment.store, {
637
+ __link: '__ROOT',
638
+ __typename: 'Query',
639
+ })?.counter,
640
+ ).toBe(1);
641
+ });
642
+ });
643
+
644
+ describe('adjacent with NetworkResponseStoreLayer', () => {
645
+ test('merges with parent NetworkResponseStoreLayer', () => {
646
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
647
+ addNetworkResponseStoreLayer(environment, 10);
648
+ const revert = addOptimisticStoreLayer(
649
+ environment,
650
+ (counter) => counter + 1,
651
+ );
652
+ addNetworkResponseStoreLayer(environment, 12);
653
+ revert(null);
654
+
655
+ expect(environment.store).toMatchObject({
656
+ kind: 'NetworkResponseStoreLayer',
657
+ parentStoreLayer: {
658
+ kind: 'OptimisticUpdaterStoreLayer',
659
+ parentStoreLayer: {
660
+ kind: 'BaseStoreLayer',
661
+ },
662
+ },
663
+ });
664
+
665
+ expect(
666
+ getStoreRecordProxy(environment.store, {
667
+ __link: '__ROOT',
668
+ __typename: 'Query',
669
+ })?.counter,
670
+ ).toBe(12);
671
+ });
672
+
673
+ test('merges child NetworkResponseStoreLayer', () => {
674
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
675
+ const revert = addOptimisticStoreLayer(
676
+ environment,
677
+ (counter) => counter + 1,
678
+ );
679
+ addNetworkResponseStoreLayer(environment, 12);
680
+ revert(null);
681
+
682
+ expect(environment.store).toMatchObject({
683
+ kind: 'NetworkResponseStoreLayer',
684
+ parentStoreLayer: {
685
+ kind: 'OptimisticUpdaterStoreLayer',
686
+ parentStoreLayer: {
687
+ kind: 'BaseStoreLayer',
688
+ },
689
+ },
690
+ });
691
+
692
+ expect(
693
+ getStoreRecordProxy(environment.store, {
694
+ __link: '__ROOT',
695
+ __typename: 'Query',
696
+ })?.counter,
697
+ ).toBe(12);
698
+ });
699
+
700
+ test('removes self and merges two adjacent NetworkResponseStoreLayers', () => {
701
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
702
+ addNetworkResponseStoreLayer(environment, 10);
703
+ const revert = addOptimisticStoreLayer(
704
+ environment,
705
+ (counter) => counter + 1,
706
+ );
707
+ addNetworkResponseStoreLayer(environment, 12);
708
+ revert(null);
709
+
710
+ expect(environment.store).toMatchObject({
711
+ kind: 'NetworkResponseStoreLayer',
712
+ parentStoreLayer: {
713
+ kind: 'OptimisticUpdaterStoreLayer',
714
+ parentStoreLayer: {
715
+ kind: 'BaseStoreLayer',
716
+ },
717
+ },
718
+ });
719
+
720
+ expect(
721
+ getStoreRecordProxy(environment.store, {
722
+ __link: '__ROOT',
723
+ __typename: 'Query',
724
+ })?.counter,
725
+ ).toBe(12);
726
+ });
727
+ });
728
+
729
+ describe('has parent OptimisticStoreLayer', () => {
730
+ test('removes self', () => {
731
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
732
+ const revert = addOptimisticStoreLayer(
733
+ environment,
734
+ (counter) => counter + 1,
735
+ );
736
+
737
+ revert(null);
738
+
739
+ expect(environment.store).toMatchObject({
740
+ kind: 'OptimisticUpdaterStoreLayer',
741
+ parentStoreLayer: {
742
+ kind: 'BaseStoreLayer',
743
+ },
744
+ });
745
+
746
+ expect(
747
+ getStoreRecordProxy(environment.store, {
748
+ __link: '__ROOT',
749
+ __typename: 'Query',
750
+ })?.counter,
751
+ ).toBe(1);
752
+ });
753
+
754
+ test("doesn't merge child nodes if has parent nodes", () => {
755
+ addOptimisticStoreLayer(environment, (counter) => counter + 1);
756
+ const revert = addOptimisticStoreLayer(
757
+ environment,
758
+ (counter) => counter + 1,
759
+ );
760
+ addStartUpdateStoreLayer(environment, (counter) => counter + 1);
761
+
762
+ revert(null);
763
+
764
+ expect(environment.store).toMatchObject({
765
+ kind: 'StartUpdateStoreLayer',
766
+ parentStoreLayer: {
767
+ kind: 'OptimisticUpdaterStoreLayer',
768
+ parentStoreLayer: {
769
+ kind: 'BaseStoreLayer',
770
+ },
771
+ },
772
+ });
773
+
774
+ expect(
775
+ getStoreRecordProxy(environment.store, {
776
+ __link: '__ROOT',
777
+ __typename: 'Query',
778
+ })?.counter,
779
+ ).toBe(2);
780
+ });
781
+ });
782
+ });
783
+ });
784
+
785
+ // utils
786
+ function addNetworkResponseStoreLayer(
787
+ environment: IsographEnvironment,
788
+ counter: number,
789
+ ) {
790
+ environment.store = addNetworkResponseStoreLayerInner(environment.store);
791
+ update(environment.store, () => counter);
792
+ }
793
+
794
+ function addOptimisticStoreLayer(
795
+ environment: IsographEnvironment,
796
+ updater: (prev: number) => number,
797
+ ) {
798
+ const node = addOptimisticStoreLayerInner(
799
+ environment.store,
800
+ (storeLayer) => {
801
+ return update(storeLayer, updater);
802
+ },
803
+ );
804
+ environment.store = node;
805
+ return (counter: null | number) => {
806
+ revert(environment, node, counter);
807
+ };
808
+ }
809
+
810
+ function revert(
811
+ environment: IsographEnvironment,
812
+ node: OptimisticStoreLayer,
813
+ counter: null | number,
814
+ ) {
815
+ return revertOptimisticStoreLayerAndMaybeReplace(
816
+ environment,
817
+ node,
818
+ counter == null
819
+ ? counter
820
+ : (storeLayer) => update(storeLayer, () => counter),
821
+ );
822
+ }
823
+
824
+ function addStartUpdateStoreLayer(
825
+ environment: IsographEnvironment,
826
+ updater: (prev: number) => number,
827
+ ) {
828
+ const node = addStartUpdateStoreLayerInner(
829
+ environment.store,
830
+ (storeLayer) => {
831
+ return update(storeLayer, updater);
832
+ },
833
+ );
834
+ environment.store = node;
835
+ }
836
+
837
+ const update = (
838
+ storeLayer: StoreLayer,
839
+ value: (counter: number) => number,
840
+ ): EncounteredIds => {
841
+ const { counter } =
842
+ getStoreRecordProxy(storeLayer, {
843
+ __link: '__ROOT',
844
+ __typename: 'Query',
845
+ }) ?? {};
846
+ const nextCounter = value(Number(counter));
847
+
848
+ ignoreReadonly(storeLayer).data = {
849
+ Query: {
850
+ __ROOT: {
851
+ counter: nextCounter,
852
+ },
853
+ },
854
+ };
855
+
856
+ return counter !== nextCounter ? CHANGES : NO_CHANGES;
857
+ };
858
+
859
+ function ignoreReadonly(value: StoreLayer): { data: StoreLayerData } {
860
+ return value;
861
+ }
862
+ });