@warp-drive/core 5.9.0-beta.0 → 5.9.0-beta.2

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 (476) hide show
  1. package/dist/-private-BYn1Vh-L.js +22 -0
  2. package/dist/-private-BYn1Vh-L.js.map +1 -0
  3. package/dist/-private-CyhhcK1a.js +120 -0
  4. package/dist/-private-CyhhcK1a.js.map +1 -0
  5. package/dist/-private-zrP4VGAf.js +3530 -0
  6. package/dist/-private-zrP4VGAf.js.map +1 -0
  7. package/dist/aliases-BWYW5EhX.d.ts +17 -0
  8. package/dist/aliases-BWYW5EhX.d.ts.map +1 -0
  9. package/dist/build-config/babel-macros.d.ts +2 -0
  10. package/dist/build-config/babel-macros.js +3 -1
  11. package/dist/build-config/canary-features.d.ts +1 -0
  12. package/dist/build-config/canary-features.js +1 -1
  13. package/dist/build-config/debugging.d.ts +1 -0
  14. package/dist/build-config/debugging.js +1 -1
  15. package/dist/build-config/deprecations.d.ts +1 -0
  16. package/dist/build-config/deprecations.js +1 -1
  17. package/dist/build-config/env.d.ts +2 -0
  18. package/dist/build-config/env.js +3 -1
  19. package/dist/build-config/macros.d.ts +2 -0
  20. package/dist/build-config/macros.js +3 -1
  21. package/dist/build-config.d.ts +2 -0
  22. package/dist/build-config.js +3 -1
  23. package/dist/change-C7kqv2kW.d.ts +41 -0
  24. package/dist/change-C7kqv2kW.d.ts.map +1 -0
  25. package/dist/concepts-DFldVwEM.d.ts +77 -0
  26. package/dist/concepts-DFldVwEM.d.ts.map +1 -0
  27. package/dist/configure-B_F639tN.d.ts +134 -0
  28. package/dist/configure-B_F639tN.d.ts.map +1 -0
  29. package/dist/configure.d.ts +2 -0
  30. package/dist/configure.js +3 -2
  31. package/dist/document-BEn91SwT.d.ts +129 -0
  32. package/dist/document-BEn91SwT.d.ts.map +1 -0
  33. package/dist/error-50OSEhsF.d.ts +77 -0
  34. package/dist/error-50OSEhsF.d.ts.map +1 -0
  35. package/dist/fields-FM7peCiM.d.ts +2327 -0
  36. package/dist/fields-FM7peCiM.d.ts.map +1 -0
  37. package/dist/graph/-private.d.ts +2 -0
  38. package/dist/graph/-private.js +2200 -3196
  39. package/dist/graph/-private.js.map +1 -0
  40. package/dist/graph-DLqYXP2z.d.ts +186 -0
  41. package/dist/graph-DLqYXP2z.d.ts.map +1 -0
  42. package/dist/identifier-DQnqOSJK.d.ts +112 -0
  43. package/dist/identifier-DQnqOSJK.d.ts.map +1 -0
  44. package/dist/index.d.ts +2 -0
  45. package/dist/index.js +3 -8
  46. package/dist/internal-DtWOpxrR.d.ts +9182 -0
  47. package/dist/internal-DtWOpxrR.d.ts.map +1 -0
  48. package/dist/json-api-raw-C5APJHHB.d.ts +378 -0
  49. package/dist/json-api-raw-C5APJHHB.d.ts.map +1 -0
  50. package/dist/mutations-CqtoGB4t.d.ts +165 -0
  51. package/dist/mutations-CqtoGB4t.d.ts.map +1 -0
  52. package/dist/operations-D1qA6r0_.d.ts +244 -0
  53. package/dist/operations-D1qA6r0_.d.ts.map +1 -0
  54. package/dist/params-DrEx3bf8.d.ts +41 -0
  55. package/dist/params-DrEx3bf8.d.ts.map +1 -0
  56. package/dist/raw-D5hnjiq7.d.ts +31 -0
  57. package/dist/raw-D5hnjiq7.d.ts.map +1 -0
  58. package/dist/reactive/-private.d.ts +2 -0
  59. package/dist/reactive/-private.js +3 -1
  60. package/dist/reactive.d.ts +2 -0
  61. package/dist/reactive.js +5 -4
  62. package/dist/record-D3QQcaIR.d.ts +254 -0
  63. package/dist/record-D3QQcaIR.d.ts.map +1 -0
  64. package/dist/relationship-CmHzMPKf.d.ts +65 -0
  65. package/dist/relationship-CmHzMPKf.d.ts.map +1 -0
  66. package/dist/request-7BJFgSu_.js +766 -0
  67. package/dist/request-7BJFgSu_.js.map +1 -0
  68. package/dist/request.d.ts +2 -0
  69. package/dist/request.js +2 -48
  70. package/dist/signals/-leaked.d.ts +1060 -0
  71. package/dist/signals/-leaked.d.ts.map +1 -0
  72. package/dist/signals/-leaked.js +3 -1
  73. package/dist/src-BOAWJH_S.js +9227 -0
  74. package/dist/src-BOAWJH_S.js.map +1 -0
  75. package/dist/store/-private.d.ts +2 -0
  76. package/dist/store/-private.js +3 -1
  77. package/dist/store-DNF9Rgoh.js +462 -0
  78. package/dist/store-DNF9Rgoh.js.map +1 -0
  79. package/dist/store.d.ts +2 -0
  80. package/dist/store.js +3 -1
  81. package/dist/symbols-DjRDCeX0.d.ts +88 -0
  82. package/dist/symbols-DjRDCeX0.d.ts.map +1 -0
  83. package/dist/types/-private.d.ts +76 -0
  84. package/dist/types/-private.d.ts.map +1 -0
  85. package/dist/types/-private.js +1 -77
  86. package/dist/types/cache/aliases.d.ts +2 -0
  87. package/dist/types/cache/change.d.ts +2 -0
  88. package/dist/types/cache/mutations.d.ts +2 -0
  89. package/dist/types/cache/operations.d.ts +2 -0
  90. package/dist/types/cache/relationship.d.ts +2 -0
  91. package/dist/types/cache.d.ts +2 -0
  92. package/dist/types/graph.d.ts +2 -0
  93. package/dist/types/identifier.d.ts +2 -0
  94. package/dist/types/identifier.js +60 -52
  95. package/dist/types/identifier.js.map +1 -0
  96. package/dist/types/json/raw.d.ts +2 -0
  97. package/dist/types/params.d.ts +2 -0
  98. package/dist/types/record.d.ts +2 -0
  99. package/dist/types/record.js +211 -181
  100. package/dist/types/record.js.map +1 -0
  101. package/dist/types/request.d.ts +2 -0
  102. package/dist/types/request.js +138 -69
  103. package/dist/types/request.js.map +1 -0
  104. package/dist/types/runtime.d.ts +55 -0
  105. package/dist/types/runtime.d.ts.map +1 -0
  106. package/dist/types/runtime.js +54 -26
  107. package/dist/types/runtime.js.map +1 -0
  108. package/dist/types/schema/concepts.d.ts +2 -0
  109. package/dist/types/schema/fields.d.ts +2 -0
  110. package/dist/types/schema/fields.js +501 -495
  111. package/dist/types/schema/fields.js.map +1 -0
  112. package/dist/types/schema/fields.type-test.d.ts +1 -0
  113. package/dist/types/schema/fields.type-test.js +79 -0
  114. package/dist/types/schema/fields.type-test.js.map +1 -0
  115. package/dist/types/schema/schema-service.d.ts +2 -0
  116. package/dist/types/spec/document.d.ts +2 -0
  117. package/dist/types/spec/error.d.ts +2 -0
  118. package/dist/types/spec/json-api-raw.d.ts +2 -0
  119. package/dist/types/symbols.d.ts +2 -0
  120. package/dist/types/symbols.js +84 -77
  121. package/dist/types/symbols.js.map +1 -0
  122. package/dist/types/utils.d.ts +2 -0
  123. package/dist/types.d.ts +3 -0
  124. package/dist/unpkg/dev/-private-BoSTJwp9.js +3519 -0
  125. package/dist/unpkg/dev/-private-BoSTJwp9.js.map +1 -0
  126. package/dist/unpkg/dev/-private-CUkeqUhO.js +22 -0
  127. package/dist/unpkg/dev/-private-CUkeqUhO.js.map +1 -0
  128. package/dist/unpkg/dev/-private-D6Tw25AD.js +111 -0
  129. package/dist/unpkg/dev/-private-D6Tw25AD.js.map +1 -0
  130. package/dist/unpkg/dev/build-config/babel-macros.js +3 -1
  131. package/dist/unpkg/dev/build-config/canary-features.js +1 -1
  132. package/dist/unpkg/dev/build-config/debugging.js +1 -1
  133. package/dist/unpkg/dev/build-config/deprecations.js +1 -1
  134. package/dist/unpkg/dev/build-config/env.js +3 -1
  135. package/dist/unpkg/dev/build-config/macros.js +3 -1
  136. package/dist/unpkg/dev/build-config.js +3 -1
  137. package/dist/unpkg/dev/configure.js +3 -1
  138. package/dist/unpkg/dev/graph/-private.js +1958 -2953
  139. package/dist/unpkg/dev/graph/-private.js.map +1 -0
  140. package/dist/unpkg/dev/index.js +3 -6
  141. package/dist/unpkg/dev/reactive/-private.js +3 -1
  142. package/dist/unpkg/dev/reactive.js +5 -3
  143. package/dist/unpkg/dev/request-CwjpJB3r.js +756 -0
  144. package/dist/unpkg/dev/request-CwjpJB3r.js.map +1 -0
  145. package/dist/unpkg/dev/request.js +2 -48
  146. package/dist/unpkg/dev/runtime-DoDtzXJb.js +110 -0
  147. package/dist/unpkg/dev/runtime-DoDtzXJb.js.map +1 -0
  148. package/dist/unpkg/dev/signals/-leaked.js +3 -1
  149. package/dist/unpkg/dev/src-CP6e_ozt.js +8331 -0
  150. package/dist/unpkg/dev/src-CP6e_ozt.js.map +1 -0
  151. package/dist/unpkg/dev/store/-private.js +3 -55
  152. package/dist/unpkg/dev/store-DamE3C4y.js +427 -0
  153. package/dist/unpkg/dev/store-DamE3C4y.js.map +1 -0
  154. package/dist/unpkg/dev/store.js +1 -556
  155. package/dist/unpkg/dev/types/-private.js +1 -67
  156. package/dist/unpkg/dev/types/identifier.js +63 -56
  157. package/dist/unpkg/dev/types/identifier.js.map +1 -0
  158. package/dist/unpkg/dev/types/record.js +211 -181
  159. package/dist/unpkg/dev/types/record.js.map +1 -0
  160. package/dist/unpkg/dev/types/request.js +138 -69
  161. package/dist/unpkg/dev/types/request.js.map +1 -0
  162. package/dist/unpkg/dev/types/runtime.js +54 -26
  163. package/dist/unpkg/dev/types/runtime.js.map +1 -0
  164. package/dist/unpkg/dev/types/schema/fields.js +501 -495
  165. package/dist/unpkg/dev/types/schema/fields.js.map +1 -0
  166. package/dist/unpkg/dev/types/schema/fields.type-test.js +79 -0
  167. package/dist/unpkg/dev/types/schema/fields.type-test.js.map +1 -0
  168. package/dist/unpkg/dev/types/symbols.js +84 -77
  169. package/dist/unpkg/dev/types/symbols.js.map +1 -0
  170. package/dist/unpkg/dev/utils/string.js +79 -85
  171. package/dist/unpkg/dev/utils/string.js.map +1 -0
  172. package/dist/unpkg/dev-deprecated/-private-BoSTJwp9.js +3519 -0
  173. package/dist/unpkg/dev-deprecated/-private-BoSTJwp9.js.map +1 -0
  174. package/dist/unpkg/dev-deprecated/-private-CUkeqUhO.js +22 -0
  175. package/dist/unpkg/dev-deprecated/-private-CUkeqUhO.js.map +1 -0
  176. package/dist/unpkg/dev-deprecated/-private-D6Tw25AD.js +111 -0
  177. package/dist/unpkg/dev-deprecated/-private-D6Tw25AD.js.map +1 -0
  178. package/dist/unpkg/dev-deprecated/build-config/babel-macros.js +3 -1
  179. package/dist/unpkg/dev-deprecated/build-config/canary-features.js +1 -1
  180. package/dist/unpkg/dev-deprecated/build-config/debugging.js +1 -1
  181. package/dist/unpkg/dev-deprecated/build-config/deprecations.js +1 -1
  182. package/dist/unpkg/dev-deprecated/build-config/env.js +3 -1
  183. package/dist/unpkg/dev-deprecated/build-config/macros.js +3 -1
  184. package/dist/unpkg/dev-deprecated/build-config.js +3 -1
  185. package/dist/unpkg/dev-deprecated/configure.js +3 -1
  186. package/dist/unpkg/dev-deprecated/graph/-private.js +2077 -3147
  187. package/dist/unpkg/dev-deprecated/graph/-private.js.map +1 -0
  188. package/dist/unpkg/dev-deprecated/index.js +3 -5
  189. package/dist/unpkg/dev-deprecated/reactive/-private.js +3 -1
  190. package/dist/unpkg/dev-deprecated/reactive.js +5 -3
  191. package/dist/unpkg/dev-deprecated/request-CwjpJB3r.js +756 -0
  192. package/dist/unpkg/dev-deprecated/request-CwjpJB3r.js.map +1 -0
  193. package/dist/unpkg/dev-deprecated/request.js +2 -48
  194. package/dist/unpkg/dev-deprecated/runtime-CPL2BGgT.js +110 -0
  195. package/dist/unpkg/dev-deprecated/runtime-CPL2BGgT.js.map +1 -0
  196. package/dist/unpkg/dev-deprecated/signals/-leaked.js +3 -1
  197. package/dist/unpkg/dev-deprecated/src-De8OV58h.js +8884 -0
  198. package/dist/unpkg/dev-deprecated/src-De8OV58h.js.map +1 -0
  199. package/dist/unpkg/dev-deprecated/store/-private.js +3 -1
  200. package/dist/unpkg/dev-deprecated/store-Bsdz5mRe.js +427 -0
  201. package/dist/unpkg/dev-deprecated/store-Bsdz5mRe.js.map +1 -0
  202. package/dist/unpkg/dev-deprecated/store.js +1 -556
  203. package/dist/unpkg/dev-deprecated/types/-private.js +1 -67
  204. package/dist/unpkg/dev-deprecated/types/identifier.js +63 -56
  205. package/dist/unpkg/dev-deprecated/types/identifier.js.map +1 -0
  206. package/dist/unpkg/dev-deprecated/types/record.js +211 -181
  207. package/dist/unpkg/dev-deprecated/types/record.js.map +1 -0
  208. package/dist/unpkg/dev-deprecated/types/request.js +138 -69
  209. package/dist/unpkg/dev-deprecated/types/request.js.map +1 -0
  210. package/dist/unpkg/dev-deprecated/types/runtime.js +54 -26
  211. package/dist/unpkg/dev-deprecated/types/runtime.js.map +1 -0
  212. package/dist/unpkg/dev-deprecated/types/schema/fields.js +501 -495
  213. package/dist/unpkg/dev-deprecated/types/schema/fields.js.map +1 -0
  214. package/dist/unpkg/dev-deprecated/types/schema/fields.type-test.js +79 -0
  215. package/dist/unpkg/dev-deprecated/types/schema/fields.type-test.js.map +1 -0
  216. package/dist/unpkg/dev-deprecated/types/symbols.js +84 -77
  217. package/dist/unpkg/dev-deprecated/types/symbols.js.map +1 -0
  218. package/dist/unpkg/dev-deprecated/utils/string.js +79 -85
  219. package/dist/unpkg/dev-deprecated/utils/string.js.map +1 -0
  220. package/dist/unpkg/prod/-private-B36B1ztP.js +22 -0
  221. package/dist/unpkg/prod/-private-B36B1ztP.js.map +1 -0
  222. package/dist/unpkg/prod/-private-DHco-h0q.js +3294 -0
  223. package/dist/unpkg/prod/-private-DHco-h0q.js.map +1 -0
  224. package/dist/unpkg/prod/-private-Dhl123OI.js +99 -0
  225. package/dist/unpkg/prod/-private-Dhl123OI.js.map +1 -0
  226. package/dist/unpkg/prod/build-config/babel-macros.js +3 -1
  227. package/dist/unpkg/prod/build-config/canary-features.js +1 -1
  228. package/dist/unpkg/prod/build-config/debugging.js +1 -1
  229. package/dist/unpkg/prod/build-config/deprecations.js +1 -1
  230. package/dist/unpkg/prod/build-config/env.js +3 -1
  231. package/dist/unpkg/prod/build-config/macros.js +3 -1
  232. package/dist/unpkg/prod/build-config.js +3 -1
  233. package/dist/unpkg/prod/configure.js +3 -2
  234. package/dist/unpkg/prod/graph/-private.js +1494 -2101
  235. package/dist/unpkg/prod/graph/-private.js.map +1 -0
  236. package/dist/unpkg/prod/index.js +2 -482
  237. package/dist/unpkg/prod/reactive/-private.js +3 -1
  238. package/dist/unpkg/prod/reactive.js +5 -30
  239. package/dist/unpkg/prod/request-BBdC1Sz7.js +480 -0
  240. package/dist/unpkg/prod/request-BBdC1Sz7.js.map +1 -0
  241. package/dist/unpkg/prod/request.js +3 -2
  242. package/dist/unpkg/prod/signals/-leaked.js +3 -1
  243. package/dist/unpkg/prod/src-nFHlZgKa.js +6942 -0
  244. package/dist/unpkg/prod/src-nFHlZgKa.js.map +1 -0
  245. package/dist/unpkg/prod/store/-private.js +3 -126
  246. package/dist/unpkg/prod/store-BWhmb7Ob.js +359 -0
  247. package/dist/unpkg/prod/store-BWhmb7Ob.js.map +1 -0
  248. package/dist/unpkg/prod/store.js +1 -435
  249. package/dist/unpkg/prod/types/-private.js +1 -47
  250. package/dist/unpkg/prod/types/identifier.js +63 -56
  251. package/dist/unpkg/prod/types/identifier.js.map +1 -0
  252. package/dist/unpkg/prod/types/record.js +211 -181
  253. package/dist/unpkg/prod/types/record.js.map +1 -0
  254. package/dist/unpkg/prod/types/request.js +138 -69
  255. package/dist/unpkg/prod/types/request.js.map +1 -0
  256. package/dist/unpkg/prod/types/runtime.js +54 -26
  257. package/dist/unpkg/prod/types/runtime.js.map +1 -0
  258. package/dist/unpkg/prod/types/schema/fields.js +501 -495
  259. package/dist/unpkg/prod/types/schema/fields.js.map +1 -0
  260. package/dist/unpkg/prod/types/schema/fields.type-test.js +79 -0
  261. package/dist/unpkg/prod/types/schema/fields.type-test.js.map +1 -0
  262. package/dist/unpkg/prod/types/symbols.js +84 -77
  263. package/dist/unpkg/prod/types/symbols.js.map +1 -0
  264. package/dist/unpkg/prod/utils/string.js +70 -66
  265. package/dist/unpkg/prod/utils/string.js.map +1 -0
  266. package/dist/unpkg/prod-deprecated/-private-B36B1ztP.js +22 -0
  267. package/dist/unpkg/prod-deprecated/-private-B36B1ztP.js.map +1 -0
  268. package/dist/unpkg/prod-deprecated/-private-DHco-h0q.js +3294 -0
  269. package/dist/unpkg/prod-deprecated/-private-DHco-h0q.js.map +1 -0
  270. package/dist/unpkg/prod-deprecated/-private-Dhl123OI.js +99 -0
  271. package/dist/unpkg/prod-deprecated/-private-Dhl123OI.js.map +1 -0
  272. package/dist/unpkg/prod-deprecated/build-config/babel-macros.js +3 -1
  273. package/dist/unpkg/prod-deprecated/build-config/canary-features.js +1 -1
  274. package/dist/unpkg/prod-deprecated/build-config/debugging.js +1 -1
  275. package/dist/unpkg/prod-deprecated/build-config/deprecations.js +1 -1
  276. package/dist/unpkg/prod-deprecated/build-config/env.js +3 -1
  277. package/dist/unpkg/prod-deprecated/build-config/macros.js +3 -1
  278. package/dist/unpkg/prod-deprecated/build-config.js +3 -1
  279. package/dist/unpkg/prod-deprecated/configure.js +3 -2
  280. package/dist/unpkg/prod-deprecated/graph/-private.js +1603 -2272
  281. package/dist/unpkg/prod-deprecated/graph/-private.js.map +1 -0
  282. package/dist/unpkg/prod-deprecated/index.js +2 -482
  283. package/dist/unpkg/prod-deprecated/reactive/-private.js +3 -1
  284. package/dist/unpkg/prod-deprecated/reactive.js +5 -5
  285. package/dist/unpkg/prod-deprecated/request-BBdC1Sz7.js +480 -0
  286. package/dist/unpkg/prod-deprecated/request-BBdC1Sz7.js.map +1 -0
  287. package/dist/unpkg/prod-deprecated/request.js +3 -2
  288. package/dist/unpkg/prod-deprecated/signals/-leaked.js +3 -1
  289. package/dist/unpkg/prod-deprecated/src-Cku5ymUJ.js +7375 -0
  290. package/dist/unpkg/prod-deprecated/src-Cku5ymUJ.js.map +1 -0
  291. package/dist/unpkg/prod-deprecated/store/-private.js +3 -88
  292. package/dist/unpkg/prod-deprecated/store-BWhmb7Ob.js +359 -0
  293. package/dist/unpkg/prod-deprecated/store-BWhmb7Ob.js.map +1 -0
  294. package/dist/unpkg/prod-deprecated/store.js +1 -435
  295. package/dist/unpkg/prod-deprecated/types/-private.js +1 -47
  296. package/dist/unpkg/prod-deprecated/types/identifier.js +63 -56
  297. package/dist/unpkg/prod-deprecated/types/identifier.js.map +1 -0
  298. package/dist/unpkg/prod-deprecated/types/record.js +211 -181
  299. package/dist/unpkg/prod-deprecated/types/record.js.map +1 -0
  300. package/dist/unpkg/prod-deprecated/types/request.js +138 -69
  301. package/dist/unpkg/prod-deprecated/types/request.js.map +1 -0
  302. package/dist/unpkg/prod-deprecated/types/runtime.js +54 -26
  303. package/dist/unpkg/prod-deprecated/types/runtime.js.map +1 -0
  304. package/dist/unpkg/prod-deprecated/types/schema/fields.js +501 -495
  305. package/dist/unpkg/prod-deprecated/types/schema/fields.js.map +1 -0
  306. package/dist/unpkg/prod-deprecated/types/schema/fields.type-test.js +79 -0
  307. package/dist/unpkg/prod-deprecated/types/schema/fields.type-test.js.map +1 -0
  308. package/dist/unpkg/prod-deprecated/types/symbols.js +84 -77
  309. package/dist/unpkg/prod-deprecated/types/symbols.js.map +1 -0
  310. package/dist/unpkg/prod-deprecated/utils/string.js +70 -66
  311. package/dist/unpkg/prod-deprecated/utils/string.js.map +1 -0
  312. package/dist/utils/string.d.ts +54 -0
  313. package/dist/utils/string.d.ts.map +1 -0
  314. package/dist/utils/string.js +84 -85
  315. package/dist/utils/string.js.map +1 -0
  316. package/dist/utils-BtURiy8l.d.ts +24 -0
  317. package/dist/utils-BtURiy8l.d.ts.map +1 -0
  318. package/package.json +17 -21
  319. package/declarations/build-config/babel-macros.d.ts +0 -1
  320. package/declarations/build-config/canary-features.d.ts +0 -1
  321. package/declarations/build-config/debugging.d.ts +0 -1
  322. package/declarations/build-config/deprecations.d.ts +0 -1
  323. package/declarations/build-config/env.d.ts +0 -1
  324. package/declarations/build-config/macros.d.ts +0 -1
  325. package/declarations/build-config.d.ts +0 -18
  326. package/declarations/configure.d.ts +0 -7
  327. package/declarations/graph/-private/-diff.d.ts +0 -19
  328. package/declarations/graph/-private/-edge-definition.d.ts +0 -149
  329. package/declarations/graph/-private/-state.d.ts +0 -9
  330. package/declarations/graph/-private/-utils.d.ts +0 -25
  331. package/declarations/graph/-private/coerce-id.d.ts +0 -4
  332. package/declarations/graph/-private/debug/assert-polymorphic-type.d.ts +0 -6
  333. package/declarations/graph/-private/edges/collection.d.ts +0 -39
  334. package/declarations/graph/-private/edges/implicit.d.ts +0 -43
  335. package/declarations/graph/-private/edges/resource.d.ts +0 -23
  336. package/declarations/graph/-private/graph.d.ts +0 -56
  337. package/declarations/graph/-private/normalize-link.d.ts +0 -2
  338. package/declarations/graph/-private/operations/add-to-related-records.d.ts +0 -4
  339. package/declarations/graph/-private/operations/merge-identifier.d.ts +0 -3
  340. package/declarations/graph/-private/operations/remove-from-related-records.d.ts +0 -4
  341. package/declarations/graph/-private/operations/replace-related-record.d.ts +0 -3
  342. package/declarations/graph/-private/operations/replace-related-records.d.ts +0 -7
  343. package/declarations/graph/-private/operations/update-relationship.d.ts +0 -9
  344. package/declarations/graph/-private.d.ts +0 -13
  345. package/declarations/index.d.ts +0 -96
  346. package/declarations/reactive/-private/default-mode.d.ts +0 -73
  347. package/declarations/reactive/-private/document.d.ts +0 -142
  348. package/declarations/reactive/-private/fields/extension.d.ts +0 -8
  349. package/declarations/reactive/-private/fields/get-field-key.d.ts +0 -8
  350. package/declarations/reactive/-private/fields/managed-array.d.ts +0 -18
  351. package/declarations/reactive/-private/fields/managed-object.d.ts +0 -17
  352. package/declarations/reactive/-private/fields/many-array-manager.d.ts +0 -19
  353. package/declarations/reactive/-private/hooks.d.ts +0 -5
  354. package/declarations/reactive/-private/kind/alias-field.d.ts +0 -4
  355. package/declarations/reactive/-private/kind/array-field.d.ts +0 -4
  356. package/declarations/reactive/-private/kind/attribute-field.d.ts +0 -4
  357. package/declarations/reactive/-private/kind/belongs-to-field.d.ts +0 -4
  358. package/declarations/reactive/-private/kind/collection-field.d.ts +0 -4
  359. package/declarations/reactive/-private/kind/derived-field.d.ts +0 -4
  360. package/declarations/reactive/-private/kind/generic-field.d.ts +0 -4
  361. package/declarations/reactive/-private/kind/has-many-field.d.ts +0 -4
  362. package/declarations/reactive/-private/kind/hash-field.d.ts +0 -4
  363. package/declarations/reactive/-private/kind/identity-field.d.ts +0 -4
  364. package/declarations/reactive/-private/kind/local-field.d.ts +0 -4
  365. package/declarations/reactive/-private/kind/object-field.d.ts +0 -4
  366. package/declarations/reactive/-private/kind/resource-field.d.ts +0 -4
  367. package/declarations/reactive/-private/kind/schema-array-field.d.ts +0 -4
  368. package/declarations/reactive/-private/kind/schema-object-field.d.ts +0 -4
  369. package/declarations/reactive/-private/record.d.ts +0 -83
  370. package/declarations/reactive/-private/schema.d.ts +0 -326
  371. package/declarations/reactive/-private/symbols.d.ts +0 -5
  372. package/declarations/reactive/-private.d.ts +0 -2
  373. package/declarations/reactive.d.ts +0 -286
  374. package/declarations/request/-private/context.d.ts +0 -39
  375. package/declarations/request/-private/debug.d.ts +0 -4
  376. package/declarations/request/-private/fetch.d.ts +0 -33
  377. package/declarations/request/-private/future.d.ts +0 -7
  378. package/declarations/request/-private/manager.d.ts +0 -158
  379. package/declarations/request/-private/promise-cache.d.ts +0 -28
  380. package/declarations/request/-private/types.d.ts +0 -234
  381. package/declarations/request/-private/utils.d.ts +0 -57
  382. package/declarations/request.d.ts +0 -52
  383. package/declarations/signals/-leaked.d.ts +0 -2
  384. package/declarations/signals/-private.d.ts +0 -6
  385. package/declarations/signals/promise-state.d.ts +0 -264
  386. package/declarations/signals/reactivity/configure.d.ts +0 -138
  387. package/declarations/signals/reactivity/internal.d.ts +0 -154
  388. package/declarations/signals/reactivity/signal.d.ts +0 -56
  389. package/declarations/signals/request-state.d.ts +0 -372
  390. package/declarations/signals/request-subscription.d.ts +0 -177
  391. package/declarations/store/-private/cache-handler/handler.d.ts +0 -56
  392. package/declarations/store/-private/cache-handler/types.d.ts +0 -84
  393. package/declarations/store/-private/cache-handler/utils.d.ts +0 -31
  394. package/declarations/store/-private/caches/instance-cache.d.ts +0 -58
  395. package/declarations/store/-private/caches/resource-utils.d.ts +0 -9
  396. package/declarations/store/-private/debug/utils.d.ts +0 -7
  397. package/declarations/store/-private/default-cache-policy.d.ts +0 -387
  398. package/declarations/store/-private/managers/cache-capabilities-manager.d.ts +0 -34
  399. package/declarations/store/-private/managers/cache-key-manager.d.ts +0 -304
  400. package/declarations/store/-private/managers/cache-manager.d.ts +0 -367
  401. package/declarations/store/-private/managers/notification-manager.d.ts +0 -83
  402. package/declarations/store/-private/managers/record-array-manager.d.ts +0 -100
  403. package/declarations/store/-private/network/request-cache.d.ts +0 -103
  404. package/declarations/store/-private/record-arrays/-utils.d.ts +0 -80
  405. package/declarations/store/-private/record-arrays/legacy-live-array.d.ts +0 -81
  406. package/declarations/store/-private/record-arrays/legacy-many-array.d.ts +0 -133
  407. package/declarations/store/-private/record-arrays/legacy-query.d.ts +0 -81
  408. package/declarations/store/-private/record-arrays/native-proxy-type-fix.d.ts +0 -3
  409. package/declarations/store/-private/record-arrays/resource-array.d.ts +0 -67
  410. package/declarations/store/-private/store-service.d.ts +0 -874
  411. package/declarations/store/-private/utils/coerce-id.d.ts +0 -4
  412. package/declarations/store/-private/utils/construct-resource.d.ts +0 -6
  413. package/declarations/store/-private/utils/is-non-empty-string.d.ts +0 -1
  414. package/declarations/store/-private/utils/normalize-model-name.d.ts +0 -1
  415. package/declarations/store/-private/utils/uuid-polyfill.d.ts +0 -1
  416. package/declarations/store/-private.d.ts +0 -24
  417. package/declarations/store/-types/q/cache-capabilities-manager.d.ts +0 -90
  418. package/declarations/store/-types/q/identifier.d.ts +0 -23
  419. package/declarations/store/-types/q/record-instance.d.ts +0 -22
  420. package/declarations/store/-types/q/store.d.ts +0 -31
  421. package/declarations/store/deprecated/-private.d.ts +0 -223
  422. package/declarations/store/deprecated/store.d.ts +0 -784
  423. package/declarations/store.d.ts +0 -2
  424. package/declarations/types/-private.d.ts +0 -22
  425. package/declarations/types/cache/aliases.d.ts +0 -1
  426. package/declarations/types/cache/change.d.ts +0 -6
  427. package/declarations/types/cache/mutations.d.ts +0 -38
  428. package/declarations/types/cache/operations.d.ts +0 -168
  429. package/declarations/types/cache/relationship.d.ts +0 -13
  430. package/declarations/types/cache.d.ts +0 -429
  431. package/declarations/types/graph.d.ts +0 -47
  432. package/declarations/types/identifier.d.ts +0 -86
  433. package/declarations/types/json/raw.d.ts +0 -6
  434. package/declarations/types/params.d.ts +0 -8
  435. package/declarations/types/record.d.ts +0 -269
  436. package/declarations/types/request.d.ts +0 -367
  437. package/declarations/types/runtime.d.ts +0 -14
  438. package/declarations/types/schema/concepts.d.ts +0 -23
  439. package/declarations/types/schema/fields.d.ts +0 -2200
  440. package/declarations/types/schema/fields.type-test.d.ts +0 -1
  441. package/declarations/types/schema/schema-service.d.ts +0 -380
  442. package/declarations/types/spec/document.d.ts +0 -67
  443. package/declarations/types/spec/error.d.ts +0 -18
  444. package/declarations/types/spec/json-api-raw.d.ts +0 -139
  445. package/declarations/types/symbols.d.ts +0 -78
  446. package/declarations/types/utils.d.ts +0 -5
  447. package/declarations/types.d.ts +0 -11
  448. package/declarations/utils/string.d.ts +0 -47
  449. package/dist/configure-DPUFCemT.js +0 -1940
  450. package/dist/default-cache-policy-D7_u4YRH.js +0 -572
  451. package/dist/future-BKkJJkj7.js +0 -678
  452. package/dist/index-CQP2NSqg.js +0 -9982
  453. package/dist/symbols-3C1OkYtZ.js +0 -39
  454. package/dist/unpkg/dev/-leaked-Co0EI6Go.js +0 -1939
  455. package/dist/unpkg/dev/-private-sql1_mdx.js +0 -39
  456. package/dist/unpkg/dev/future-DFfOzSoe.js +0 -672
  457. package/dist/unpkg/dev/index-BzcBOnw9.js +0 -9392
  458. package/dist/unpkg/dev/runtime-E1M51_-O.js +0 -135
  459. package/dist/unpkg/dev-deprecated/-leaked-DjMeRqdU.js +0 -1939
  460. package/dist/unpkg/dev-deprecated/-private-3C1OkYtZ.js +0 -39
  461. package/dist/unpkg/dev-deprecated/future-DFfOzSoe.js +0 -672
  462. package/dist/unpkg/dev-deprecated/index-6TnTv-WG.js +0 -10007
  463. package/dist/unpkg/dev-deprecated/runtime-DAu5b0IR.js +0 -135
  464. package/dist/unpkg/prod/-leaked-DUONXQDB.js +0 -1676
  465. package/dist/unpkg/prod/-private-sql1_mdx.js +0 -39
  466. package/dist/unpkg/prod/handler-EU_8ncB2.js +0 -1619
  467. package/dist/unpkg/prod/promise-cache-DIT8Ypjq.js +0 -19
  468. package/dist/unpkg/prod/request-BrJSCG6r.js +0 -421
  469. package/dist/unpkg/prod/schema-BSkHyoWz.js +0 -5219
  470. package/dist/unpkg/prod-deprecated/-leaked-DRNv9VIX.js +0 -1676
  471. package/dist/unpkg/prod-deprecated/-private-3C1OkYtZ.js +0 -39
  472. package/dist/unpkg/prod-deprecated/handler-CCIu4sQ3.js +0 -334
  473. package/dist/unpkg/prod-deprecated/hooks-Dv4Np0MY.js +0 -26
  474. package/dist/unpkg/prod-deprecated/promise-cache-DIT8Ypjq.js +0 -19
  475. package/dist/unpkg/prod-deprecated/request-BrJSCG6r.js +0 -421
  476. package/dist/unpkg/prod-deprecated/schema-CJcjHv0E.js +0 -6939
@@ -0,0 +1,3530 @@
1
+ import { a as setTransient, r as peekTransient, t as getOrSetGlobal } from "./-private-CyhhcK1a.js";
2
+ import { f as setPromiseResult, o as DOMError, u as getPromiseResult } from "./request-7BJFgSu_.js";
3
+ import { getGlobalConfig, macroCondition } from "@embroider/macros";
4
+
5
+ //#region src/signals/reactivity/configure.ts
6
+ const ARRAY_SIGNAL = getOrSetGlobal("#[]", Symbol("#[]"));
7
+ const OBJECT_SIGNAL = getOrSetGlobal("#{}", Symbol("#{}"));
8
+ /**
9
+ * An Opaque type that represents a framework specific or TC39 signal.
10
+ *
11
+ * It may be an array of signals or a single signal.
12
+ *
13
+ * @private
14
+ */
15
+ /**
16
+ * The hooks which MUST be configured in order to use reactive arrays,
17
+ * resources and documents with framework specfic signals or TC39 signals.
18
+ *
19
+ * Support for multiple frameworks simultaneously can be done via
20
+ * this abstraction by returning multiple signals from the `createSignal`
21
+ * method, and consuming the correct one via the correct framework via
22
+ * the `consumeSignal` and `notifySignal` methods.
23
+ *
24
+ * Unlike many signals implementations, WarpDrive does not wrap values as
25
+ * signals directly, but instead uses signals to alert the reactive layer
26
+ * to changes in the underlying cache. E.g. a signal is associated to a value,
27
+ * but does not serve as the cache for that value directly. We refer to this as
28
+ * a "gate", the pattern has also been called "side-signals".
29
+ *
30
+ * A no-op implementation is allowed, though it may lead to performance issues
31
+ * in locations that use createMemo as no memoization would be done. This is
32
+ * typically desirable only when integrating with a framework that does its own
33
+ * memoization and does not integrate with any signals-like primitive. For these
34
+ * scenarios you may also be interested in integrating with the {@link NotificationManager}
35
+ * more directly.
36
+ *
37
+ * @public
38
+ */
39
+ /**
40
+ * Contains information a {@link SignalHooks} implementation may want
41
+ * to use, such as the specialized key used for the signal
42
+ * representing an array's contents / length.
43
+ *
44
+ * ```ts
45
+ * interface HooksOptions {
46
+ * wellknown: {
47
+ * Array: symbol | string;
48
+ * }
49
+ * }
50
+ * ```
51
+ *
52
+ * @public
53
+ */
54
+ /**
55
+ * Configures the signals implementation to use. Supports multiple
56
+ * implementations simultaneously.
57
+ *
58
+ * See {@link HooksOptions} for the options passed to the provided function
59
+ * when called.
60
+ *
61
+ * See {@link SignalHooks} for the implementation the callback function should
62
+ * return.
63
+ *
64
+ * @public
65
+ * @param buildConfig - a function that takes options and returns a configuration object
66
+ */
67
+ function setupSignals(buildConfig) {
68
+ const hooks = buildConfig({ wellknown: { Array: ARRAY_SIGNAL } });
69
+ setTransient("signalHooks", hooks);
70
+ }
71
+ /**
72
+ * Internal method for consuming the configured `createSignal` hook
73
+ *
74
+ * @private
75
+ */
76
+ function createSignal(obj, key) {
77
+ const signalHooks = peekTransient("signalHooks");
78
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
79
+ if (!test) throw new Error(`Signal hooks not configured`);
80
+ })(signalHooks);
81
+ return signalHooks.createSignal(obj, key);
82
+ }
83
+ /**
84
+ * Internal method for consuming the configured `consumeSignal` hook
85
+ *
86
+ * @private
87
+ */
88
+ function consumeSignal(signal) {
89
+ const signalHooks = peekTransient("signalHooks");
90
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
91
+ if (!test) throw new Error(`Signal hooks not configured`);
92
+ })(signalHooks);
93
+ return signalHooks.consumeSignal(signal);
94
+ }
95
+ /**
96
+ * Internal method for consuming the configured `notifySignal` hook
97
+ *
98
+ * @private
99
+ */
100
+ function notifySignal(signal) {
101
+ const signalHooks = peekTransient("signalHooks");
102
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
103
+ if (!test) throw new Error(`Signal hooks not configured`);
104
+ })(signalHooks);
105
+ return signalHooks.notifySignal(signal);
106
+ }
107
+ function createMemo(object, key, fn) {
108
+ const signalHooks = peekTransient("signalHooks");
109
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
110
+ if (!test) throw new Error(`Signal hooks not configured`);
111
+ })(signalHooks);
112
+ return signalHooks.createMemo(object, key, fn);
113
+ }
114
+ function willSyncFlushWatchers() {
115
+ const signalHooks = peekTransient("signalHooks");
116
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
117
+ if (!test) throw new Error(`Signal hooks not configured`);
118
+ })(signalHooks);
119
+ return signalHooks.willSyncFlushWatchers();
120
+ }
121
+ /**
122
+ * Wraps `promise` using the configured {@link SignalHooks.waitFor}, if any,
123
+ * for things like test-waiters. Returns `promise` unchanged if no
124
+ * `waitFor` hook is configured.
125
+ */
126
+ function waitFor(promise) {
127
+ const signalHooks = peekTransient("signalHooks");
128
+ if (signalHooks?.waitFor) return signalHooks.waitFor(promise);
129
+ return promise;
130
+ }
131
+
132
+ //#endregion
133
+ //#region src/signals/reactivity/internal.ts
134
+ const INITIALIZER_PROTO = { isInitializer: true };
135
+ /**
136
+ * Wraps `fn` so that a signal can recognize it as a lazy initializer
137
+ * for its value rather than the value itself, deferring the call to
138
+ * `fn` until the signal is first accessed.
139
+ */
140
+ function makeInitializer(fn) {
141
+ return Object.assign(Object.create(INITIALIZER_PROTO), { value: fn });
142
+ }
143
+ function isInitializer(obj) {
144
+ return typeof obj === "object" && obj !== null && Object.getPrototypeOf(obj) === INITIALIZER_PROTO;
145
+ }
146
+ /**
147
+ * A WarpDriveSignal is a wrapper around a framework specific or TC39 signal
148
+ * that enables us to store and manage the signal in a universal way.
149
+ *
150
+ * WarpDrive uses signals to manage three separate concepts:
151
+ *
152
+ * - as a `storage` for a value local to the object that we want to be reactive
153
+ * (see `@local` schema field for an example)
154
+ * - as a `gate` for a memoized getter that we want to act as a reactive property
155
+ * but whose value is computed/pulled from a non-reactive source elsewhere
156
+ * and whose latest value is stored in the signal
157
+ * (see `field` schema field for an example)
158
+ * - as a `gate` with a manually managed value updated on pull when `isStale` is true
159
+ *
160
+ *
161
+ * It offers
162
+ *
163
+ * - a non-reactive way to access/update the current value
164
+ * - a non-reactive way to mark the signal as dirtied
165
+ * - a non-reactive way to store content for why the signal was dirtied
166
+ * - access to the underlying Signal(s) in-use
167
+ *
168
+ * For debugging:
169
+ * - the "key" or "name" of the signal
170
+ * - the "object identity" or "context" to which the signal is attached
171
+ *
172
+ * @private
173
+ */
174
+ /**
175
+ * We attach signals to their context object via
176
+ * a Map attached to the object via this symbol.
177
+ *
178
+ * This allows us to store multiple signals
179
+ * on the same object with smaller memory
180
+ * overhead and no WeakMap lookups.
181
+ *
182
+ * Performance sensitive objects should
183
+ * pre-warm their shape by assigning this
184
+ * during initialization.
185
+ *
186
+ * ```ts
187
+ * initializeSignalStore(obj);
188
+ * ```
189
+ *
190
+ * @private
191
+ */
192
+ const Signals = getOrSetGlobal("Signals", Symbol("Signals"));
193
+ /**
194
+ * A type util to recast the object as having a signal store.
195
+ *
196
+ * @private
197
+ */
198
+ function upgradeWithSignals(obj) {}
199
+ /**
200
+ * A util that will create a signal store on the object
201
+ * if it does not already exist and returns the associated
202
+ * signal store.
203
+ *
204
+ * @private
205
+ */
206
+ function withSignalStore(obj) {
207
+ /* @__PURE__ */ upgradeWithSignals(obj);
208
+ if (!obj[Signals]) initializeSignalStore(obj);
209
+ return obj[Signals];
210
+ }
211
+ /**
212
+ * A util that will create a signal store on the object
213
+ * if it does not already exist.
214
+ *
215
+ * Useful for pre-warming the shape of an object to ensure
216
+ * a key-transition to add it is not required later.
217
+ *
218
+ * @private
219
+ */
220
+ function initializeSignalStore(obj) {
221
+ /* @__PURE__ */ upgradeWithSignals(obj);
222
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
223
+ if (!test) throw new Error(`Signal store already exists on object`);
224
+ })(!obj[Signals]);
225
+ obj[Signals] = /* @__PURE__ */ new Map();
226
+ }
227
+ function createInternalSignal(signals, obj, key, initialValue) {
228
+ const warpDriveSignal = {
229
+ key,
230
+ context: obj,
231
+ signal: createSignal(obj, key),
232
+ value: isInitializer(initialValue) ? initialValue.value.call(obj) : initialValue,
233
+ isStale: false
234
+ };
235
+ signals.set(key, warpDriveSignal);
236
+ return warpDriveSignal;
237
+ }
238
+ function getOrCreateInternalSignal(signals, obj, key, initialValue) {
239
+ let signal = peekInternalSignal(signals, key);
240
+ if (!signal) signal = createInternalSignal(signals, obj, key, initialValue);
241
+ return signal;
242
+ }
243
+ function createInternalMemo(signals, object, key, fn) {
244
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
245
+ if (!test) throw new Error(`Expected no signal/memo to exist for key "${String(key)}"`);
246
+ })(!peekInternalSignal(signals, key));
247
+ if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) return withFrame(signals, object, key, fn);
248
+ else {
249
+ const memo = createMemo(object, key, fn);
250
+ signals.set(key, memo);
251
+ return memo;
252
+ }
253
+ }
254
+ /**
255
+ * Looks up the {@link WarpDriveSignal} stored for `key` in `signals`,
256
+ * if one has already been created, without creating or consuming it.
257
+ */
258
+ function peekInternalSignal(signals, key) {
259
+ return signals?.get(key);
260
+ }
261
+ function consumeInternalSignal(signal) {
262
+ TrackingFrame?.signals.add(signal);
263
+ consumeSignal(signal.signal);
264
+ }
265
+ /**
266
+ * Marks `signal` as stale and notifies its underlying framework/TC39
267
+ * signal, scheduling any of its consumers for re-render/re-computation.
268
+ */
269
+ function notifyInternalSignal(signal) {
270
+ if (signal) {
271
+ signal.isStale = true;
272
+ notifySignal(signal.signal);
273
+ }
274
+ }
275
+ let TrackingFrame = null;
276
+ /**
277
+ * This is currently just for signals debugging, but it could be used in production
278
+ * if we wanted to eliminate the need for frameworks to implement createMemo / to
279
+ * allow us to add our own Watcher.
280
+ *
281
+ * @internal
282
+ */
283
+ function withFrame(signals, object, key, fn) {
284
+ const frameSignals = /* @__PURE__ */ new Set();
285
+ const frameFn = () => {
286
+ if (frameSignals.size) frameSignals.clear();
287
+ TrackingFrame = {
288
+ object,
289
+ key,
290
+ signals: frameSignals,
291
+ parent: TrackingFrame
292
+ };
293
+ try {
294
+ return fn();
295
+ } finally {
296
+ TrackingFrame = TrackingFrame.parent;
297
+ }
298
+ };
299
+ const memo = createMemo(object, key, frameFn);
300
+ memo.signals = frameSignals;
301
+ signals.set(key, memo);
302
+ return memo;
303
+ }
304
+ function isMemo(obj) {
305
+ return typeof obj === "function" && obj.signals instanceof Set;
306
+ }
307
+ if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) globalThis.debugWarpDriveSignals = (obj, key) => {
308
+ /* @__PURE__ */ upgradeWithSignals(obj);
309
+ const signals = obj[Signals];
310
+ if (!signals) {
311
+ log("The object has no associated signals");
312
+ return false;
313
+ }
314
+ if (key) {
315
+ const signal = signals.get(key);
316
+ if (!signal) {
317
+ log(`No signal found for key "${String(key)}"`);
318
+ return false;
319
+ }
320
+ log(signal);
321
+ if (isMemo(signal)) {
322
+ colorizeLines(printMemo(signal, key));
323
+ return true;
324
+ } else {
325
+ colorizeLines(printSignal(signal, key));
326
+ return true;
327
+ }
328
+ }
329
+ const lines = [];
330
+ for (const [k, signal] of signals) {
331
+ if (isMemo(signal)) continue;
332
+ printSignal(signal, k, lines);
333
+ }
334
+ for (const [k, signal] of signals) if (isMemo(signal)) printMemo(signal, k, lines);
335
+ log(signals);
336
+ colorizeLines(lines);
337
+ return true;
338
+ };
339
+ const LightColors = {
340
+ red: "color: red;",
341
+ green: "color: green;",
342
+ reset: "color: inherit;"
343
+ };
344
+ const DarkColors = {
345
+ red: "color: red;",
346
+ green: "color: lightgreen;",
347
+ reset: "color: inherit;"
348
+ };
349
+ function isLightMode() {
350
+ if (window?.matchMedia?.("(prefers-color-scheme: light)").matches) return true;
351
+ return false;
352
+ }
353
+ const RED = {};
354
+ const GREEN = {};
355
+ const RESET = {};
356
+ const EOL = {};
357
+ function colorizeLines(lines) {
358
+ const Colors = isLightMode() ? LightColors : DarkColors;
359
+ const colors = [];
360
+ let line = "";
361
+ for (const str of lines) if (str === RED) {
362
+ colors.push(Colors.red);
363
+ line += "%c";
364
+ } else if (str === GREEN) {
365
+ colors.push(Colors.green);
366
+ line += "%c";
367
+ } else if (str === RESET) {
368
+ colors.push(Colors.reset);
369
+ line += "%c";
370
+ } else if (str === EOL) line += "\n";
371
+ else line += str;
372
+ log(line, ...colors);
373
+ }
374
+ function log(...args) {
375
+ console.log(...args);
376
+ }
377
+ function isDirty(signal) {
378
+ return signal.isStale;
379
+ }
380
+ function isDirtyMemo(memo) {
381
+ for (const signal of memo.signals) {
382
+ if (isMemo(signal)) continue;
383
+ if (isDirty(signal)) return true;
384
+ }
385
+ for (const signal of memo.signals) if (isMemo(signal)) return isDirtyMemo(signal);
386
+ return false;
387
+ }
388
+ function printSignal(signal, key, lines = [], depth = 0) {
389
+ const _dirty = isDirty(signal);
390
+ lines.push(`${"".padStart(depth * 2, " ")}${_dirty ? "❌" : "✅"} `, _dirty ? RED : GREEN, `${String(key)}`, RESET, EOL);
391
+ return lines;
392
+ }
393
+ function printMemo(memo, key, lines = [], depth = 0) {
394
+ const _dirty = isDirtyMemo(memo);
395
+ lines.push(`${"".padStart(depth * 2, " ")}${_dirty ? "❌" : "✅"} `, _dirty ? RED : GREEN, `<memo> ${String(key)}`, RESET, `: (consumes ${memo.signals.size} signals)`, EOL);
396
+ for (const signal of memo.signals) {
397
+ if (isMemo(signal)) continue;
398
+ printSignal(signal, signal.key, lines, depth + 1);
399
+ }
400
+ for (const signal of memo.signals) if (isMemo(signal)) printMemo(signal, signal.key, lines, depth + 1);
401
+ return lines;
402
+ }
403
+
404
+ //#endregion
405
+ //#region src/signals/reactivity/signal.ts
406
+ /**
407
+ * Creates a signal for the key/object pairing and subscribes to the signal.
408
+ *
409
+ * Use when you need to ensure a signal exists and is subscribed to.
410
+ *
411
+ * @private
412
+ */
413
+ function entangleSignal(signals, obj, key, initialValue) {
414
+ let internalSignal = peekInternalSignal(signals, key);
415
+ if (!internalSignal) internalSignal = createInternalSignal(signals, obj, key, initialValue);
416
+ consumeInternalSignal(internalSignal);
417
+ return internalSignal;
418
+ }
419
+ function entangleInitiallyStaleSignal(signals, obj, key, initialValue) {
420
+ let internalSignal = peekInternalSignal(signals, key);
421
+ if (!internalSignal) {
422
+ internalSignal = createInternalSignal(signals, obj, key, initialValue);
423
+ internalSignal.isStale = true;
424
+ }
425
+ consumeInternalSignal(internalSignal);
426
+ return internalSignal;
427
+ }
428
+ function createSignalDescriptor(key, intialValue) {
429
+ return {
430
+ enumerable: true,
431
+ configurable: false,
432
+ get() {
433
+ const internalSignal = entangleSignal(withSignalStore(this), this, key, intialValue);
434
+ internalSignal.isStale = false;
435
+ return internalSignal.value;
436
+ },
437
+ set(value) {
438
+ const signals = withSignalStore(this);
439
+ const internalSignal = getOrCreateInternalSignal(signals, this, key, intialValue);
440
+ if (internalSignal.value !== value) {
441
+ internalSignal.value = value;
442
+ notifyInternalSignal(internalSignal);
443
+ }
444
+ }
445
+ };
446
+ }
447
+ /**
448
+ * define an enumerable signal property.
449
+ *
450
+ * Akin to Object.defineProperty.
451
+ *
452
+ * The signal will be lazily created when accessed and scoped to the
453
+ * instance of the object.
454
+ *
455
+ * @private
456
+ */
457
+ function defineSignal(obj, key, v) {
458
+ Object.defineProperty(obj, key, createSignalDescriptor(key, v));
459
+ }
460
+ /**
461
+ * Define a non-enumerable signal property.
462
+ *
463
+ * @private
464
+ */
465
+ function defineNonEnumerableSignal(obj, key, v) {
466
+ const desc = createSignalDescriptor(key, v);
467
+ desc.enumerable = false;
468
+ Object.defineProperty(obj, key, desc);
469
+ }
470
+ /**
471
+ * Decorator version of creating a signal.
472
+ */
473
+ function signal(target, key, descriptor) {
474
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
475
+ if (!test) throw new Error("You attempted to use @signal(), which is not necessary nor supported. Remove the parentheses and you will be good to go!");
476
+ })(target !== void 0);
477
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
478
+ if (!test) throw new Error(`You attempted to use @signal on with ${arguments.length > 1 ? "arguments" : "an argument"} ( @signal(${Array.from(arguments).map((d) => `'${d}'`).join(", ")}) ), which is not supported. Dependencies are automatically tracked, so you can just use \`@signal\``);
479
+ })(typeof target === "object" && typeof key === "string" && typeof descriptor === "object" && arguments.length === 3);
480
+ return createSignalDescriptor(key, descriptor.initializer ? makeInitializer(descriptor.initializer) : null);
481
+ }
482
+ /**
483
+ * Decorator version of creating a memoized getter
484
+ */
485
+ function memoized(target, key, descriptor) {
486
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
487
+ if (!test) throw new Error("You attempted to use @memoized(), which is not necessary nor supported. Remove the parentheses and you will be good to go!");
488
+ })(target !== void 0);
489
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
490
+ if (!test) throw new Error(`You attempted to use @memoized on with ${arguments.length > 1 ? "arguments" : "an argument"} ( @memoized(${Array.from(arguments).map((d) => `'${d}'`).join(", ")}), which is not supported. Dependencies are automatically tracked, so you can just use \`@memoized\``);
491
+ })(typeof target === "object" && typeof key === "string" && typeof descriptor === "object" && arguments.length === 3);
492
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
493
+ if (!test) throw new Error(`The @memoized decorator must be applied to getters. '${key}' is not a getter.`);
494
+ })(typeof descriptor.get === "function");
495
+ const getter = descriptor.get;
496
+ descriptor.get = function() {
497
+ const signals = withSignalStore(this);
498
+ let memoSignal = signals.get(key);
499
+ if (!memoSignal) memoSignal = createInternalMemo(signals, this, key, getter.bind(this));
500
+ return memoSignal();
501
+ };
502
+ return descriptor;
503
+ }
504
+ /**
505
+ * Decorator version of creating a gate.
506
+ *
507
+ * @private
508
+ */
509
+ function gate(_target, key, desc) {
510
+ const getter = desc.get;
511
+ const setter = desc.set;
512
+ const isLocal = desc.isLocal;
513
+ desc.get = function() {
514
+ const signals = withSignalStore(this);
515
+ let internalSignal = peekInternalSignal(signals, key);
516
+ if (!internalSignal) internalSignal = createInternalSignal(signals, this, key, getter.call(this));
517
+ else if (internalSignal.isStale) {
518
+ internalSignal.isStale = false;
519
+ internalSignal.value = getter.call(this);
520
+ }
521
+ consumeInternalSignal(internalSignal);
522
+ return internalSignal.value;
523
+ };
524
+ if (setter) desc.set = function(v) {
525
+ const signals = withSignalStore(this);
526
+ let internalSignal = peekInternalSignal(signals, key);
527
+ if (!internalSignal) {
528
+ internalSignal = createInternalSignal(signals, this, key, void 0);
529
+ internalSignal.isStale = true;
530
+ }
531
+ setter.call(this, v);
532
+ if (isLocal) {
533
+ internalSignal.isStale = true;
534
+ notifyInternalSignal(internalSignal);
535
+ }
536
+ };
537
+ return desc;
538
+ }
539
+ /**
540
+ * Defines a reactive "gated" property on `obj` using `desc` as its
541
+ * getter/setter descriptor.
542
+ *
543
+ * Unlike a signal defined with {@link defineSignal}, a gated property's
544
+ * consumers are not notified when the property is set, since its update
545
+ * is expected to be controlled externally (for instance, by a signal it
546
+ * derives its value from) unless the descriptor opts into being locally
547
+ * managed.
548
+ *
549
+ * Akin to `Object.defineProperty`.
550
+ *
551
+ * @private
552
+ */
553
+ function defineGate(obj, key, desc) {
554
+ const options = Object.assign({
555
+ enumerable: true,
556
+ configurable: false
557
+ }, gate(obj, key, desc));
558
+ Object.defineProperty(obj, key, options);
559
+ }
560
+
561
+ //#endregion
562
+ //#region src/signals/request-state.ts
563
+ const RequestCache = /* @__PURE__ */ new WeakMap();
564
+ function isAbortError(error) {
565
+ return error instanceof DOMError && error.name === "AbortError";
566
+ }
567
+ function upgradeLoadingState(state) {
568
+ return state;
569
+ }
570
+ async function watchStream(stream, loadingState) {
571
+ const state = upgradeLoadingState(loadingState);
572
+ const reader = stream.getReader();
573
+ let bytesLoaded = 0;
574
+ let shouldForward = state._stream !== null && state._stream.readable.locked;
575
+ let isForwarding = shouldForward;
576
+ let writer = state._stream?.writable.getWriter();
577
+ const buffer = [];
578
+ state._isPending = false;
579
+ state._isStarted = true;
580
+ state._startTime = performance.now();
581
+ while (true) {
582
+ const { value, done } = await reader.read();
583
+ if (done) break;
584
+ bytesLoaded += value.byteLength;
585
+ state._bytesLoaded = bytesLoaded;
586
+ state._lastPacketTime = performance.now();
587
+ shouldForward = shouldForward || state._stream !== null && state._stream.readable.locked;
588
+ if (shouldForward) {
589
+ if (!isForwarding) {
590
+ isForwarding = true;
591
+ writer = state._stream.writable.getWriter();
592
+ for (const item of buffer) {
593
+ await writer.ready;
594
+ await writer.write(item);
595
+ }
596
+ buffer.length = 0;
597
+ }
598
+ await writer.ready;
599
+ await writer.write(value);
600
+ } else buffer.push(value);
601
+ }
602
+ if (isForwarding) {
603
+ await writer.ready;
604
+ await writer.close();
605
+ } else if (state._stream) {
606
+ await state._stream.readable.cancel("The Stream Has Already Ended");
607
+ state._stream = null;
608
+ }
609
+ state._endTime = performance.now();
610
+ state._isComplete = true;
611
+ state._isStarted = false;
612
+ }
613
+ /**
614
+ * Lazily consumes the stream of a request, providing a number of
615
+ * reactive properties that can be used to build UIs that respond
616
+ * to the progress of a request.
617
+ *
618
+ * @hideconstructor
619
+ */
620
+ var RequestLoadingState = class {
621
+ /** @internal */
622
+ /** @internal */
623
+ /** @internal */
624
+ /** @internal */
625
+ /** @internal */
626
+ /** @internal */
627
+ /** @internal */
628
+ /** @internal */
629
+ /** @internal */
630
+ /** @internal */
631
+ /** @internal */
632
+ /** @internal */
633
+ _stream = null;
634
+ /** @internal */
635
+ _future;
636
+ /** @internal */
637
+ _triggered = false;
638
+ /** @internal */
639
+ _trigger() {
640
+ if (this._triggered) return;
641
+ this._triggered = true;
642
+ const promise = this._future.getStream();
643
+ if (promise.sizeHint) this._sizeHint = promise.sizeHint;
644
+ this.promise = promise.then((stream) => {
645
+ if (!stream) {
646
+ this._isPending = false;
647
+ this._isComplete = true;
648
+ return;
649
+ }
650
+ return watchStream(stream, this);
651
+ }, (error) => {
652
+ this._isPending = false;
653
+ this._isStarted = false;
654
+ if (isAbortError(error)) {
655
+ this._isCancelled = true;
656
+ this._isComplete = true;
657
+ }
658
+ this._isErrored = true;
659
+ this._error = error;
660
+ });
661
+ }
662
+ /**
663
+ * Resolves once the stream has finished being consumed, or rejects
664
+ * if the request errors. `null` until first accessed.
665
+ */
666
+ promise = null;
667
+ /**
668
+ * Whether the stream has not yet started being consumed.
669
+ */
670
+ get isPending() {
671
+ this._trigger();
672
+ return this._isPending;
673
+ }
674
+ /**
675
+ * The total size of the response in bytes, if known ahead of time
676
+ * (via a `Content-Length` header or similar).
677
+ */
678
+ get sizeHint() {
679
+ this._trigger();
680
+ return this._sizeHint;
681
+ }
682
+ /**
683
+ * A readable stream of the response content. Accessing this property
684
+ * begins consumption of the underlying request stream.
685
+ */
686
+ get stream() {
687
+ this._trigger();
688
+ if (!this._stream) {
689
+ if (this._isComplete || this._isCancelled || this._isErrored) return null;
690
+ this._stream = new TransformStream();
691
+ }
692
+ return this._stream.readable;
693
+ }
694
+ /**
695
+ * Whether the stream has started being consumed but has not yet completed.
696
+ */
697
+ get isStarted() {
698
+ this._trigger();
699
+ return this._isStarted;
700
+ }
701
+ /**
702
+ * The number of bytes loaded so far.
703
+ */
704
+ get bytesLoaded() {
705
+ this._trigger();
706
+ return this._bytesLoaded;
707
+ }
708
+ /**
709
+ * The `performance.now()` timestamp at which the stream started being consumed.
710
+ */
711
+ get startTime() {
712
+ this._trigger();
713
+ return this._startTime;
714
+ }
715
+ /**
716
+ * The `performance.now()` timestamp at which the stream finished being consumed.
717
+ */
718
+ get endTime() {
719
+ this._trigger();
720
+ return this._endTime;
721
+ }
722
+ /**
723
+ * The `performance.now()` timestamp at which the last chunk of data was received.
724
+ */
725
+ get lastPacketTime() {
726
+ this._trigger();
727
+ return this._lastPacketTime;
728
+ }
729
+ /**
730
+ * Whether the stream has finished being consumed.
731
+ */
732
+ get isComplete() {
733
+ this._trigger();
734
+ return this._isComplete;
735
+ }
736
+ /**
737
+ * Whether the request was aborted before the stream finished being consumed.
738
+ */
739
+ get isCancelled() {
740
+ this._trigger();
741
+ return this._isCancelled;
742
+ }
743
+ /**
744
+ * Whether an error occurred while consuming the stream.
745
+ */
746
+ get isErrored() {
747
+ this._trigger();
748
+ return this._isErrored;
749
+ }
750
+ /**
751
+ * The error that occurred while consuming the stream, if any.
752
+ */
753
+ get error() {
754
+ this._trigger();
755
+ return this._error;
756
+ }
757
+ /**
758
+ * The number of milliseconds elapsed since the stream started being
759
+ * consumed, using the last packet time (or end time, once complete)
760
+ * as the endpoint.
761
+ */
762
+ get elapsedTime() {
763
+ return (this.endTime || this.lastPacketTime) - this.startTime;
764
+ }
765
+ /**
766
+ * The ratio (0 to 1) of {@link RequestLoadingState.bytesLoaded | bytesLoaded}
767
+ * to {@link RequestLoadingState.sizeHint | sizeHint}, or `0` if no size hint is available.
768
+ */
769
+ get completedRatio() {
770
+ return this.sizeHint ? this.bytesLoaded / this.sizeHint : 0;
771
+ }
772
+ /**
773
+ * The inverse of {@link RequestLoadingState.completedRatio | completedRatio}.
774
+ */
775
+ get remainingRatio() {
776
+ return 1 - this.completedRatio;
777
+ }
778
+ /**
779
+ * The total number of milliseconds elapsed between
780
+ * {@link RequestLoadingState.startTime | startTime} and {@link RequestLoadingState.endTime | endTime}.
781
+ */
782
+ get duration() {
783
+ return this.endTime - this.startTime;
784
+ }
785
+ /**
786
+ * The average download speed in bytes per second.
787
+ */
788
+ get speed() {
789
+ return this.bytesLoaded / (this.elapsedTime / 1e3);
790
+ }
791
+ constructor(future) {
792
+ this._future = future;
793
+ }
794
+ /**
795
+ * Aborts the underlying request.
796
+ */
797
+ abort = () => {
798
+ this._future.abort();
799
+ };
800
+ };
801
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_isPending", true);
802
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_isStarted", false);
803
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_isComplete", false);
804
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_isCancelled", false);
805
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_isErrored", false);
806
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_error", null);
807
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_sizeHint", 0);
808
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_bytesLoaded", 0);
809
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_startTime", 0);
810
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_endTime", 0);
811
+ defineNonEnumerableSignal(RequestLoadingState.prototype, "_lastPacketTime", 0);
812
+ /**
813
+ * The state of a request in the "pending"
814
+ * state. This is the default initial state.
815
+ *
816
+ * Extends the {@link PendingPromise} interface.
817
+ *
818
+ */
819
+ /**
820
+ * The state of a request in the "fulfilled" state.
821
+ * This is the state of a request that has resolved
822
+ * successfully.
823
+ *
824
+ * Extends the {@link ResolvedPromise} interface.
825
+ *
826
+ */
827
+ /**
828
+ * The state of a request in the "rejected" state.
829
+ * This is the state of a request that has rejected
830
+ * with an error.
831
+ *
832
+ * Extends the {@link RejectedPromise} interface.
833
+ *
834
+ */
835
+ /**
836
+ * The state of a request in the "cancelled" state.
837
+ * This is the state of a promise that has been
838
+ * cancelled.
839
+ *
840
+ */
841
+ /**
842
+ * RequestState extends the concept of {@link PromiseState} to provide a reactive
843
+ * wrapper for a request {@link Future} which allows you write declarative code
844
+ * around a Future's control flow.
845
+ *
846
+ * It is useful in both Template and JavaScript contexts, allowing you
847
+ * to quickly derive behaviors and data from pending, error and success
848
+ * states.
849
+ *
850
+ * The key difference between a {@link Promise} and a Future is that Futures provide
851
+ * access to a {@link ReadableStream | stream} of their content, the {@link RequestKey} of the request (if any)
852
+ * as well as the ability to attempt to {@link Future.abort | abort} the request.
853
+ *
854
+ * ```ts
855
+ * interface Future<T> extends Promise<T>> {
856
+ * getStream(): Promise<ReadableStream>;
857
+ * abort(): void;
858
+ * lid: RequestKey | null;
859
+ * }
860
+ * ```
861
+ *
862
+ * These additional APIs allow us to craft even richer state experiences.
863
+ *
864
+ * To get the state of a request, use {@link getRequestState}.
865
+ *
866
+ * See also:
867
+ * - {@link PendingRequest}
868
+ * - {@link ResolvedRequest}
869
+ * - {@link RejectedRequest}
870
+ * - {@link CancelledRequest}
871
+ *
872
+ */
873
+ const RequestStateProto = {};
874
+ function performRefresh(requester, request, isReload) {
875
+ const req = Object.assign({}, request);
876
+ const cacheOptions = Object.assign({}, req.cacheOptions);
877
+ if (isReload) cacheOptions.reload = true;
878
+ else if (isReload === false) {
879
+ delete cacheOptions.reload;
880
+ cacheOptions.backgroundReload = true;
881
+ } else {
882
+ delete cacheOptions.backgroundReload;
883
+ delete cacheOptions.reload;
884
+ }
885
+ req.cacheOptions = cacheOptions;
886
+ return requester.request(req);
887
+ }
888
+ defineSignal(RequestStateProto, "reason", null);
889
+ defineSignal(RequestStateProto, "value", null);
890
+ defineSignal(RequestStateProto, "result", null);
891
+ defineSignal(RequestStateProto, "error", null);
892
+ defineSignal(RequestStateProto, "status", "pending");
893
+ defineSignal(RequestStateProto, "isPending", true);
894
+ defineSignal(RequestStateProto, "isLoading", true);
895
+ defineSignal(RequestStateProto, "isSuccess", false);
896
+ defineSignal(RequestStateProto, "isError", false);
897
+ defineSignal(RequestStateProto, "request", null);
898
+ defineSignal(RequestStateProto, "response", null);
899
+ Object.defineProperty(RequestStateProto, "isCancelled", { get() {
900
+ return this.isError && isAbortError(this.reason);
901
+ } });
902
+ Object.defineProperty(RequestStateProto, "loadingState", { get() {
903
+ if (!this._loadingState) this._loadingState = new RequestLoadingState(this._request);
904
+ return this._loadingState;
905
+ } });
906
+ function createRequestState(future) {
907
+ const state = getPromiseResult(future);
908
+ const promiseState = Object.create(RequestStateProto);
909
+ promiseState._request = future;
910
+ promiseState.reload = () => {
911
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
912
+ if (!test) throw new Error(`Cannot reload a request that is still pending. Await or abort the original request first.`);
913
+ })(!promiseState.isPending);
914
+ return performRefresh(future.requester, promiseState.request, true);
915
+ };
916
+ promiseState.refresh = (usePolicy = false) => {
917
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
918
+ if (!test) throw new Error(`Cannot refresh a request that is still pending. Await or abort the original request first.`);
919
+ })(!promiseState.isPending);
920
+ return performRefresh(future.requester, promiseState.request, usePolicy === true ? null : false);
921
+ };
922
+ if (state) {
923
+ if (state.isError) {
924
+ promiseState.error = state.result;
925
+ promiseState.reason = state.result;
926
+ promiseState.status = "rejected";
927
+ promiseState.isError = true;
928
+ promiseState.isPending = false;
929
+ promiseState.isLoading = false;
930
+ promiseState.request = state.result.request;
931
+ promiseState.response = state.result.response;
932
+ } else {
933
+ promiseState.result = state.result.content;
934
+ promiseState.value = state.result.content;
935
+ promiseState.status = "fulfilled";
936
+ promiseState.isSuccess = true;
937
+ promiseState.isPending = false;
938
+ promiseState.isLoading = false;
939
+ promiseState.request = state.result.request;
940
+ promiseState.response = state.result.response;
941
+ }
942
+ } else future.then((result) => {
943
+ setPromiseResult(future, {
944
+ isError: false,
945
+ result
946
+ });
947
+ promiseState.result = result.content;
948
+ promiseState.value = result.content;
949
+ promiseState.status = "fulfilled";
950
+ promiseState.isSuccess = true;
951
+ promiseState.isPending = false;
952
+ promiseState.isLoading = false;
953
+ promiseState.request = result.request;
954
+ promiseState.response = result.response;
955
+ }, (error) => {
956
+ setPromiseResult(future, {
957
+ isError: true,
958
+ result: error
959
+ });
960
+ promiseState.error = error;
961
+ promiseState.reason = error;
962
+ promiseState.status = "rejected";
963
+ promiseState.isError = true;
964
+ promiseState.isPending = false;
965
+ promiseState.isLoading = false;
966
+ promiseState.request = error.request;
967
+ promiseState.response = error.response;
968
+ });
969
+ return promiseState;
970
+ }
971
+ /**
972
+ * `getRequestState` can be used in both JavaScript and Template contexts.
973
+ *
974
+ * ```ts
975
+ * import { getRequestState } from '@warp-drive/ember';
976
+ *
977
+ * const state = getRequestState(future);
978
+ * ```
979
+ *
980
+ * For instance, we could write a getter on a component that updates whenever
981
+ * the request state advances or the future changes, by combining the function
982
+ * with the use of `@cached`
983
+ *
984
+ * ```ts
985
+ * class Component {
986
+ * @cached
987
+ * get title() {
988
+ * const state = getRequestState(this.args.request);
989
+ * if (state.isPending) {
990
+ * return 'loading...';
991
+ * }
992
+ * if (state.isError) { return null; }
993
+ * return state.result.title;
994
+ * }
995
+ * }
996
+ * ```
997
+ *
998
+ * Or in a template as a helper:
999
+ *
1000
+ * ```gjs
1001
+ * import { getRequestState } from '@warp-drive/ember';
1002
+ *
1003
+ * <template>
1004
+ * {{#let (getRequestState @request) as |state|}}
1005
+ * {{#if state.isPending}}
1006
+ * <Spinner />
1007
+ * {{else if state.isError}}
1008
+ * <ErrorForm @error={{state.error}} />
1009
+ * {{else}}
1010
+ * <h1>{{state.result.title}}</h1>
1011
+ * {{/if}}
1012
+ * {{/let}}
1013
+ * </template>
1014
+ * ```
1015
+ *
1016
+ * If looking to use in a template, consider also the `<Request />` component
1017
+ * which offers a number of additional capabilities for requests *beyond* what
1018
+ * `RequestState` provides.
1019
+ *
1020
+ */
1021
+ function getRequestState(future) {
1022
+ let state = RequestCache.get(future);
1023
+ if (!state) {
1024
+ state = createRequestState(future);
1025
+ RequestCache.set(future, state);
1026
+ }
1027
+ return state;
1028
+ }
1029
+
1030
+ //#endregion
1031
+ //#region ../../node_modules/.pnpm/decorat_5d4eca388601a94e7fbc656401b751d1/node_modules/decorator-transforms/dist/runtime--fcdnjmJ.js
1032
+ const deferred = /* @__PURE__ */ new WeakMap();
1033
+ function deferDecorator(proto, prop, desc) {
1034
+ let map = deferred.get(proto);
1035
+ if (!map) {
1036
+ map = /* @__PURE__ */ new Map();
1037
+ deferred.set(proto, map);
1038
+ }
1039
+ map.set(prop, desc);
1040
+ }
1041
+ function findDeferredDecorator(target, prop) {
1042
+ var _a;
1043
+ let cursor = target.prototype;
1044
+ while (cursor) {
1045
+ let desc = (_a = deferred.get(cursor)) == null ? void 0 : _a.get(prop);
1046
+ if (desc) return desc;
1047
+ cursor = Object.getPrototypeOf(cursor);
1048
+ }
1049
+ }
1050
+ function decorateFieldV2(prototype, prop, decorators, initializer) {
1051
+ let desc = {
1052
+ configurable: true,
1053
+ enumerable: true,
1054
+ writable: true,
1055
+ initializer: null
1056
+ };
1057
+ if (initializer) desc.initializer = initializer;
1058
+ for (let decorator of decorators) desc = decorator(prototype, prop, desc) || desc;
1059
+ if (desc.initializer === void 0) Object.defineProperty(prototype, prop, desc);
1060
+ else deferDecorator(prototype, prop, desc);
1061
+ }
1062
+ function decorateMethodV2(prototype, prop, decorators) {
1063
+ let desc = { ...Object.getOwnPropertyDescriptor(prototype, prop) };
1064
+ for (let decorator of decorators) desc = decorator(prototype, prop, desc) || desc;
1065
+ if (desc.initializer !== void 0) {
1066
+ desc.value = desc.initializer ? desc.initializer.call(prototype) : void 0;
1067
+ desc.initializer = void 0;
1068
+ }
1069
+ Object.defineProperty(prototype, prop, desc);
1070
+ }
1071
+ function initializeDeferredDecorator(target, prop) {
1072
+ let desc = findDeferredDecorator(target.constructor, prop);
1073
+ if (desc) Object.defineProperty(target, prop, {
1074
+ enumerable: desc.enumerable,
1075
+ configurable: desc.configurable,
1076
+ writable: desc.writable,
1077
+ value: desc.initializer ? desc.initializer.call(target) : void 0
1078
+ });
1079
+ }
1080
+
1081
+ //#endregion
1082
+ //#region src/signals/request-subscription.ts
1083
+ const DEFAULT_DEADLINE = 3e4;
1084
+ /**
1085
+ * A symbol used to dispose of a {@link RequestSubscription} when the
1086
+ * component or context using it is torn down.
1087
+ */
1088
+ const DISPOSE = Symbol.dispose || Symbol.for("dispose");
1089
+ function isNeverString(val) {
1090
+ return val;
1091
+ }
1092
+ /**
1093
+ * The individual autorefresh strategies a {@link RequestSubscription}
1094
+ * may combine, see {@link AutorefreshBehaviorCombos}.
1095
+ */
1096
+ /**
1097
+ * The value accepted by {@link SubscriptionArgs.autorefresh}: either a
1098
+ * boolean, a single {@link AutorefreshBehaviorType}, or a comma-separated
1099
+ * combination of up to three of them.
1100
+ */
1101
+ /**
1102
+ * Utilities to assist in recovering from the error.
1103
+ */
1104
+ /** @deprecated use {@link RecoveryFeatures} */
1105
+ /**
1106
+ * Utilities for keeping the request fresh
1107
+ */
1108
+ /**
1109
+ * The args accepted by the `<Request />` component.
1110
+ */
1111
+ /**
1112
+ * The args accepted by a {@link RequestSubscription}.
1113
+ */
1114
+ /**
1115
+ * A reactive class
1116
+ *
1117
+ * @hideconstructor
1118
+ */
1119
+ var RequestSubscription = class {
1120
+ /**
1121
+ * Whether the browser reports that the network is online.
1122
+ */
1123
+ /**
1124
+ * Whether the browser reports that the tab is hidden.
1125
+ */
1126
+ /**
1127
+ * Whether the component is currently refreshing the request.
1128
+ */
1129
+ /**
1130
+ * The most recent blocking request that was made, typically
1131
+ * the result of a reload.
1132
+ *
1133
+ * This will never be the original request passed as an arg to
1134
+ * the component.
1135
+ *
1136
+ * @internal
1137
+ */
1138
+ /**
1139
+ * The most recent request that was made, typically due to either a
1140
+ * reload or a refresh.
1141
+ *
1142
+ * This will never be the original request passed as an arg to
1143
+ * the component.
1144
+ *
1145
+ * @internal
1146
+ */
1147
+ /**
1148
+ * The time at which the network was reported as offline.
1149
+ *
1150
+ * @internal
1151
+ */
1152
+ /** @internal */
1153
+ /** @internal */
1154
+ /** @internal */
1155
+ /** @internal */
1156
+ /** @internal */
1157
+ /**
1158
+ * The event listener for network status changes,
1159
+ * cached to use the reference for removal.
1160
+ *
1161
+ * @internal
1162
+ */
1163
+ /**
1164
+ * The event listener for visibility status changes,
1165
+ * cached to use the reference for removal.
1166
+ *
1167
+ * @internal
1168
+ */
1169
+ /**
1170
+ * The last request passed as an arg to the component,
1171
+ * cached for comparison.
1172
+ *
1173
+ * @internal
1174
+ */
1175
+ /**
1176
+ * The last query passed as an arg to the component,
1177
+ * cached for comparison.
1178
+ *
1179
+ * @internal
1180
+ */
1181
+ /** @internal */
1182
+ /** @internal */
1183
+ /** @internal */
1184
+ /**
1185
+ * The Store this subscription subscribes to or the RequestManager
1186
+ * which issues this request.
1187
+ */
1188
+ /**
1189
+ * The Store or RequestManager that the last subscription is attached to.
1190
+ *
1191
+ * This differs from 'store' because a <Request /> may be passed a
1192
+ * request originating from a different store than the <Request />
1193
+ * component would use if it were to issue the request itself.
1194
+ *
1195
+ * @internal
1196
+ */
1197
+ _requester;
1198
+ constructor(store, args) {
1199
+ this._args = args;
1200
+ this.store = store;
1201
+ this._subscribedTo = null;
1202
+ this._subscription = null;
1203
+ this._intervalStart = null;
1204
+ this._invalidated = false;
1205
+ this._nextInterval = null;
1206
+ this._requester = null;
1207
+ this.isDestroyed = false;
1208
+ this[DISPOSE] = _DISPOSE$2;
1209
+ this._installListeners();
1210
+ this._beginPolling();
1211
+ }
1212
+ /**
1213
+ * @internal
1214
+ */
1215
+ async _beginPolling() {
1216
+ try {
1217
+ if (!this.isIdle) await this.request;
1218
+ } catch {} finally {
1219
+ if (!this.isDestroyed) this._scheduleInterval();
1220
+ }
1221
+ }
1222
+ /**
1223
+ * Whether neither a `request` nor a `query` arg was provided, and so
1224
+ * this subscription has nothing to fetch or monitor.
1225
+ */
1226
+ get isIdle() {
1227
+ const { request, query } = this._args;
1228
+ return Boolean(!request && !query);
1229
+ }
1230
+ /**
1231
+ * The set of {@link AutorefreshBehaviorType}s this subscription is
1232
+ * configured to autorefresh for, derived from {@link SubscriptionArgs.autorefresh}.
1233
+ */
1234
+ static {
1235
+ decorateMethodV2(this.prototype, "isIdle", [memoized]);
1236
+ }
1237
+ get autorefreshTypes() {
1238
+ const { autorefresh } = this._args;
1239
+ let types;
1240
+ if (autorefresh === true) types = ["online", "invalid"];
1241
+ else if (typeof autorefresh === "string") types = autorefresh.split(",");
1242
+ else types = [];
1243
+ return new Set(types);
1244
+ }
1245
+ /** @internal */
1246
+ static {
1247
+ decorateMethodV2(this.prototype, "autorefreshTypes", [memoized]);
1248
+ }
1249
+ async _scheduleInterval() {
1250
+ const { autorefreshThreshold } = this._args;
1251
+ if (typeof window === "undefined" || !(typeof autorefreshThreshold === "number" && autorefreshThreshold > 0) || !this.autorefreshTypes.has("interval") || this._intervalStart !== null) return;
1252
+ if (this._latestRequest) {
1253
+ try {
1254
+ await this._latestRequest;
1255
+ } catch {}
1256
+ if (this.isDestroyed) return;
1257
+ }
1258
+ this._intervalStart = Date.now();
1259
+ this._nextInterval = setTimeout(() => {
1260
+ this._maybeUpdate();
1261
+ }, autorefreshThreshold);
1262
+ }
1263
+ /** @internal */
1264
+ _clearInterval() {
1265
+ if (this._nextInterval) {
1266
+ clearTimeout(this._nextInterval);
1267
+ this._intervalStart = null;
1268
+ }
1269
+ }
1270
+ /**
1271
+ * @internal
1272
+ */
1273
+ _updateSubscriptions() {
1274
+ if (this.isIdle) return;
1275
+ const requestId = this._request.lid;
1276
+ if (this._subscribedTo === requestId) return;
1277
+ this._removeSubscriptions();
1278
+ const store = this._getRequester();
1279
+ this._requester = store;
1280
+ if (requestId && isStore(store)) {
1281
+ this._subscribedTo = requestId;
1282
+ this._subscription = store.notifications.subscribe(requestId, (_id, op) => {
1283
+ if (this._isUpdating) return;
1284
+ switch (op) {
1285
+ case "invalidated":
1286
+ if (this.autorefreshTypes.has("invalid")) {
1287
+ this._invalidated = true;
1288
+ this._maybeUpdate();
1289
+ }
1290
+ break;
1291
+ case "state": {
1292
+ const priority = store.requestManager._deduped.get(requestId)?.priority;
1293
+ const state = this.reqState;
1294
+ if (!priority) this.isRefreshing = false;
1295
+ else if (priority.blocking && !state.isLoading) {
1296
+ this.isRefreshing = false;
1297
+ this._maybeUpdate("policy", true);
1298
+ } else this.isRefreshing = true;
1299
+ }
1300
+ }
1301
+ });
1302
+ }
1303
+ }
1304
+ /**
1305
+ * @internal
1306
+ */
1307
+ _removeSubscriptions() {
1308
+ const store = this._requester;
1309
+ if (this._subscription && store && isStore(store)) {
1310
+ store.notifications.unsubscribe(this._subscription);
1311
+ this._subscribedTo = null;
1312
+ this._subscription = null;
1313
+ this._requester = null;
1314
+ }
1315
+ }
1316
+ /**
1317
+ * Install the event listeners for network and visibility changes.
1318
+ *
1319
+ * This is only done in environments that provide a fully-featured global
1320
+ * `window` and/or `document`. Some non-DOM environments (e.g. React Native,
1321
+ * SSR/Node, workers) may provide a `window` global without the APIs we
1322
+ * rely on here (or no `window`/`document` at all), in which case we skip
1323
+ * attaching the corresponding listeners rather than throwing.
1324
+ *
1325
+ * @internal
1326
+ */
1327
+ _installListeners() {
1328
+ const hasWindow = typeof window !== "undefined";
1329
+ const hasDocument = typeof document !== "undefined";
1330
+ const hasWindowEvents = hasWindow && typeof window.addEventListener === "function";
1331
+ const hasDocumentEvents = hasDocument && typeof document.addEventListener === "function";
1332
+ this.isOnline = hasWindow && typeof window.navigator?.onLine === "boolean" ? window.navigator.onLine : true;
1333
+ this._unavailableStart = this.isOnline ? null : Date.now();
1334
+ this.isHidden = hasDocument && typeof document.visibilityState === "string" && document.visibilityState === "hidden";
1335
+ if (hasWindowEvents) {
1336
+ this._onlineChanged = (event) => {
1337
+ this.isOnline = event.type === "online";
1338
+ if (event.type === "offline" && this._unavailableStart === null) this._unavailableStart = Date.now();
1339
+ this._maybeUpdate();
1340
+ };
1341
+ window.addEventListener("online", this._onlineChanged, {
1342
+ passive: true,
1343
+ capture: true
1344
+ });
1345
+ window.addEventListener("offline", this._onlineChanged, {
1346
+ passive: true,
1347
+ capture: true
1348
+ });
1349
+ }
1350
+ if (hasDocumentEvents) {
1351
+ this._backgroundChanged = () => {
1352
+ const isHidden = document.visibilityState === "hidden";
1353
+ this.isHidden = isHidden;
1354
+ if (isHidden && this._unavailableStart === null) this._unavailableStart = Date.now();
1355
+ this._maybeUpdate();
1356
+ };
1357
+ document.addEventListener("visibilitychange", this._backgroundChanged, {
1358
+ passive: true,
1359
+ capture: true
1360
+ });
1361
+ }
1362
+ }
1363
+ /**
1364
+ * If the network is online and the tab is visible, either reload or refresh the request
1365
+ * based on the component's configuration and the requested update mode.
1366
+ *
1367
+ * Valid modes are:
1368
+ *
1369
+ * - `'reload'`: Force a reload of the request.
1370
+ * - `'refresh'`: Refresh the request in the background.
1371
+ * - `'policy'`: Make the request, letting the store's configured CachePolicy decide whether to reload, refresh, or do nothing.
1372
+ * - `undefined`: Make the request using the component's autorefreshBehavior setting if the autorefreshThreshold has passed.
1373
+ *
1374
+ * @internal
1375
+ */
1376
+ _maybeUpdate(mode, silent) {
1377
+ if (this.isIdle) return;
1378
+ const { reqState } = this;
1379
+ if (reqState.isPending) return;
1380
+ if (!Boolean(this.isOnline && !this.isHidden && (mode || this.autorefreshTypes.size))) {
1381
+ if (!silent && mode && mode !== "_invalidated") throw new Error(`Reload not available: the network is not online or the tab is hidden`);
1382
+ return;
1383
+ }
1384
+ const { autorefreshTypes } = this;
1385
+ let shouldAttempt = this._invalidated || Boolean(mode);
1386
+ if (!shouldAttempt && autorefreshTypes.has("online")) {
1387
+ const { _unavailableStart } = this;
1388
+ const { autorefreshThreshold } = this._args;
1389
+ const deadline = typeof autorefreshThreshold === "number" ? autorefreshThreshold : DEFAULT_DEADLINE;
1390
+ shouldAttempt = Boolean(_unavailableStart && Date.now() - _unavailableStart > deadline);
1391
+ }
1392
+ if (!shouldAttempt && autorefreshTypes.has("interval")) {
1393
+ const { _intervalStart } = this;
1394
+ const { autorefreshThreshold } = this._args;
1395
+ if (_intervalStart && typeof autorefreshThreshold === "number" && autorefreshThreshold > 0) shouldAttempt = Boolean(Date.now() - _intervalStart >= autorefreshThreshold);
1396
+ }
1397
+ this._unavailableStart = null;
1398
+ this._invalidated = false;
1399
+ if (shouldAttempt) {
1400
+ this._clearInterval();
1401
+ this._isUpdating = true;
1402
+ const val = (mode === "_invalidated" ? null : mode) ?? this._args.autorefreshBehavior ?? "policy";
1403
+ const requester = this._getRequester();
1404
+ if (!reqState._request.requester) reqState._request.requester = requester;
1405
+ switch (val) {
1406
+ case "reload":
1407
+ this._latestRequest = reqState.reload();
1408
+ break;
1409
+ case "refresh":
1410
+ this._latestRequest = reqState.refresh();
1411
+ break;
1412
+ case "policy":
1413
+ this._latestRequest = reqState.refresh(true);
1414
+ break;
1415
+ default: macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1416
+ if (!test) throw new Error(`Invalid ${mode ? "update mode" : "@autorefreshBehavior"} for <Request />: ${isNeverString(val)}`);
1417
+ })(false);
1418
+ }
1419
+ if (val !== "refresh") this._localRequest = this._latestRequest;
1420
+ this._scheduleInterval();
1421
+ this._latestRequest.finally(() => {
1422
+ this._isUpdating = false;
1423
+ });
1424
+ }
1425
+ }
1426
+ /**
1427
+ * @internal
1428
+ */
1429
+ _getRequester() {
1430
+ if (this._args.request?.requester) return this._args.request.requester;
1431
+ return this.store;
1432
+ }
1433
+ /**
1434
+ * Retry the request, reloading it from the server.
1435
+ */
1436
+ retry = async () => {
1437
+ this._maybeUpdate("reload");
1438
+ await this._localRequest;
1439
+ };
1440
+ /**
1441
+ * Refresh the request, updating it in the background.
1442
+ */
1443
+ refresh = async () => {
1444
+ this._maybeUpdate("refresh");
1445
+ await this._latestRequest;
1446
+ };
1447
+ /**
1448
+ * features to yield to the error slot of a component
1449
+ */
1450
+ get errorFeatures() {
1451
+ return {
1452
+ isHidden: this.isHidden,
1453
+ isOnline: this.isOnline,
1454
+ retry: this.retry
1455
+ };
1456
+ }
1457
+ /**
1458
+ * features to yield to the content slot of a component
1459
+ */
1460
+ static {
1461
+ decorateMethodV2(this.prototype, "errorFeatures", [memoized]);
1462
+ }
1463
+ get contentFeatures() {
1464
+ const feat = {
1465
+ isHidden: this.isHidden,
1466
+ isOnline: this.isOnline,
1467
+ reload: this.retry,
1468
+ refresh: this.refresh,
1469
+ isRefreshing: this.isRefreshing,
1470
+ latestRequest: this._latestRequest
1471
+ };
1472
+ if (feat.isRefreshing) feat.abort = () => {
1473
+ this._latestRequest?.abort();
1474
+ };
1475
+ return feat;
1476
+ }
1477
+ /**
1478
+ * @internal
1479
+ */
1480
+ static {
1481
+ decorateMethodV2(this.prototype, "contentFeatures", [memoized]);
1482
+ }
1483
+ get _request() {
1484
+ const { request, query } = this._args;
1485
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1486
+ if (!test) throw new Error(`Cannot use both @request and @query args with the <Request> component`);
1487
+ })(!request || !query);
1488
+ const { _localRequest, _originalRequest, _originalQuery } = this;
1489
+ if (_localRequest && request === _originalRequest && query === _originalQuery) return _localRequest;
1490
+ this._originalQuery = query;
1491
+ this._originalRequest = request;
1492
+ if (request) return request;
1493
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1494
+ if (!test) throw new Error(`You must provide either @request or an @query arg with the <Request> component`);
1495
+ })(query);
1496
+ return this.store.request(query);
1497
+ }
1498
+ /**
1499
+ * The {@link Future} this subscription is currently monitoring, and
1500
+ * (re-)subscribes to notifications for as a side effect of access.
1501
+ */
1502
+ static {
1503
+ decorateMethodV2(this.prototype, "_request", [memoized]);
1504
+ }
1505
+ get request() {
1506
+ if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) try {
1507
+ const request = this._request;
1508
+ this._updateSubscriptions();
1509
+ return request;
1510
+ } catch (e) {
1511
+ console.log(e);
1512
+ throw new Error(`Unable to initialize the request`, { cause: e });
1513
+ }
1514
+ else {
1515
+ const request = this._request;
1516
+ this._updateSubscriptions();
1517
+ return request;
1518
+ }
1519
+ }
1520
+ /**
1521
+ * The {@link RequestState} for {@link RequestSubscription.request | request}.
1522
+ */
1523
+ static {
1524
+ decorateMethodV2(this.prototype, "request", [memoized]);
1525
+ }
1526
+ get reqState() {
1527
+ return getRequestState(this.request);
1528
+ }
1529
+ /**
1530
+ * The resolved content of the request, once it has succeeded.
1531
+ */
1532
+ get result() {
1533
+ return this.reqState.result;
1534
+ }
1535
+ };
1536
+ defineSignal(RequestSubscription.prototype, "isOnline", true);
1537
+ defineSignal(RequestSubscription.prototype, "isHidden", false);
1538
+ defineSignal(RequestSubscription.prototype, "isRefreshing", false);
1539
+ defineSignal(RequestSubscription.prototype, "_localRequest", void 0);
1540
+ defineSignal(RequestSubscription.prototype, "_latestRequest", void 0);
1541
+ function isStore(store) {
1542
+ return "requestManager" in store;
1543
+ }
1544
+ /**
1545
+ * Creates a {@link RequestSubscription}, the reactive class powering the
1546
+ * `<Request />` component's autorefresh, retry, and refresh behaviors.
1547
+ */
1548
+ function createRequestSubscription(store, args) {
1549
+ return new RequestSubscription(store, args);
1550
+ }
1551
+ function upgradeSubscription$2(sub) {
1552
+ return sub;
1553
+ }
1554
+ function _DISPOSE$2() {
1555
+ const self = upgradeSubscription$2(this);
1556
+ self.isDestroyed = true;
1557
+ self._removeSubscriptions();
1558
+ self._clearInterval();
1559
+ if (self._onlineChanged && typeof window !== "undefined" && typeof window.removeEventListener === "function") {
1560
+ window.removeEventListener("online", self._onlineChanged, {
1561
+ passive: true,
1562
+ capture: true
1563
+ });
1564
+ window.removeEventListener("offline", self._onlineChanged, {
1565
+ passive: true,
1566
+ capture: true
1567
+ });
1568
+ }
1569
+ if (self._backgroundChanged && typeof document !== "undefined" && typeof document.removeEventListener === "function") document.removeEventListener("visibilitychange", self._backgroundChanged, {
1570
+ passive: true,
1571
+ capture: true
1572
+ });
1573
+ }
1574
+
1575
+ //#endregion
1576
+ //#region src/signals/page-cache.ts
1577
+ const { abs } = Math;
1578
+ /**
1579
+ * Extracts the `data` member of a document type, or the document type itself
1580
+ * when it has no `data` member.
1581
+ */
1582
+ /**
1583
+ * The element type of a collection document's `data` array — the item type an
1584
+ * infinite view renders. See {@link PaginationState.data}.
1585
+ */
1586
+ /** @internal */
1587
+ function getHref(link) {
1588
+ if (!link) return null;
1589
+ if (typeof link === "string") return link;
1590
+ return link.href;
1591
+ }
1592
+ /**
1593
+ * A single page of a paginated collection: its request, its loaded document, and
1594
+ * its links to neighboring pages in the shared page graph.
1595
+ *
1596
+ * Pages are yielded to consumers as `Readonly<PageCache>` — through
1597
+ * {@link PaginationState.activePage}, {@link PaginationState.pages}, and the
1598
+ * relational getters below — to read a page's data and request status when
1599
+ * building pagination UIs:
1600
+ *
1601
+ * ```ts
1602
+ * const page = paginationState.activePage;
1603
+ *
1604
+ * if (page?.isLoading) {
1605
+ * // show a spinner
1606
+ * } else if (page?.isError) {
1607
+ * // show page.reason
1608
+ * } else {
1609
+ * // render page.data
1610
+ * }
1611
+ * ```
1612
+ *
1613
+ * @since 5.9.0
1614
+ * @public
1615
+ * @hideconstructor
1616
+ */
1617
+ var PageCache = class {
1618
+ static {
1619
+ decorateFieldV2(this.prototype, "request", [signal]);
1620
+ }
1621
+ #request = (initializeDeferredDecorator(this, "request"), void 0);
1622
+ /** @internal */
1623
+ /**
1624
+ * The request that loaded (or is loading) this page, or `null` if the page is
1625
+ * known from links but was never requested. Wrap it in a `<Request>` component
1626
+ * to render the page's loading, error, and content states.
1627
+ */
1628
+ static {
1629
+ decorateFieldV2(this.prototype, "state", [signal]);
1630
+ }
1631
+ #state = (initializeDeferredDecorator(this, "state"), void 0);
1632
+ /** @internal */
1633
+ static {
1634
+ decorateFieldV2(this.prototype, "selfLink", [signal]);
1635
+ }
1636
+ #selfLink = (initializeDeferredDecorator(this, "selfLink"), void 0);
1637
+ /** The `self` link of this page — the URL that identifies it in the collection. */
1638
+ static {
1639
+ decorateFieldV2(this.prototype, "prevLink", [signal]);
1640
+ }
1641
+ #prevLink = (initializeDeferredDecorator(this, "prevLink"), void 0);
1642
+ /** The `prev` link of this page, or `null` at the start of the collection. */
1643
+ static {
1644
+ decorateFieldV2(this.prototype, "nextLink", [signal]);
1645
+ }
1646
+ #nextLink = (initializeDeferredDecorator(this, "nextLink"), void 0);
1647
+ /** The `next` link of this page, or `null` at the end of the collection. */
1648
+ static {
1649
+ decorateFieldV2(this.prototype, "firstLink", [signal]);
1650
+ }
1651
+ #firstLink = (initializeDeferredDecorator(this, "firstLink"), void 0);
1652
+ /** The `first` link of the collection, when the response exposed one. */
1653
+ static {
1654
+ decorateFieldV2(this.prototype, "lastLink", [signal]);
1655
+ }
1656
+ #lastLink = (initializeDeferredDecorator(this, "lastLink"), void 0);
1657
+ /** The `last` link of the collection, when the response exposed one. */
1658
+ static {
1659
+ decorateFieldV2(this.prototype, "pageNumber", [signal]);
1660
+ }
1661
+ #pageNumber = (initializeDeferredDecorator(this, "pageNumber"), void 0);
1662
+ /**
1663
+ * The 1-based page number, or `0` when unknown (for example cursor-based
1664
+ * pagination, where pages have no ordinal position). Derived from the
1665
+ * collection's {@link PageHints}.
1666
+ */
1667
+ static {
1668
+ decorateFieldV2(this.prototype, "before", [signal]);
1669
+ }
1670
+ #before = (initializeDeferredDecorator(this, "before"), void 0);
1671
+ /** @internal */
1672
+ static {
1673
+ decorateFieldV2(this.prototype, "after", [signal]);
1674
+ }
1675
+ #after = (initializeDeferredDecorator(this, "after"), void 0);
1676
+ /** @internal */
1677
+ constructor(manager, url) {
1678
+ this.manager = manager;
1679
+ this.pageNumber = 0;
1680
+ this.selfLink = url;
1681
+ }
1682
+ /**
1683
+ * The document this page's request resolved to, or `null` while it has not
1684
+ * resolved.
1685
+ */
1686
+ get value() {
1687
+ return this.state?.value;
1688
+ }
1689
+ /**
1690
+ * The `data` member of the loaded document — the page's items — or `null`
1691
+ * while the page has not loaded.
1692
+ */
1693
+ static {
1694
+ decorateMethodV2(this.prototype, "value", [memoized]);
1695
+ }
1696
+ get data() {
1697
+ return this.value?.data ?? null;
1698
+ }
1699
+ /**
1700
+ * Whether a request has ever been issued for this page. `false` for pages that
1701
+ * are known only from links.
1702
+ */
1703
+ static {
1704
+ decorateMethodV2(this.prototype, "data", [memoized]);
1705
+ }
1706
+ get isRequested() {
1707
+ return Boolean(this.state);
1708
+ }
1709
+ /** Whether this page's request has settled (successfully or with an error). */
1710
+ static {
1711
+ decorateMethodV2(this.prototype, "isRequested", [memoized]);
1712
+ }
1713
+ get isLoaded() {
1714
+ return this.isSuccess || this.isError;
1715
+ }
1716
+ /** Whether this page's request is currently in flight. */
1717
+ static {
1718
+ decorateMethodV2(this.prototype, "isLoaded", [memoized]);
1719
+ }
1720
+ get isLoading() {
1721
+ return Boolean(this.state?.isLoading);
1722
+ }
1723
+ /** Whether this page's request resolved successfully. */
1724
+ static {
1725
+ decorateMethodV2(this.prototype, "isLoading", [memoized]);
1726
+ }
1727
+ get isSuccess() {
1728
+ return Boolean(this.state?.isSuccess);
1729
+ }
1730
+ /** Whether this page's request was cancelled (aborted). */
1731
+ static {
1732
+ decorateMethodV2(this.prototype, "isSuccess", [memoized]);
1733
+ }
1734
+ get isCancelled() {
1735
+ return Boolean(this.state?.isCancelled);
1736
+ }
1737
+ /** Whether this page's request rejected with an error. */
1738
+ static {
1739
+ decorateMethodV2(this.prototype, "isCancelled", [memoized]);
1740
+ }
1741
+ get isError() {
1742
+ return Boolean(this.state?.isError);
1743
+ }
1744
+ /** The error this page's request rejected with, or `null` if it did not reject. */
1745
+ static {
1746
+ decorateMethodV2(this.prototype, "isError", [memoized]);
1747
+ }
1748
+ get reason() {
1749
+ return this.state?.reason ?? null;
1750
+ }
1751
+ /** The page at this page's `prev` link, or `null` at the start of the collection. */
1752
+ static {
1753
+ decorateMethodV2(this.prototype, "reason", [memoized]);
1754
+ }
1755
+ get prev() {
1756
+ const url = this.prevLink;
1757
+ return url ? this.manager.getPageCache(url) : null;
1758
+ }
1759
+ /** The page at this page's `next` link, or `null` at the end of the collection. */
1760
+ static {
1761
+ decorateMethodV2(this.prototype, "prev", [memoized]);
1762
+ }
1763
+ get next() {
1764
+ const url = this.nextLink;
1765
+ return url ? this.manager.getPageCache(url) : null;
1766
+ }
1767
+ /** The first page of the collection, when the response exposed a `first` link. */
1768
+ static {
1769
+ decorateMethodV2(this.prototype, "next", [memoized]);
1770
+ }
1771
+ get first() {
1772
+ const url = this.firstLink;
1773
+ return url ? this.manager.getPageCache(url) : null;
1774
+ }
1775
+ /** The last page of the collection, when the response exposed a `last` link. */
1776
+ static {
1777
+ decorateMethodV2(this.prototype, "first", [memoized]);
1778
+ }
1779
+ get last() {
1780
+ const url = this.lastLink;
1781
+ return url ? this.manager.getPageCache(url) : null;
1782
+ }
1783
+ /** @internal */
1784
+ static {
1785
+ decorateMethodV2(this.prototype, "last", [memoized]);
1786
+ }
1787
+ get isLinked() {
1788
+ return Boolean(this.before || this.after);
1789
+ }
1790
+ /** @internal */
1791
+ static {
1792
+ decorateMethodV2(this.prototype, "isLinked", [memoized]);
1793
+ }
1794
+ async load(request) {
1795
+ try {
1796
+ this.request = request;
1797
+ this.state = getRequestState(this.request);
1798
+ const content = (await this.request).content;
1799
+ const self = getHref(content?.links?.self);
1800
+ const first = getHref(content?.links?.first);
1801
+ const last = getHref(content?.links?.last);
1802
+ const next = getHref(content?.links?.next);
1803
+ const prev = getHref(content?.links?.prev);
1804
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1805
+ if (!test) throw new Error("Expected the page to have a self link");
1806
+ })(self);
1807
+ const pageNumber = this.getPageNumber(content);
1808
+ if (pageNumber) this.pageNumber = pageNumber;
1809
+ const firstPage = first ? this.manager.getPageCache(first) : null;
1810
+ const lastPage = last ? this.manager.getPageCache(last) : null;
1811
+ const prevPage = prev ? this.manager.getPageCache(prev) : null;
1812
+ const nextPage = next ? this.manager.getPageCache(next) : null;
1813
+ if (firstPage) {
1814
+ this.firstLink = first;
1815
+ firstPage.setPageNumber(1);
1816
+ if (!firstPage.after) firstPage.updateLinkage({ after: this });
1817
+ }
1818
+ if (lastPage) {
1819
+ this.lastLink = last;
1820
+ lastPage.setPageNumber(this.manager.totalPages);
1821
+ if (!lastPage.before) lastPage.updateLinkage({ before: this });
1822
+ }
1823
+ if (nextPage) {
1824
+ this.nextLink = next;
1825
+ nextPage.setPageNumber(this.pageNumber + 1);
1826
+ nextPage.updateLinks({ prev: self });
1827
+ }
1828
+ if (prevPage) {
1829
+ this.prevLink = prev;
1830
+ prevPage.setPageNumber(this.pageNumber - 1);
1831
+ prevPage.updateLinks({ next: self });
1832
+ }
1833
+ if (this.isLinked) {
1834
+ if (prevPage) prevPage.updateLinkage({ after: this });
1835
+ if (nextPage) nextPage.updateLinkage({ before: this });
1836
+ } else if (prevPage?.isLinked) {
1837
+ this.updateLinkage({ before: prevPage });
1838
+ if (nextPage) nextPage.updateLinkage({ before: this });
1839
+ } else if (nextPage?.isLinked) {
1840
+ this.updateLinkage({ after: nextPage });
1841
+ if (prevPage) prevPage.updateLinkage({ after: this });
1842
+ } else if ((prevPage || nextPage) && (firstPage || lastPage)) this.lookupLinkage(firstPage, lastPage);
1843
+ else if (prevPage || nextPage) this.updateLinkage({
1844
+ before: prevPage,
1845
+ after: nextPage
1846
+ });
1847
+ return content;
1848
+ } catch {}
1849
+ return null;
1850
+ }
1851
+ /** @internal */
1852
+ updateLinkage({ before, after }) {
1853
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1854
+ if (!test) throw new Error("Expected at least one of before or after page states to link to this page");
1855
+ })(before || after);
1856
+ const leftSide = before ?? after?.before;
1857
+ const rightSide = after ?? before?.after;
1858
+ if (leftSide && leftSide !== this) {
1859
+ leftSide.setAfter(this);
1860
+ this.setBefore(leftSide);
1861
+ }
1862
+ if (rightSide && rightSide !== this) {
1863
+ rightSide.setBefore(this);
1864
+ this.setAfter(rightSide);
1865
+ }
1866
+ }
1867
+ /** @internal */
1868
+ lookupLinkage(firstPage, lastPage) {
1869
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1870
+ if (!test) throw new Error("Expected at least one of firstPage or lastPage to lookup linkage against");
1871
+ })(firstPage || lastPage);
1872
+ if (firstPage && lastPage) {
1873
+ if (abs(this.pageNumber - firstPage.pageNumber) <= abs(this.pageNumber - lastPage.pageNumber)) this.lookupLinkageForward(firstPage);
1874
+ else this.lookupLinkageBackwards(lastPage);
1875
+ } else if (firstPage) this.lookupLinkageForward(firstPage);
1876
+ else if (lastPage) this.lookupLinkageBackwards(lastPage);
1877
+ }
1878
+ /** @internal */
1879
+ lookupLinkageForward(page) {
1880
+ while (page.after && page.after.pageNumber < this.pageNumber) page = page.after;
1881
+ this.updateLinkage({ before: page });
1882
+ }
1883
+ /** @internal */
1884
+ lookupLinkageBackwards(page) {
1885
+ while (page.before && page.before.pageNumber > this.pageNumber) page = page.before;
1886
+ this.updateLinkage({ after: page });
1887
+ }
1888
+ /** @internal */
1889
+ setBefore(page) {
1890
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1891
+ if (!test) throw new Error("Expected the before page to be a different page, got the same page");
1892
+ })(page !== this);
1893
+ this.before = page;
1894
+ }
1895
+ /** @internal */
1896
+ setAfter(page) {
1897
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
1898
+ if (!test) throw new Error("Expected the after page to be a different page, got the same page");
1899
+ })(page !== this);
1900
+ this.after = page;
1901
+ }
1902
+ /** @internal */
1903
+ getPageNumber(document) {
1904
+ return this.manager.readPageHints(document).currentPage;
1905
+ }
1906
+ /** @internal */
1907
+ updateLinks = ({ prev, next, first, last }) => {
1908
+ if (prev) this.prevLink = prev;
1909
+ if (next) this.nextLink = next;
1910
+ if (first) this.firstLink = first;
1911
+ if (last) this.lastLink = last;
1912
+ };
1913
+ /** @internal */
1914
+ setPageNumber = (pageNumber) => {
1915
+ if (!this.pageNumber) this.pageNumber = pageNumber;
1916
+ };
1917
+ };
1918
+
1919
+ //#endregion
1920
+ //#region src/signals/pagination-cache.ts
1921
+ const PaginationCacheMap = /* @__PURE__ */ new Map();
1922
+ /**
1923
+ * A hint function for extracting the `currentPage` and `totalPages` from a loaded
1924
+ * document, for when the response does not expose these values through the
1925
+ * default `meta` locations. Provided by the consumer via `<Paginate />`'s
1926
+ * `@pageHints` arg:
1927
+ *
1928
+ * ```gts
1929
+ * <Paginate @pageHints={{...}} />
1930
+ * ```
1931
+ *
1932
+ * Since these values are attached to the shared {@link PaginationCache}, the hint is
1933
+ * a property of the *collection*, not the component. Every `<Paginate />` sharing a
1934
+ * collection must provide the same function reference — define it once at module
1935
+ * scope and import it everywhere.
1936
+ *
1937
+ * @since 5.9.0
1938
+ * @public
1939
+ */
1940
+ /**
1941
+ * The default {@link PageHints}. Reads `currentPage`/`page` and `totalPages` from the
1942
+ * document `meta`, matching the behavior used before `pageHints` was configurable.
1943
+ * Used whenever the consumer does not provide a `pageHints` function.
1944
+ *
1945
+ * @since 5.9.0
1946
+ * @public
1947
+ */
1948
+ const defaultPageHints = (document) => {
1949
+ return {
1950
+ currentPage: document.meta?.page ?? document.meta?.currentPage ?? 0,
1951
+ totalPages: document.meta?.totalPages ?? 0
1952
+ };
1953
+ };
1954
+ /**
1955
+ * The global, shared cache for a paginated collection. Keyed by the collection's
1956
+ * `first` (or `self`) link, so that multiple components paging the same collection
1957
+ * share loaded pages, the page graph, and `totalPages`.
1958
+ *
1959
+ * This holds only shared, request-agnostic data. Per-component state (the active
1960
+ * page, navigation) lives on {@link PaginationState}, which is the API consumers
1961
+ * interact with — the cache itself is plumbing shared between the pagination
1962
+ * classes.
1963
+ *
1964
+ * @since 5.9.0
1965
+ * @public
1966
+ * @hideconstructor
1967
+ */
1968
+ var PaginationCache = class {
1969
+ static {
1970
+ decorateFieldV2(this.prototype, "firstPage", [signal]);
1971
+ }
1972
+ #firstPage = (initializeDeferredDecorator(this, "firstPage"), void 0);
1973
+ /**
1974
+ * The cache key this collection is stored under in the module-level cache —
1975
+ * its `first` (or `self`) link. This is the collection's identity: two
1976
+ * requests whose documents resolve to the same key are pages of the same
1977
+ * collection.
1978
+ *
1979
+ * @internal
1980
+ */
1981
+ /** @internal */
1982
+ static {
1983
+ decorateFieldV2(this.prototype, "totalPages", [signal]);
1984
+ }
1985
+ #totalPages = (initializeDeferredDecorator(this, "totalPages"), void 0);
1986
+ /**
1987
+ * The total number of pages in the collection, or `0` when unknown. Consumers
1988
+ * should read this via {@link PaginationState.totalPages}.
1989
+ */
1990
+ static {
1991
+ decorateFieldV2(this.prototype, "isNumbered", [signal]);
1992
+ }
1993
+ #isNumbered = (initializeDeferredDecorator(this, "isNumbered"), void 0);
1994
+ /**
1995
+ * Whether this collection has server-known page numbers. Stays `false` for
1996
+ * cursor-based collections (opaque `prev`/`next`, no index/total), which drives
1997
+ * whether numbered links are produced. Set once a {@link PageHints} yields a real
1998
+ * `currentPage`/`totalPages`.
1999
+ *
2000
+ * @internal
2001
+ */
2002
+ /** @internal */
2003
+ /** @internal */
2004
+ pageHints = defaultPageHints;
2005
+ constructor(key) {
2006
+ this.key = key;
2007
+ this.pagesCache = /* @__PURE__ */ new Map();
2008
+ this.firstPage = null;
2009
+ this.totalPages = 0;
2010
+ this.isNumbered = false;
2011
+ }
2012
+ /**
2013
+ * Installs the consumer-provided {@link PageHints} onto the shared cache. The first
2014
+ * explicit hint wins; passing `undefined` (no hint) is a no-op that preserves the
2015
+ * default. In dev, asserts that components sharing a collection do not provide
2016
+ * diverging hint functions.
2017
+ *
2018
+ * @internal
2019
+ */
2020
+ installPageHints(pageHints) {
2021
+ if (!pageHints) return;
2022
+ if (this.pageHints === defaultPageHints) {
2023
+ this.pageHints = pageHints;
2024
+ return;
2025
+ }
2026
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
2027
+ if (!test) throw new Error("Received diverging `pageHints` functions for the same paginated collection. Provide the same function reference to every <Paginate /> sharing a collection (define it once at module scope).");
2028
+ })(this.pageHints === pageHints);
2029
+ }
2030
+ /**
2031
+ * Runs the active {@link PageHints} against a document.
2032
+ *
2033
+ * Both values are *hints*, not requirements. A value of `0` means "unknown" —
2034
+ * the response did not expose it and no `pageHints` function derived it. When a
2035
+ * value is present (`> 0`) it is relied upon (numbered links, total, sparse
2036
+ * placement of jumped-to pages); when absent the page graph falls back to pure
2037
+ * `prev`/`next` adjacency (as in cursor/infinite streams).
2038
+ *
2039
+ * @internal
2040
+ */
2041
+ readPageHints(document) {
2042
+ const { currentPage, totalPages } = this.pageHints(document);
2043
+ if (currentPage > 0 || totalPages > 0) this.isNumbered = true;
2044
+ return {
2045
+ currentPage,
2046
+ totalPages
2047
+ };
2048
+ }
2049
+ /** @internal */
2050
+ getPageCache(url) {
2051
+ let page = this.pagesCache.get(url);
2052
+ if (!page) {
2053
+ page = new PageCache(this, url);
2054
+ this.pagesCache.set(url, page);
2055
+ }
2056
+ return page;
2057
+ }
2058
+ /** @internal */
2059
+ loadPage(url, request) {
2060
+ const page = this.getPageCache(url);
2061
+ if ((!page.isLoaded || page.isError) && request) {
2062
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
2063
+ if (!test) throw new Error("Expected a request to a load a page");
2064
+ })(request);
2065
+ page.load(request).then((document) => {
2066
+ this.updateFirstPage(page);
2067
+ if (document) this.totalPages = this.getTotalPages(document);
2068
+ });
2069
+ }
2070
+ return page;
2071
+ }
2072
+ /** @internal */
2073
+ updateFirstPage(page) {
2074
+ let maybeFirstPage = page;
2075
+ while (maybeFirstPage.before) maybeFirstPage = maybeFirstPage.before;
2076
+ if (!this.firstPage || this.firstPage.pageNumber > maybeFirstPage.pageNumber) this.firstPage = maybeFirstPage;
2077
+ }
2078
+ /** @internal */
2079
+ getTotalPages(document) {
2080
+ return this.readPageHints(document).totalPages;
2081
+ }
2082
+ /**
2083
+ * Every page known to the shared graph, in order — loaded pages and pages
2084
+ * known only from links — across all components sharing the collection.
2085
+ *
2086
+ * This is the whole-collection view. For the run a single component is
2087
+ * viewing, use {@link PaginationState.pages}.
2088
+ *
2089
+ * ```ts
2090
+ * const cache = getPaginationCache(firstLink);
2091
+ * for (const page of cache.pages) {
2092
+ * // page.isLoaded, page.pageNumber, page.data, ...
2093
+ * }
2094
+ * ```
2095
+ */
2096
+ get pages() {
2097
+ const self = this;
2098
+ return { *[Symbol.iterator]() {
2099
+ let page = self.firstPage;
2100
+ while (page) {
2101
+ yield page;
2102
+ page = page.after;
2103
+ }
2104
+ } };
2105
+ }
2106
+ /**
2107
+ * The items of every loaded page in the shared graph, flattened into one
2108
+ * contiguous iterable in page order. Pages that are known but not loaded
2109
+ * contribute nothing.
2110
+ *
2111
+ * This is the whole-collection view. For the run a single component is
2112
+ * viewing, use {@link PaginationState.data}.
2113
+ */
2114
+ static {
2115
+ decorateMethodV2(this.prototype, "pages", [memoized]);
2116
+ }
2117
+ get data() {
2118
+ const self = this;
2119
+ return { *[Symbol.iterator]() {
2120
+ for (const page of self.pages) if (page.data) yield* page.data;
2121
+ } };
2122
+ }
2123
+ static {
2124
+ decorateMethodV2(this.prototype, "data", [memoized]);
2125
+ }
2126
+ };
2127
+ /**
2128
+ * Get the shared {@link PaginationCache} for a given cache key (the collection's
2129
+ * `first` or `self` link). Returns the same instance for the same key for the
2130
+ * lifetime of the module.
2131
+ *
2132
+ * @since 5.9.0
2133
+ * @public
2134
+ */
2135
+ function getPaginationCache(key) {
2136
+ let cache = PaginationCacheMap.get(key);
2137
+ if (!cache) {
2138
+ cache = new PaginationCache(key);
2139
+ PaginationCacheMap.set(key, cache);
2140
+ }
2141
+ return cache;
2142
+ }
2143
+ /**
2144
+ * Clears the module-level pagination cache used by {@link getPaginationCache}.
2145
+ * Primarily intended for test isolation, since the cache is keyed by url and
2146
+ * otherwise persists for the lifetime of the module.
2147
+ *
2148
+ * @since 5.9.0
2149
+ * @public
2150
+ */
2151
+ function clearPaginationCache() {
2152
+ PaginationCacheMap.clear();
2153
+ }
2154
+
2155
+ //#endregion
2156
+ //#region src/signals/pagination-state.ts
2157
+ /**
2158
+ * The two navigation surfaces a `<Paginate />` component can drive. Selecting
2159
+ * one (via the component's `@mode` arg) narrows the yielded state so the two
2160
+ * APIs cannot be mixed:
2161
+ *
2162
+ * - `'paged'` — single-page view, see {@link PagedPaginationState}.
2163
+ * - `'infinite'` — accumulated view, see {@link InfinitePaginationState}.
2164
+ */
2165
+ /**
2166
+ * The part of a {@link PaginationState} available to both navigation surfaces.
2167
+ */
2168
+ /**
2169
+ * The paged (single-page view) surface of a {@link PaginationState}: render
2170
+ * {@link PaginationState.activePageRequest | activePageRequest}, navigate with
2171
+ * {@link PaginationState.loadPage | loadPage}. This is what the `<Paginate />`
2172
+ * component yields in `'paged'` mode (the default).
2173
+ */
2174
+ /**
2175
+ * The infinite (accumulated view) surface of a {@link PaginationState}: render
2176
+ * {@link PaginationState.data | data}, grow it with
2177
+ * {@link PaginationState.loadNext | loadNext}/{@link PaginationState.loadPrev | loadPrev}.
2178
+ * This is what the `<Paginate />` component yields in `'infinite'` mode.
2179
+ */
2180
+ /**
2181
+ * Resolves a {@link PaginateMode} to the surface it exposes, so a component
2182
+ * generic over the mode can yield only that surface.
2183
+ */
2184
+ /**
2185
+ * The per-component, local pagination state. It houses the state that is unique
2186
+ * to a single component instance — the active page and navigation — while
2187
+ * referencing a shared {@link PaginationCache} for the page graph and data.
2188
+ *
2189
+ * This is the object yielded by the `<Paginate />` component, narrowed by the
2190
+ * component's `@mode` arg to one of its two navigation surfaces so the two
2191
+ * APIs cannot be mixed:
2192
+ *
2193
+ * - **Paged** (`@mode="paged"`, the default): {@link PagedPaginationState} —
2194
+ * render {@link activePageRequest}, navigate with {@link loadPage} (what the
2195
+ * numbered/relational links call). Reads {@link activePage}.
2196
+ * - **Infinite** (`@mode="infinite"`): {@link InfinitePaginationState} — render
2197
+ * {@link data}, wrap {@link nextRequest}/{@link previousRequest} in `<Request>`
2198
+ * for loading state, and grow the view with {@link loadNext}/{@link loadPrev}.
2199
+ *
2200
+ * Both surfaces read the same shared page graph; the mode only selects which
2201
+ * API is exposed.
2202
+ *
2203
+ * Instances are created via {@link getPaginationState} (or by the `<Paginate />`
2204
+ * component on your behalf), never constructed directly.
2205
+ *
2206
+ * @since 5.9.0
2207
+ * @public
2208
+ * @hideconstructor
2209
+ */
2210
+ var PaginationState = class {
2211
+ /** @internal */
2212
+ /** @internal */
2213
+ /** @internal */
2214
+ /**
2215
+ * The shared page graph and data this component reads from.
2216
+ *
2217
+ * @internal
2218
+ */
2219
+ /**
2220
+ * The page the paged surface is currently showing. Starts at the page this
2221
+ * component first loaded and moves whenever {@link loadPage} runs (for
2222
+ * example a numbered link is clicked).
2223
+ */
2224
+ /**
2225
+ * The page this component first loaded, used to seed the active page and frontier.
2226
+ *
2227
+ * @internal
2228
+ */
2229
+ /**
2230
+ * The first and last loaded pages of the contiguous run this component is
2231
+ * viewing. Drives the infinite surface — {@link data} walks from
2232
+ * `frontierStart` to `frontierEnd`, and {@link loadPrev}/{@link loadNext} extend
2233
+ * them backward/forward. Both seed to {@link initialPage}; a purely paged
2234
+ * consumer never extends them, so they stay put and are effectively unused.
2235
+ *
2236
+ * @internal
2237
+ */
2238
+ /** @internal */
2239
+ /**
2240
+ * The request of the latest {@link adoptPage} call — only that call may
2241
+ * commit. Later calls (or a {@link loadPage} navigation) claim the slot,
2242
+ * superseding in-flight adoptions so the newest navigation always wins.
2243
+ * Untracked bookkeeping.
2244
+ *
2245
+ * @internal
2246
+ */
2247
+ constructor(request, pageHints) {
2248
+ this.store = request.requester;
2249
+ this.request = request;
2250
+ this.pageHints = pageHints;
2251
+ this._adoptTarget = null;
2252
+ this.setup();
2253
+ }
2254
+ /**
2255
+ * The request for the {@link activePage}, for the paged surface to render. This
2256
+ * is what a single-page view wraps in a `<Request>` to show the active page's
2257
+ * loading, error, and content states:
2258
+ *
2259
+ * ```gts
2260
+ * <Paginate @request={{this.request}}>
2261
+ * <:content as |pages|>
2262
+ * <Request @request={{pages.activePageRequest}}>
2263
+ * <:content as |result|>
2264
+ * {{#each result.data as |item|}}...{{/each}}
2265
+ * </:content>
2266
+ * </Request>
2267
+ * </:content>
2268
+ * </Paginate>
2269
+ * ```
2270
+ */
2271
+ get activePageRequest() {
2272
+ return this.activePage?.request ?? null;
2273
+ }
2274
+ /**
2275
+ * The total number of pages in the collection, or `0` when it is unknown (for
2276
+ * example a cursor-based collection that reports no total).
2277
+ *
2278
+ * ```gts
2279
+ * <p>Page {{pages.activePage.pageNumber}} of {{pages.totalPages}}</p>
2280
+ * ```
2281
+ */
2282
+ static {
2283
+ decorateMethodV2(this.prototype, "activePageRequest", [memoized]);
2284
+ }
2285
+ get totalPages() {
2286
+ return this.paginationCache?.totalPages ?? 0;
2287
+ }
2288
+ /**
2289
+ * The pages of the run this component is viewing, from the backward frontier
2290
+ * to the forward frontier inclusive, in order. Part of the infinite surface:
2291
+ * it is the same run as {@link data}, yielding the {@link PageCache} objects
2292
+ * instead of their flattened items — use it when the UI needs per-page
2293
+ * boundaries or request states.
2294
+ *
2295
+ * Grows as {@link loadNext}/{@link loadPrev} extend the frontier. Scoped to
2296
+ * this component's frontier (not the shared cache), so components paging the
2297
+ * same collection to different extents each see only what they have scrolled
2298
+ * through. For every page known to the whole collection, see
2299
+ * {@link PaginationCache.pages}.
2300
+ */
2301
+ static {
2302
+ decorateMethodV2(this.prototype, "totalPages", [memoized]);
2303
+ }
2304
+ get pages() {
2305
+ const self = this;
2306
+ return { *[Symbol.iterator]() {
2307
+ const end = self.frontierEnd;
2308
+ let page = self.frontierStart;
2309
+ while (page) {
2310
+ yield page;
2311
+ if (page === end) break;
2312
+ page = page.after;
2313
+ }
2314
+ } };
2315
+ }
2316
+ /**
2317
+ * The accumulated items across the loaded run, from the backward frontier to
2318
+ * the forward frontier inclusive — the single set an infinite collection renders.
2319
+ * Grows as {@link loadNext}/{@link loadPrev} extend the frontier. Scoped to this
2320
+ * component's frontier (not the shared cache), so components paging the same
2321
+ * collection to different extents each see only what they have scrolled through.
2322
+ *
2323
+ * The flattened items of {@link pages}, as one contiguous iterable. For the
2324
+ * items of every loaded page in the whole collection, see
2325
+ * {@link PaginationCache.data}.
2326
+ *
2327
+ * ```gts
2328
+ * <Paginate @request={{this.request}} @mode="infinite">
2329
+ * <:content as |pages features|>
2330
+ * {{#each pages.data as |item|}}...{{/each}}
2331
+ * {{#if pages.hasNext}}
2332
+ * <button {{on "click" features.loadNext}}>Load more</button>
2333
+ * {{/if}}
2334
+ * </:content>
2335
+ * </Paginate>
2336
+ * ```
2337
+ */
2338
+ static {
2339
+ decorateMethodV2(this.prototype, "pages", [memoized]);
2340
+ }
2341
+ get data() {
2342
+ const self = this;
2343
+ return { *[Symbol.iterator]() {
2344
+ for (const page of self.pages) if (page.data) yield* page.data;
2345
+ } };
2346
+ }
2347
+ /**
2348
+ * Whether a page exists after the forward frontier — i.e. there is more to load
2349
+ * going forward. Use to hide the trailing load-more sentinel at end-of-list:
2350
+ *
2351
+ * ```gts
2352
+ * {{#if pages.hasNext}}
2353
+ * <button {{on "click" features.loadNext}}>Load more</button>
2354
+ * {{/if}}
2355
+ * ```
2356
+ */
2357
+ static {
2358
+ decorateMethodV2(this.prototype, "data", [memoized]);
2359
+ }
2360
+ get hasNext() {
2361
+ return Boolean(this.frontierEnd?.nextLink);
2362
+ }
2363
+ /**
2364
+ * Whether a page exists before the backward frontier.
2365
+ */
2366
+ static {
2367
+ decorateMethodV2(this.prototype, "hasNext", [memoized]);
2368
+ }
2369
+ get hasPrevious() {
2370
+ return Boolean(this.frontierStart?.prevLink);
2371
+ }
2372
+ /**
2373
+ * The request for the page just after the forward frontier, for the infinite
2374
+ * surface. `null` until {@link loadNext} fires it (so a `<Request>` wrapping it
2375
+ * renders its idle block), the in-flight `Future` while that page loads, then
2376
+ * `null` again once the frontier advances onto it. Also `null` at end-of-list.
2377
+ *
2378
+ * ```gts
2379
+ * {{#if pages.hasNext}}
2380
+ * <Request @request={{pages.nextRequest}}>
2381
+ * <:idle><button {{on "click" features.loadNext}}>Load more</button></:idle>
2382
+ * <:loading><Spinner /></:loading>
2383
+ * </Request>
2384
+ * {{/if}}
2385
+ * ```
2386
+ */
2387
+ static {
2388
+ decorateMethodV2(this.prototype, "hasPrevious", [memoized]);
2389
+ }
2390
+ get nextRequest() {
2391
+ const url = this.frontierEnd?.nextLink;
2392
+ if (!url) return null;
2393
+ return this.paginationCache?.getPageCache(url).request ?? null;
2394
+ }
2395
+ /**
2396
+ * The request for the page just before the backward frontier. Mirror of
2397
+ * {@link nextRequest} for {@link loadPrev}.
2398
+ */
2399
+ static {
2400
+ decorateMethodV2(this.prototype, "nextRequest", [memoized]);
2401
+ }
2402
+ get previousRequest() {
2403
+ const url = this.frontierStart?.prevLink;
2404
+ if (!url) return null;
2405
+ return this.paginationCache?.getPageCache(url).request ?? null;
2406
+ }
2407
+ /** @internal */
2408
+ static {
2409
+ decorateMethodV2(this.prototype, "previousRequest", [memoized]);
2410
+ }
2411
+ async setup() {
2412
+ let document;
2413
+ try {
2414
+ document = await this.request;
2415
+ } catch {
2416
+ return;
2417
+ }
2418
+ const content = document.content;
2419
+ const selfLink = getHref(content.links?.self);
2420
+ const firstLink = getHref(content.links?.first);
2421
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
2422
+ if (!test) throw new Error("Expected the initial document to have a self link");
2423
+ })(selfLink);
2424
+ const cache = getPaginationCache(firstLink ?? selfLink ?? "");
2425
+ cache.installPageHints(this.pageHints);
2426
+ this.paginationCache = cache;
2427
+ cache.totalPages = cache.getTotalPages(content);
2428
+ this.activePage = this.initialPage = cache.loadPage(selfLink, this.request);
2429
+ this.frontierStart = this.frontierEnd = this.initialPage;
2430
+ }
2431
+ /**
2432
+ * Commits a resolved, membership-proven page into this state, making it the
2433
+ * {@link activePage}. The synchronous commit step under {@link adoptPage},
2434
+ * which is where the resolution and membership verification live.
2435
+ *
2436
+ * It only activates the page and keeps the infinite surface's frontier
2437
+ * coherent — a page already inside the run leaves the frontier untouched,
2438
+ * an adjacent page extends it, and a disjoint page resets the run to the
2439
+ * adopted page (jump semantics).
2440
+ *
2441
+ * @internal
2442
+ */
2443
+ _activate(page, url) {
2444
+ this.activePage = page;
2445
+ for (const existing of this.pages) if (existing === page) return;
2446
+ if (this.frontierEnd?.nextLink === url) this.frontierEnd = page;
2447
+ else if (this.frontierStart?.prevLink === url) this.frontierStart = page;
2448
+ else this.frontierStart = this.frontierEnd = page;
2449
+ }
2450
+ /**
2451
+ * Adopts an externally-issued request into this pagination, making its page
2452
+ * the {@link activePage} — the programmatic entry point for route-driven
2453
+ * navigation when managing a `PaginationState` directly (the `<Paginate />`
2454
+ * component uses the same mechanism for a changed `@request` arg).
2455
+ *
2456
+ * Awaits the request and verifies that its document is a page of this
2457
+ * state's collection (same `first` — or `self` — link). On a match, the
2458
+ * page is loaded (a page already in the shared cache is reused) and — once
2459
+ * its request settles — committed: it becomes the active page, and the
2460
+ * infinite surface's run is kept coherent (a page already inside the run
2461
+ * leaves it untouched, an adjacent page extends it, a disjoint page resets
2462
+ * the run to the adopted page). The commit happens only after the page has
2463
+ * loaded, so the previous page stays active — and rendered — while the
2464
+ * adoption resolves. Returns the page's document.
2465
+ *
2466
+ * Concurrent calls race safely: the latest call wins. An earlier in-flight
2467
+ * adoption is superseded and commits nothing, and a {@link loadPage}
2468
+ * navigation also supersedes a pending adoption (the user's click is the
2469
+ * newer intent).
2470
+ *
2471
+ * Returns `null` — leaving the state untouched — whenever the adoption does
2472
+ * not commit:
2473
+ *
2474
+ * - the request (or its page's load) rejected
2475
+ * - the document is a page of a *different* collection
2476
+ * - this state has not finished setting up its own collection yet
2477
+ * - the call was superseded by a newer navigation
2478
+ *
2479
+ * ```ts
2480
+ * const pages = getPaginationState(initialRequest);
2481
+ * // later, e.g. in a route model hook reacting to a ?page= param:
2482
+ * const adopted = await pages.adoptPage(store.request(query));
2483
+ * if (adopted === null) {
2484
+ * // not part of this collection — start a fresh pagination
2485
+ * }
2486
+ * ```
2487
+ *
2488
+ * It is a stable reference, so it is safe to pass around as an "action" or
2489
+ * "event" handler.
2490
+ */
2491
+ adoptPage = async (request) => {
2492
+ this._adoptTarget = request;
2493
+ let content;
2494
+ try {
2495
+ content = (await request).content;
2496
+ } catch {
2497
+ return null;
2498
+ }
2499
+ if (this._adoptTarget !== request) return null;
2500
+ const cache = this.paginationCache;
2501
+ if (!cache) return null;
2502
+ const selfLink = getHref(content.links?.self);
2503
+ const firstLink = getHref(content.links?.first);
2504
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
2505
+ if (!test) throw new Error("Expected the adopted document to have a self link");
2506
+ })(selfLink);
2507
+ if (!selfLink || (firstLink ?? selfLink) !== cache.key) return null;
2508
+ const page = cache.loadPage(selfLink, request);
2509
+ try {
2510
+ await page.request;
2511
+ } catch {
2512
+ return null;
2513
+ }
2514
+ if (this._adoptTarget !== request) return null;
2515
+ this._activate(page, selfLink);
2516
+ return page.value;
2517
+ };
2518
+ /**
2519
+ * Extends the backward frontier by one page, prepending it to {@link data}.
2520
+ * The frontier advances only once the page has loaded, so
2521
+ * {@link previousRequest} tracks the in-flight page meanwhile. Returns the
2522
+ * loaded value, or `null` when there is no previous page or the load fails.
2523
+ *
2524
+ * On failure the frontier stays put and {@link previousRequest} keeps
2525
+ * resolving to the failed page, so a wrapping `<Request>` renders its error
2526
+ * block. Calling again retries: the failed page is re-requested with a
2527
+ * forced reload.
2528
+ *
2529
+ * In templates it is also available as the `loadPrev` content feature
2530
+ * ({@link InfinitePaginationContentFeatures.loadPrev}) yielded by
2531
+ * `<Paginate />`; the two are the same function.
2532
+ *
2533
+ * It is a stable reference, so it is safe to pass around as an "action" or
2534
+ * "event" handler.
2535
+ */
2536
+ loadPrev = async () => {
2537
+ return this._extend("prev");
2538
+ };
2539
+ /**
2540
+ * Extends the forward frontier by one page, appending it to {@link data}.
2541
+ * Mirror of {@link loadPrev}.
2542
+ *
2543
+ * In templates it is also available as the `loadNext` content feature
2544
+ * ({@link InfinitePaginationContentFeatures.loadNext}) yielded by
2545
+ * `<Paginate />`; the two are the same function.
2546
+ *
2547
+ * ```gts
2548
+ * <button {{on "click" pages.loadNext}}>Load more</button>
2549
+ * ```
2550
+ */
2551
+ loadNext = async () => {
2552
+ return this._extend("next");
2553
+ };
2554
+ /** @internal */
2555
+ _extend = async (dir) => {
2556
+ const cache = this.paginationCache;
2557
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
2558
+ if (!test) throw new Error("Expected the pagination cache to be set up before loading a page");
2559
+ })(cache);
2560
+ const frontier = dir === "next" ? this.frontierEnd : this.frontierStart;
2561
+ const url = dir === "next" ? frontier?.nextLink : frontier?.prevLink;
2562
+ if (!url) return null;
2563
+ const page = cache.getPageCache(url);
2564
+ if (!page.isRequested || page.isError) {
2565
+ const request = this.store.request(page.isError ? {
2566
+ method: "GET",
2567
+ url,
2568
+ cacheOptions: { reload: true }
2569
+ } : {
2570
+ method: "GET",
2571
+ url
2572
+ });
2573
+ cache.loadPage(url, request);
2574
+ }
2575
+ try {
2576
+ await page.request;
2577
+ } catch {
2578
+ return null;
2579
+ }
2580
+ if (dir === "next") this.frontierEnd = page;
2581
+ else this.frontierStart = page;
2582
+ return page.value;
2583
+ };
2584
+ /**
2585
+ * Loads a specific page by its URL and makes it the {@link activePage},
2586
+ * requesting it first if it is not already loaded. This is the paged surface's
2587
+ * navigation entry point, called by the numbered and relational links.
2588
+ *
2589
+ * In templates it is also available as the `loadPage` content feature
2590
+ * ({@link PagedPaginationContentFeatures.loadPage}) yielded by `<Paginate />`;
2591
+ * the two are the same function.
2592
+ *
2593
+ * It is a stable reference, so it is safe to pass around as an "action" or
2594
+ * "event" handler. Returns the page's value, or `null` if it has none or
2595
+ * the load fails.
2596
+ *
2597
+ * On failure the page stays active and {@link activePageRequest} resolves to
2598
+ * it, so a wrapping `<Request>` renders its error block. Calling again (for
2599
+ * example clicking the page's link a second time) retries: the failed page
2600
+ * is re-requested with a forced reload.
2601
+ *
2602
+ * ```gts
2603
+ * <EachLink @pages={{pages}}>
2604
+ * <:link as |link|>
2605
+ * <button {{on "click" (fn features.loadPage link.url)}}>{{link.text}}</button>
2606
+ * </:link>
2607
+ * </EachLink>
2608
+ * ```
2609
+ */
2610
+ loadPage = async (url) => {
2611
+ const cache = this.paginationCache;
2612
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
2613
+ if (!test) throw new Error("Expected the pagination cache to be set up before loading a page");
2614
+ })(cache);
2615
+ this._adoptTarget = null;
2616
+ const page = cache.getPageCache(url);
2617
+ this.activePage = page;
2618
+ if (!page.isLoaded || page.isError) {
2619
+ const request = this.store.request(page.isError ? {
2620
+ method: "GET",
2621
+ url,
2622
+ cacheOptions: { reload: true }
2623
+ } : {
2624
+ method: "GET",
2625
+ url
2626
+ });
2627
+ cache.loadPage(url, request);
2628
+ try {
2629
+ await page.request;
2630
+ } catch {
2631
+ return null;
2632
+ }
2633
+ }
2634
+ return page.value;
2635
+ };
2636
+ };
2637
+ defineSignal(PaginationState.prototype, "paginationCache", null);
2638
+ defineSignal(PaginationState.prototype, "activePage", null);
2639
+ defineSignal(PaginationState.prototype, "initialPage", null);
2640
+ defineSignal(PaginationState.prototype, "frontierStart", null);
2641
+ defineSignal(PaginationState.prototype, "frontierEnd", null);
2642
+ const PaginationStateCache = /* @__PURE__ */ new WeakMap();
2643
+ /**
2644
+ * Get the {@link PaginationState} for a given request. Returns the same instance
2645
+ * for the same request future, so that repeated calls (e.g. in a template, or
2646
+ * alongside the `<Paginate />` component using the same request) share the same
2647
+ * local pagination state. Keyed by request identity, just like
2648
+ * {@link getRequestState}.
2649
+ *
2650
+ * ```ts
2651
+ * const future = store.request(query);
2652
+ * const pages = getPaginationState(future);
2653
+ *
2654
+ * await future;
2655
+ * pages.totalPages; // now known, if the response exposed it
2656
+ * await pages.loadNext();
2657
+ * ```
2658
+ *
2659
+ * @since 5.9.0
2660
+ * @public
2661
+ */
2662
+ function getPaginationState(request, pageHints) {
2663
+ let state = PaginationStateCache.get(request);
2664
+ if (!state) {
2665
+ state = new PaginationState(request, pageHints);
2666
+ PaginationStateCache.set(request, state);
2667
+ }
2668
+ return state;
2669
+ }
2670
+
2671
+ //#endregion
2672
+ //#region src/signals/pagination-links.ts
2673
+ const PaginationLinksCache = /* @__PURE__ */ new WeakMap();
2674
+ /**
2675
+ * A single numbered link, e.g. page `3`. Loads its page and makes it active when
2676
+ * {@link setActive} runs. Carries its {@link index} and its
2677
+ * {@link distanceFromActiveIndex} so a UI can style links by how far they sit
2678
+ * from the current page.
2679
+ *
2680
+ * ```gts
2681
+ * <EachLink @pages={{pages}} as |state|>
2682
+ * {{#each state.links as |link|}}
2683
+ * {{#if link.isReal}}
2684
+ * <button class={{if link.isCurrent "active"}} {{on "click" link.setActive}}>
2685
+ * {{link.text}}
2686
+ * </button>
2687
+ * {{/if}}
2688
+ * {{/each}}
2689
+ * </EachLink>
2690
+ * ```
2691
+ *
2692
+ * @since 5.9.0
2693
+ * @public
2694
+ * @hideconstructor
2695
+ */
2696
+ var RealPaginationLink = class {
2697
+ isReal = true;
2698
+ url;
2699
+ index;
2700
+ isCurrent;
2701
+ distanceFromActiveIndex;
2702
+ /** @internal */
2703
+ constructor(url, index, activeIndex, loadPage) {
2704
+ this.url = url;
2705
+ this.index = index;
2706
+ this.isCurrent = index === activeIndex;
2707
+ this.distanceFromActiveIndex = Math.abs(index - activeIndex);
2708
+ this._loadPage = loadPage;
2709
+ }
2710
+ get text() {
2711
+ return `${this.index}`;
2712
+ }
2713
+ /**
2714
+ * Loads this link's page and makes it the active page on the associated
2715
+ * {@link PaginationState}. It is a stable reference, so it is safe to pass
2716
+ * around as an "action" or "event" handler:
2717
+ *
2718
+ * ```gts
2719
+ * <button {{on "click" link.setActive}}>{{link.text}}</button>
2720
+ * ```
2721
+ */
2722
+ setActive = () => {
2723
+ return this._loadPage(this.url);
2724
+ };
2725
+ };
2726
+ /**
2727
+ * A stand-in for a run of pages that have not been loaded yet, rendered as an
2728
+ * ellipsis between numbered links. It covers an {@link indexRange} rather than a
2729
+ * single page and has no page to navigate to.
2730
+ *
2731
+ * ```gts
2732
+ * <EachLink @pages={{pages}} as |state|>
2733
+ * {{#each state.links as |link|}}
2734
+ * {{#unless link.isReal}}
2735
+ * <span title="{{link.rangeSize}} more pages">{{link.text}}</span>
2736
+ * {{/unless}}
2737
+ * {{/each}}
2738
+ * </EachLink>
2739
+ * ```
2740
+ *
2741
+ * @since 5.9.0
2742
+ * @public
2743
+ * @hideconstructor
2744
+ */
2745
+ var PlaceholderPaginationLink = class {
2746
+ isReal = false;
2747
+ /**
2748
+ * The inclusive `[start, end]` page-number range of not-yet-loaded pages this
2749
+ * placeholder stands in for.
2750
+ */
2751
+ indexRange;
2752
+ /** @internal */
2753
+ activeIndex;
2754
+ text = ".";
2755
+ constructor(index, activeIndex) {
2756
+ this.indexRange = index;
2757
+ this.activeIndex = activeIndex;
2758
+ }
2759
+ /** The number of pages this placeholder covers. */
2760
+ get rangeSize() {
2761
+ return this.indexRange[1] - this.indexRange[0] + 1;
2762
+ }
2763
+ /**
2764
+ * The distance between the active page and the nearest edge of this
2765
+ * placeholder's index range.
2766
+ */
2767
+ get distanceFromActiveIndex() {
2768
+ const [start, end] = this.indexRange;
2769
+ return Math.min(Math.abs(start - this.activeIndex), Math.abs(end - this.activeIndex));
2770
+ }
2771
+ /** @internal */
2772
+ _mergeRange(newRange) {
2773
+ const [oldStart, oldEnd] = this.indexRange;
2774
+ const [newStart, newEnd] = newRange;
2775
+ const mergedRange = [Math.min(oldStart, newStart), Math.max(oldEnd, newEnd)];
2776
+ this.indexRange = mergedRange;
2777
+ }
2778
+ };
2779
+ /**
2780
+ * A relational (`first`/`prev`/`next`/`last`) navigation link, relative to the
2781
+ * active page. Unlike {@link RealPaginationLink} these carry no ordinal index —
2782
+ * they are the only links available for cursor-based pagination, where pages are
2783
+ * chained purely by opaque relational links with no page number or total. They
2784
+ * are also available in numbered pagination as a convenience.
2785
+ *
2786
+ * ```gts
2787
+ * <EachLink @pages={{pages}} as |state|>
2788
+ * {{#if state.prev}}<button {{on "click" state.prev.setActive}}>Previous</button>{{/if}}
2789
+ * {{#if state.next}}<button {{on "click" state.next.setActive}}>Next</button>{{/if}}
2790
+ * </EachLink>
2791
+ * ```
2792
+ *
2793
+ * @since 5.9.0
2794
+ * @public
2795
+ * @hideconstructor
2796
+ */
2797
+ var RelationalPaginationLink = class {
2798
+ isReal = true;
2799
+ rel;
2800
+ url;
2801
+ /**
2802
+ * Whether this link points at the page that is already active — for example
2803
+ * the `first` link while the first page is being viewed. Useful for
2804
+ * disabling the control.
2805
+ */
2806
+ isCurrent;
2807
+ /** @internal */
2808
+ constructor(rel, url, isCurrent, loadPage) {
2809
+ this.rel = rel;
2810
+ this.url = url;
2811
+ this.isCurrent = isCurrent;
2812
+ this._loadPage = loadPage;
2813
+ }
2814
+ get text() {
2815
+ return this.rel;
2816
+ }
2817
+ /**
2818
+ * Loads this link's page and makes it the active page on the associated
2819
+ * {@link PaginationState}. It is a stable reference, so it is safe to pass
2820
+ * around as an "action" or "event" handler:
2821
+ *
2822
+ * ```gts
2823
+ * <button {{on "click" link.setActive}}>{{link.text}}</button>
2824
+ * ```
2825
+ */
2826
+ setActive = () => {
2827
+ return this._loadPage(this.url);
2828
+ };
2829
+ };
2830
+ /**
2831
+ * A member of {@link PaginationLinks.links}: either a numbered
2832
+ * {@link RealPaginationLink} or a {@link PlaceholderPaginationLink} standing in
2833
+ * for a gap. Discriminate with {@link RealPaginationLink.isReal | isReal}:
2834
+ *
2835
+ * ```ts
2836
+ * for (const link of links.links) {
2837
+ * if (link.isReal) {
2838
+ * // numbered link: link.index, link.setActive
2839
+ * } else {
2840
+ * // gap: link.indexRange
2841
+ * }
2842
+ * }
2843
+ * ```
2844
+ */
2845
+ /**
2846
+ * The reactive set of navigation links derived from a {@link PaginationState}.
2847
+ * Where `PaginationState` tracks which pages are loaded and which one is active,
2848
+ * `PaginationLinks` turns that page graph into the links a UI renders to move
2849
+ * between pages.
2850
+ *
2851
+ * It provides two kinds of link:
2852
+ *
2853
+ * - {@link links}: the numbered links, with {@link PlaceholderPaginationLink}
2854
+ * placeholders standing in for gaps of not-yet-loaded pages. Only numbered
2855
+ * collections (where the server exposes page numbers) produce these.
2856
+ * - {@link prev} and {@link next}: the relational links for the active page.
2857
+ * Available in both numbered and cursor-based pagination, and the only links a
2858
+ * cursor-based collection has.
2859
+ * - {@link first} and {@link last}: the relational links to the collection's
2860
+ * edges, when the response exposes them. Usually present on every page —
2861
+ * including the edge page itself, where the link's
2862
+ * {@link RelationalPaginationLink.isCurrent | isCurrent} is `true`.
2863
+ *
2864
+ * Every link updates as pages load and as the active page changes, since they
2865
+ * read straight from the state's shared page graph. To get the links for a
2866
+ * state, use {@link getPaginationLinks}.
2867
+ *
2868
+ * See also:
2869
+ * - {@link RealPaginationLink}
2870
+ * - {@link PlaceholderPaginationLink}
2871
+ * - {@link RelationalPaginationLink}
2872
+ *
2873
+ * @since 5.9.0
2874
+ * @public
2875
+ * @hideconstructor
2876
+ */
2877
+ var PaginationLinks = class {
2878
+ /** @internal */
2879
+ constructor(paginationState) {
2880
+ this.paginationState = paginationState;
2881
+ }
2882
+ /**
2883
+ * The relational `first` link of the collection, or `null` when the active
2884
+ * page's response did not expose one. Unlike {@link prev}/{@link next} it is
2885
+ * usually present on every page — including the first page itself, where the
2886
+ * link's {@link RelationalPaginationLink.isCurrent | isCurrent} is `true`
2887
+ * (useful for disabling the control).
2888
+ */
2889
+ get first() {
2890
+ const activePage = this.paginationState.activePage;
2891
+ const url = activePage?.firstLink;
2892
+ return url ? new RelationalPaginationLink("first", url, url === activePage?.selfLink, this.paginationState.loadPage) : null;
2893
+ }
2894
+ /**
2895
+ * The relational `prev` link for the active page, or `null` at the start of the
2896
+ * collection. Available in both numbered and cursor pagination.
2897
+ */
2898
+ static {
2899
+ decorateMethodV2(this.prototype, "first", [memoized]);
2900
+ }
2901
+ get prev() {
2902
+ const activePage = this.paginationState.activePage;
2903
+ const url = activePage?.prevLink;
2904
+ return url ? new RelationalPaginationLink("prev", url, url === activePage?.selfLink, this.paginationState.loadPage) : null;
2905
+ }
2906
+ /**
2907
+ * The relational `next` link for the active page, or `null` at the end of the
2908
+ * collection. Available in both numbered and cursor pagination.
2909
+ */
2910
+ static {
2911
+ decorateMethodV2(this.prototype, "prev", [memoized]);
2912
+ }
2913
+ get next() {
2914
+ const activePage = this.paginationState.activePage;
2915
+ const url = activePage?.nextLink;
2916
+ return url ? new RelationalPaginationLink("next", url, url === activePage?.selfLink, this.paginationState.loadPage) : null;
2917
+ }
2918
+ /**
2919
+ * The relational `last` link of the collection, or `null` when the active
2920
+ * page's response did not expose one. Mirror of {@link first} for the end of
2921
+ * the collection.
2922
+ */
2923
+ static {
2924
+ decorateMethodV2(this.prototype, "next", [memoized]);
2925
+ }
2926
+ get last() {
2927
+ const activePage = this.paginationState.activePage;
2928
+ const url = activePage?.lastLink;
2929
+ return url ? new RelationalPaginationLink("last", url, url === activePage?.selfLink, this.paginationState.loadPage) : null;
2930
+ }
2931
+ /**
2932
+ * The numbered links and placeholders, derived from the shared page graph.
2933
+ *
2934
+ * Only produced for numbered pagination (where the server exposes page numbers).
2935
+ * Cursor-based collections have no page numbers, so this is empty — use
2936
+ * {@link prev}/{@link next} for cursor navigation.
2937
+ */
2938
+ static {
2939
+ decorateMethodV2(this.prototype, "last", [memoized]);
2940
+ }
2941
+ get links() {
2942
+ const links = [];
2943
+ const cache = this.paginationState.paginationCache;
2944
+ if (!cache || !cache.isNumbered) return links;
2945
+ const { firstPage, totalPages } = cache;
2946
+ const activeIndex = this.paginationState.activePage?.pageNumber ?? 0;
2947
+ if (firstPage) {
2948
+ let previousPage = null;
2949
+ let currentPage = firstPage;
2950
+ while (currentPage) {
2951
+ if (previousPage && currentPage.pageNumber - previousPage.pageNumber > 1) links.push(new PlaceholderPaginationLink([previousPage.pageNumber + 1, currentPage.pageNumber - 1], activeIndex));
2952
+ links.push(new RealPaginationLink(currentPage.selfLink ?? "", currentPage.pageNumber, activeIndex, this.paginationState.loadPage));
2953
+ previousPage = currentPage;
2954
+ currentPage = currentPage.after;
2955
+ }
2956
+ if (previousPage && previousPage.pageNumber < totalPages) links.push(new PlaceholderPaginationLink([previousPage.pageNumber + 1, totalPages], activeIndex));
2957
+ }
2958
+ return links;
2959
+ }
2960
+ static {
2961
+ decorateMethodV2(this.prototype, "links", [memoized]);
2962
+ }
2963
+ };
2964
+ /**
2965
+ * Get the {@link PaginationLinks} for a given {@link PaginationState}. Returns
2966
+ * the same instance for the same state, so repeated calls (for example a
2967
+ * `<Paginate />` component and a separate links component reading the same state)
2968
+ * share one set of links. Keyed by state identity, the same way
2969
+ * {@link getPaginationState} is keyed by request and {@link getRequestState} by
2970
+ * future.
2971
+ *
2972
+ * ```ts
2973
+ * const links = getPaginationLinks(paginationState);
2974
+ *
2975
+ * for (const link of links.links) {
2976
+ * if (link.isReal) {
2977
+ * // render a numbered link, using link.setActive as the click handler
2978
+ * } else {
2979
+ * // render an ellipsis for the gap link.indexRange covers
2980
+ * }
2981
+ * }
2982
+ * ```
2983
+ *
2984
+ * @since 5.9.0
2985
+ * @public
2986
+ */
2987
+ function getPaginationLinks(state) {
2988
+ let links = PaginationLinksCache.get(state);
2989
+ if (!links) {
2990
+ links = new PaginationLinks(state);
2991
+ PaginationLinksCache.set(state, links);
2992
+ }
2993
+ return links;
2994
+ }
2995
+
2996
+ //#endregion
2997
+ //#region src/signals/pagination-subscription.ts
2998
+ /**
2999
+ * The content features available in both pagination modes: the state and
3000
+ * controls of the initial request.
3001
+ */
3002
+ /**
3003
+ * The content features yielded in `'paged'` mode: navigation happens by
3004
+ * loading a specific page.
3005
+ */
3006
+ /**
3007
+ * The content features yielded in `'infinite'` mode: navigation happens by
3008
+ * extending the loaded run at either end.
3009
+ */
3010
+ /**
3011
+ * The full set of content features a {@link PaginationSubscription} builds —
3012
+ * both modes' surfaces. The `<Paginate />` component narrows this to one mode
3013
+ * via {@link PaginationContentFeaturesFor} before yielding.
3014
+ */
3015
+ /**
3016
+ * Resolves a {@link PaginateMode} to the content features it exposes. Mirror of
3017
+ * {@link PaginationStateFor}.
3018
+ */
3019
+ /**
3020
+ * Lifecycle glue for the `<Paginate />` component. Owns the initial
3021
+ * {@link RequestSubscription} (loading/error state, autorefresh, disposal) and
3022
+ * the per-component {@link PaginationState} that it hands to the component.
3023
+ *
3024
+ * @since 5.9.0
3025
+ * @public
3026
+ * @hideconstructor
3027
+ */
3028
+ var PaginationSubscription = class {
3029
+ /** @internal */
3030
+ /** @internal */
3031
+ /** @internal */
3032
+ /**
3033
+ * The Store this subscription subscribes to or the RequestManager
3034
+ * which issues this request.
3035
+ */
3036
+ /**
3037
+ * The wrapped {@link RequestSubscription} monitoring the initial request.
3038
+ * Created eagerly: constructing one consumes reactive state (its own
3039
+ * signals), so building it lazily inside a tracked getter would cause the
3040
+ * getter to invalidate — and the subscription to be recreated, losing its
3041
+ * reloaded request — whenever `retry`/`reload` runs.
3042
+ *
3043
+ * @internal
3044
+ */
3045
+ /**
3046
+ * The first request this subscription saw — the one that keys the
3047
+ * {@link PaginationState} until a navigation resolves to a different
3048
+ * collection. Plain (untracked) because it is written during the first
3049
+ * computation of {@link paginationState}.
3050
+ *
3051
+ * @internal
3052
+ */
3053
+ /**
3054
+ * The request a resolved navigation swapped the {@link PaginationState} to,
3055
+ * when the navigation turned out to target a different collection. A signal:
3056
+ * writing it (always outside of render, from {@link _resolveNavigation})
3057
+ * invalidates {@link paginationState} so the fresh state takes over.
3058
+ *
3059
+ * @internal
3060
+ */
3061
+ /**
3062
+ * The changed request currently being resolved by {@link _resolveNavigation},
3063
+ * both to avoid kicking the same navigation twice and as the latest-wins
3064
+ * guard when several changes race. Untracked bookkeeping.
3065
+ *
3066
+ * @internal
3067
+ */
3068
+ constructor(store, args) {
3069
+ this._args = args;
3070
+ this.store = store;
3071
+ this.isDestroyed = false;
3072
+ this._seedRequest = null;
3073
+ this._navTarget = null;
3074
+ this[DISPOSE] = _DISPOSE$1;
3075
+ this._requestSubscription = createRequestSubscription(store, args);
3076
+ }
3077
+ /**
3078
+ * The per-component pagination state yielded to the component.
3079
+ *
3080
+ * Keyed to the request that started the collection, not the current
3081
+ * `@request` arg: when the arg changes, the existing state keeps rendering
3082
+ * while {@link _resolveNavigation} resolves the new request in the
3083
+ * background. A request that resolves to a page of the same collection is
3084
+ * adopted into this state as the new active page (route-driven navigation,
3085
+ * e.g. the browser back button); one that resolves to a different
3086
+ * collection swaps in a fresh state (a true reset).
3087
+ *
3088
+ * A background `refresh` does not swap the request, so the pagination
3089
+ * state is stable across refreshes.
3090
+ */
3091
+ get paginationState() {
3092
+ const request = this._requestSubscription.request;
3093
+ const active = this._navRequest ?? this._seedRequest;
3094
+ if (!active) {
3095
+ this._seedRequest = request;
3096
+ return getPaginationState(request, this._args.pageHints);
3097
+ }
3098
+ if (request !== active && request !== this._navTarget) {
3099
+ this._navTarget = request;
3100
+ this._resolveNavigation(request);
3101
+ }
3102
+ return getPaginationState(active, this._args.pageHints);
3103
+ }
3104
+ /**
3105
+ * Resolves a changed `@request` arg against the current collection via
3106
+ * {@link PaginationState.adoptPage}: a request that resolves to a page of
3107
+ * the same collection is adopted into the existing state; one that resolves
3108
+ * to a different collection (or arrives before a collection is loaded) swaps
3109
+ * the state for a fresh one keyed to this request.
3110
+ *
3111
+ * A rejected request changes nothing here — the request subscription
3112
+ * already surfaces the failure (error/cancelled states), and the existing
3113
+ * pagination state is kept for recovery. The request is awaited before
3114
+ * `adoptPage` so that rejection and the latest-wins guard are handled
3115
+ * before anything is adopted.
3116
+ *
3117
+ * @internal
3118
+ */
3119
+ static {
3120
+ decorateMethodV2(this.prototype, "paginationState", [memoized]);
3121
+ }
3122
+ async _resolveNavigation(request) {
3123
+ try {
3124
+ await request;
3125
+ } catch {
3126
+ return;
3127
+ }
3128
+ if (this.isDestroyed || this._navTarget !== request) return;
3129
+ const adopted = await this.paginationState.adoptPage(request);
3130
+ if (this.isDestroyed || this._navTarget !== request) return;
3131
+ if (adopted === null) this._navRequest = request;
3132
+ }
3133
+ /**
3134
+ * Whether there is no request or query to monitor, so the component has
3135
+ * nothing to load.
3136
+ */
3137
+ get isIdle() {
3138
+ return this._requestSubscription.isIdle;
3139
+ }
3140
+ /**
3141
+ * Whether the collection is still blocking-loading: no {@link PaginationState}
3142
+ * has finished setting up yet. Only the very first page load (or the reset
3143
+ * to a different collection) blocks here — extending the collection with
3144
+ * `loadNext`/`loadPrev` does not, and neither does a changed `@request` arg
3145
+ * while a collection is already on screen (that is {@link isNavigating}).
3146
+ *
3147
+ * Remains `true` for the moment between the request resolving and the
3148
+ * {@link paginationState} finishing its setup from the response, so that
3149
+ * {@link isSuccess} consumers never see a success state with an empty
3150
+ * pagination surface.
3151
+ */
3152
+ static {
3153
+ decorateMethodV2(this.prototype, "isIdle", [memoized]);
3154
+ }
3155
+ get isLoading() {
3156
+ const { reqState } = this._requestSubscription;
3157
+ return this.paginationState.paginationCache === null && (reqState.isLoading || reqState.isSuccess);
3158
+ }
3159
+ /**
3160
+ * Whether a changed `@request` arg is resolving while a collection is
3161
+ * already on screen — route-driven navigation, e.g. the browser back
3162
+ * button. The content stays rendered (see {@link isSuccess}); consumers can
3163
+ * use this to show a lightweight navigation indicator, the same way a
3164
+ * `loadPage` call surfaces through the active page's request state.
3165
+ */
3166
+ static {
3167
+ decorateMethodV2(this.prototype, "isLoading", [memoized]);
3168
+ }
3169
+ get isNavigating() {
3170
+ return this.paginationState.paginationCache !== null && this._requestSubscription.reqState.isLoading;
3171
+ }
3172
+ /**
3173
+ * The {@link RequestLoadingState} for the initial request, for building UIs
3174
+ * that respond to download progress.
3175
+ */
3176
+ static {
3177
+ decorateMethodV2(this.prototype, "isNavigating", [memoized]);
3178
+ }
3179
+ get loadingState() {
3180
+ return this._requestSubscription.reqState.loadingState;
3181
+ }
3182
+ /**
3183
+ * Whether the component has a set-up {@link paginationState} to render and
3184
+ * the current request did not fail. Stays `true` while a changed `@request`
3185
+ * arg resolves ({@link isNavigating}), so the existing content keeps
3186
+ * rendering instead of falling back to a blocking loading state.
3187
+ */
3188
+ static {
3189
+ decorateMethodV2(this.prototype, "loadingState", [memoized]);
3190
+ }
3191
+ get isSuccess() {
3192
+ const { reqState } = this._requestSubscription;
3193
+ return this.paginationState.paginationCache !== null && !reqState.isError && !reqState.isCancelled;
3194
+ }
3195
+ /**
3196
+ * Whether the initial request was cancelled (aborted).
3197
+ */
3198
+ static {
3199
+ decorateMethodV2(this.prototype, "isSuccess", [memoized]);
3200
+ }
3201
+ get isCancelled() {
3202
+ return this._requestSubscription.reqState.isCancelled;
3203
+ }
3204
+ /**
3205
+ * Whether the initial request rejected with an error.
3206
+ */
3207
+ static {
3208
+ decorateMethodV2(this.prototype, "isCancelled", [memoized]);
3209
+ }
3210
+ get isError() {
3211
+ return this._requestSubscription.reqState.isError;
3212
+ }
3213
+ /**
3214
+ * The error the initial request rejected with, or `null` if it did not reject.
3215
+ */
3216
+ static {
3217
+ decorateMethodV2(this.prototype, "isError", [memoized]);
3218
+ }
3219
+ get reason() {
3220
+ return this._requestSubscription.reqState.reason;
3221
+ }
3222
+ /**
3223
+ * Error features to yield to the error slot of a component
3224
+ */
3225
+ static {
3226
+ decorateMethodV2(this.prototype, "reason", [memoized]);
3227
+ }
3228
+ get errorFeatures() {
3229
+ return {
3230
+ isHidden: this._requestSubscription.isHidden,
3231
+ isOnline: this._requestSubscription.isOnline,
3232
+ retry: this._requestSubscription.retry
3233
+ };
3234
+ }
3235
+ /**
3236
+ * Content features to yield to the content slot of a component
3237
+ */
3238
+ static {
3239
+ decorateMethodV2(this.prototype, "errorFeatures", [memoized]);
3240
+ }
3241
+ get contentFeatures() {
3242
+ const contentFeatures = this._requestSubscription.contentFeatures;
3243
+ const { paginationState } = this;
3244
+ const feat = {
3245
+ ...contentFeatures,
3246
+ isNavigating: this.isNavigating,
3247
+ loadPrev: paginationState.loadPrev,
3248
+ loadNext: paginationState.loadNext,
3249
+ loadPage: paginationState.loadPage
3250
+ };
3251
+ if (feat.isRefreshing) feat.abort = () => {
3252
+ contentFeatures.latestRequest?.abort();
3253
+ };
3254
+ return feat;
3255
+ }
3256
+ /**
3257
+ * The initial request `Future` this subscription is monitoring, i.e. the first
3258
+ * page load. This is the future the {@link paginationState} is built from.
3259
+ *
3260
+ * @internal
3261
+ */
3262
+ static {
3263
+ decorateMethodV2(this.prototype, "contentFeatures", [memoized]);
3264
+ }
3265
+ get request() {
3266
+ return this._requestSubscription.request;
3267
+ }
3268
+ static {
3269
+ decorateMethodV2(this.prototype, "request", [memoized]);
3270
+ }
3271
+ };
3272
+ defineSignal(PaginationSubscription.prototype, "_navRequest", null);
3273
+ /**
3274
+ * Creates the {@link PaginationSubscription} a `<Paginate />` component uses to
3275
+ * manage its request lifecycle and pagination state. Pass the result back into
3276
+ * the component via `@subscription` to manage the lifecycle externally.
3277
+ *
3278
+ * ```ts
3279
+ * const subscription = createPaginationSubscription(store, { request });
3280
+ *
3281
+ * subscription.paginationState; // the per-component PaginationState
3282
+ * subscription[DISPOSE](); // tear down when the owning component unmounts
3283
+ * ```
3284
+ *
3285
+ * @since 5.9.0
3286
+ * @public
3287
+ */
3288
+ function createPaginationSubscription(store, args) {
3289
+ return new PaginationSubscription(store, args);
3290
+ }
3291
+ function upgradeSubscription$1(sub) {
3292
+ return sub;
3293
+ }
3294
+ function _DISPOSE$1() {
3295
+ const self = upgradeSubscription$1(this);
3296
+ self.isDestroyed = true;
3297
+ self._requestSubscription?.[DISPOSE]?.();
3298
+ }
3299
+
3300
+ //#endregion
3301
+ //#region src/signals/pagination-links-subscription.ts
3302
+ /**
3303
+ * The framework-agnostic core of a pagination links component (for example the
3304
+ * `<EachLink />` component of `@warp-drive/ember`): it owns the component
3305
+ * lifecycle, while the links themselves live on the {@link PaginationLinks}
3306
+ * it exposes.
3307
+ *
3308
+ * Given the {@link PagedPaginationState} a `<Paginate />` component is driving,
3309
+ * {@link paginationLinks} derives that state's `PaginationLinks` — the numbered
3310
+ * links (with placeholders for gaps) and the relational
3311
+ * `first`/`prev`/`next`/`last` links a component yields for the consumer to
3312
+ * render. All of them read from the same shared page graph as the
3313
+ * `<Paginate />` component, so they stay in sync as pages load and the active
3314
+ * page changes.
3315
+ *
3316
+ * @since 5.9.0
3317
+ * @public
3318
+ * @hideconstructor
3319
+ */
3320
+ var PaginationLinksSubscription = class {
3321
+ /** @internal */
3322
+ /** @internal */
3323
+ constructor(args) {
3324
+ this._args = args;
3325
+ this.isDestroyed = false;
3326
+ this[DISPOSE] = _DISPOSE;
3327
+ }
3328
+ /**
3329
+ * The {@link PaginationLinks} derived from the {@link PagedPaginationState}
3330
+ * passed as an arg — the surface a links component yields to its consumer:
3331
+ * the numbered {@link PaginationLinks.links | links} (empty for cursor-based
3332
+ * collections) and the relational {@link PaginationLinks.first | first}/
3333
+ * {@link PaginationLinks.prev | prev}/{@link PaginationLinks.next | next}/
3334
+ * {@link PaginationLinks.last | last} links.
3335
+ *
3336
+ * Recomputes when the `pages` arg changes, so a component whose pagination
3337
+ * resets to a different collection derives fresh links automatically.
3338
+ */
3339
+ get paginationLinks() {
3340
+ return getPaginationLinks(this._args.pages);
3341
+ }
3342
+ static {
3343
+ decorateMethodV2(this.prototype, "paginationLinks", [memoized]);
3344
+ }
3345
+ };
3346
+ /**
3347
+ * Creates the {@link PaginationLinksSubscription} a links component (such as
3348
+ * `<EachLink />`) uses to derive its links from a {@link PagedPaginationState}.
3349
+ *
3350
+ * ```ts
3351
+ * const subscription = createPaginationLinksSubscription({ pages: paginationState });
3352
+ *
3353
+ * subscription.paginationLinks; // the derived PaginationLinks
3354
+ * subscription[DISPOSE](); // tear down when the owning component unmounts
3355
+ * ```
3356
+ *
3357
+ * @since 5.9.0
3358
+ * @public
3359
+ */
3360
+ function createPaginationLinksSubscription(args) {
3361
+ return new PaginationLinksSubscription(args);
3362
+ }
3363
+ function upgradeSubscription(sub) {
3364
+ return sub;
3365
+ }
3366
+ function _DISPOSE() {
3367
+ const self = upgradeSubscription(this);
3368
+ self.isDestroyed = true;
3369
+ }
3370
+
3371
+ //#endregion
3372
+ //#region src/signals/promise-state.ts
3373
+ const PromiseCache = /* @__PURE__ */ new WeakMap();
3374
+ /**
3375
+ * The state of a promise in the "pending"
3376
+ * state. This is the default initial state.
3377
+ *
3378
+ */
3379
+ /**
3380
+ * The state of a promise in the "fulfilled" state.
3381
+ * This is the state of a promise that has resolved
3382
+ * successfully.
3383
+ *
3384
+ */
3385
+ /**
3386
+ * The state of a promise in the "rejected" state.
3387
+ * This is the state of a promise that has rejected
3388
+ * with an error.
3389
+ *
3390
+ */
3391
+ /**
3392
+ * The state of a promise. This is the type that is returned
3393
+ * from `getPromiseState`.
3394
+ *
3395
+ * See also:
3396
+ * - {@link PendingPromise}
3397
+ * - {@link ResolvedPromise}
3398
+ * - {@link RejectedPromise}
3399
+ *
3400
+ */
3401
+ const PromiseStateProto = {};
3402
+ defineSignal(PromiseStateProto, "reason", null);
3403
+ defineSignal(PromiseStateProto, "value", null);
3404
+ defineSignal(PromiseStateProto, "result", null);
3405
+ defineSignal(PromiseStateProto, "error", null);
3406
+ defineSignal(PromiseStateProto, "status", "pending");
3407
+ defineSignal(PromiseStateProto, "isPending", true);
3408
+ defineSignal(PromiseStateProto, "isLoading", true);
3409
+ defineSignal(PromiseStateProto, "isSuccess", false);
3410
+ defineSignal(PromiseStateProto, "isError", false);
3411
+ function createPromiseState(promise) {
3412
+ const state = getPromiseResult(promise);
3413
+ const promiseState = Object.create(PromiseStateProto);
3414
+ if (state) {
3415
+ if (state.isError) {
3416
+ promiseState.error = state.result;
3417
+ promiseState.reason = state.result;
3418
+ promiseState.status = "rejected";
3419
+ promiseState.isError = true;
3420
+ promiseState.isPending = false;
3421
+ promiseState.isLoading = false;
3422
+ } else {
3423
+ promiseState.result = state.result;
3424
+ promiseState.value = state.result;
3425
+ promiseState.status = "fulfilled";
3426
+ promiseState.isSuccess = true;
3427
+ promiseState.isPending = false;
3428
+ promiseState.isLoading = false;
3429
+ }
3430
+ } else promise.then((result) => {
3431
+ setPromiseResult(promise, {
3432
+ isError: false,
3433
+ result
3434
+ });
3435
+ promiseState.result = result;
3436
+ promiseState.value = result;
3437
+ promiseState.status = "fulfilled";
3438
+ promiseState.isSuccess = true;
3439
+ promiseState.isPending = false;
3440
+ promiseState.isLoading = false;
3441
+ }, (error) => {
3442
+ setPromiseResult(promise, {
3443
+ isError: true,
3444
+ result: error
3445
+ });
3446
+ promiseState.error = error;
3447
+ promiseState.reason = error;
3448
+ promiseState.status = "rejected";
3449
+ promiseState.isError = true;
3450
+ promiseState.isPending = false;
3451
+ promiseState.isLoading = false;
3452
+ });
3453
+ return promiseState;
3454
+ }
3455
+ const LegacyPromiseProxy = Symbol.for("LegacyPromiseProxy");
3456
+ function isLegacyAwaitable(promise) {
3457
+ return LegacyPromiseProxy in promise && "promise" in promise && promise[LegacyPromiseProxy] === true;
3458
+ }
3459
+ function getPromise(promise) {
3460
+ return isLegacyAwaitable(promise) ? promise.promise : promise;
3461
+ }
3462
+ /**
3463
+ * Returns a reactive state-machine for the provided promise or awaitable.
3464
+ *
3465
+ * Repeat calls to `getPromiseState` with the same promise will return the same state object
3466
+ * making is safe and easy to use in templates and JavaScript code to produce reactive
3467
+ * behaviors around promises.
3468
+ *
3469
+ * `getPromiseState` can be used in both JavaScript and Template contexts.
3470
+ *
3471
+ * ```ts
3472
+ * import { getPromiseState } from '@warp-drive/ember';
3473
+ *
3474
+ * const state = getPromiseState(promise);
3475
+ * ```
3476
+ *
3477
+ * For instance, we could write a getter on a component that updates whenever
3478
+ * the promise state advances or the promise changes, by combining the function
3479
+ * with the use of `@cached`
3480
+ *
3481
+ * ```ts
3482
+ * class Component {
3483
+ * @cached
3484
+ * get title() {
3485
+ * const state = getPromiseState(this.args.request);
3486
+ * if (state.isPending) {
3487
+ * return 'loading...';
3488
+ * }
3489
+ * if (state.isError) { return null; }
3490
+ * return state.result.title;
3491
+ * }
3492
+ * }
3493
+ * ```
3494
+ *
3495
+ * Or in a template as a helper:
3496
+ *
3497
+ * ```gjs
3498
+ * import { getPromiseState } from '@warp-drive/ember';
3499
+ *
3500
+ * <template>
3501
+ * {{#let (getPromiseState @request) as |state|}}
3502
+ * {{#if state.isPending}} <Spinner />
3503
+ * {{else if state.isError}} <ErrorForm @error={{state.error}} />
3504
+ * {{else}}
3505
+ * <h1>{{state.result.title}}</h1>
3506
+ * {{/if}}
3507
+ * {{/let}}
3508
+ * </template>
3509
+ * ```
3510
+ *
3511
+ * If looking to use in a template, consider also the `<Await />` component.
3512
+ *
3513
+ * See also {@link PromiseState}
3514
+ */
3515
+ function getPromiseState(promise) {
3516
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
3517
+ if (!test) throw new Error(`getPromiseState expects to be called with a promise: called with ${String(promise)}`);
3518
+ })(promise);
3519
+ const _promise = getPromise(promise);
3520
+ let state = PromiseCache.get(_promise);
3521
+ if (!state) {
3522
+ state = createPromiseState(_promise);
3523
+ PromiseCache.set(_promise, state);
3524
+ }
3525
+ return state;
3526
+ }
3527
+
3528
+ //#endregion
3529
+ export { ARRAY_SIGNAL as A, createInternalMemo as C, notifyInternalSignal as D, makeInitializer as E, setupSignals as M, waitFor as N, peekInternalSignal as O, willSyncFlushWatchers as P, consumeInternalSignal as S, getOrCreateInternalSignal as T, entangleSignal as _, getPaginationState as a, signal as b, getPaginationCache as c, getRequestState as d, createSignalDescriptor as f, entangleInitiallyStaleSignal as g, defineSignal as h, getPaginationLinks as i, OBJECT_SIGNAL as j, withSignalStore as k, DISPOSE as l, defineNonEnumerableSignal as m, createPaginationLinksSubscription as n, clearPaginationCache as o, defineGate as p, createPaginationSubscription as r, defaultPageHints as s, getPromiseState as t, createRequestSubscription as u, gate as v, createInternalSignal as w, Signals as x, memoized as y };
3530
+ //# sourceMappingURL=-private-zrP4VGAf.js.map