@warp-drive/legacy 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 (468) hide show
  1. package/README.md +6 -0
  2. package/dist/-private-DQ6Iap2t.js +193 -0
  3. package/dist/-private-DQ6Iap2t.js.map +1 -0
  4. package/dist/-private-DccRZQsm.js +904 -0
  5. package/dist/-private-DccRZQsm.js.map +1 -0
  6. package/dist/adapter/-private.d.ts +33 -0
  7. package/dist/adapter/-private.d.ts.map +1 -0
  8. package/dist/adapter/-private.js +3 -1
  9. package/dist/adapter/error.d.ts +2 -0
  10. package/dist/adapter/error.js +425 -311
  11. package/dist/adapter/error.js.map +1 -0
  12. package/{declarations → dist}/adapter/json-api.d.ts +31 -19
  13. package/dist/adapter/json-api.d.ts.map +1 -0
  14. package/dist/adapter/json-api.js +265 -131
  15. package/dist/adapter/json-api.js.map +1 -0
  16. package/dist/adapter/rest.d.ts +2 -0
  17. package/dist/adapter/rest.js +937 -1100
  18. package/dist/adapter/rest.js.map +1 -0
  19. package/dist/adapter-CARrK3-8.d.ts +784 -0
  20. package/dist/adapter-CARrK3-8.d.ts.map +1 -0
  21. package/dist/adapter-eYo2pIuM.js +1130 -0
  22. package/dist/adapter-eYo2pIuM.js.map +1 -0
  23. package/dist/adapter.d.ts +2 -0
  24. package/dist/adapter.js +1 -1251
  25. package/dist/compat/-private.d.ts +2 -0
  26. package/dist/compat/-private.js +3 -1
  27. package/dist/compat/builders.d.ts +169 -0
  28. package/dist/compat/builders.d.ts.map +1 -0
  29. package/dist/compat/builders.js +205 -246
  30. package/dist/compat/builders.js.map +1 -0
  31. package/dist/compat/extensions.d.ts +2 -0
  32. package/dist/compat/extensions.js +271 -233
  33. package/dist/compat/extensions.js.map +1 -0
  34. package/dist/compat/utils.d.ts +151 -0
  35. package/dist/compat/utils.d.ts.map +1 -0
  36. package/dist/compat/utils.js +189 -194
  37. package/dist/compat/utils.js.map +1 -0
  38. package/dist/compat-BbNNmTM-.d.ts +1386 -0
  39. package/dist/compat-BbNNmTM-.d.ts.map +1 -0
  40. package/dist/compat-DcHVxuuZ.js +734 -0
  41. package/dist/compat-DcHVxuuZ.js.map +1 -0
  42. package/dist/compat.d.ts +2 -0
  43. package/dist/compat.js +1 -1019
  44. package/dist/error-CzkyXr1Q.d.ts +435 -0
  45. package/dist/error-CzkyXr1Q.d.ts.map +1 -0
  46. package/dist/errors-BEEsrHbl.js +2134 -0
  47. package/dist/errors-BEEsrHbl.js.map +1 -0
  48. package/dist/extensions-DumNm4dA.d.ts +102 -0
  49. package/dist/extensions-DumNm4dA.d.ts.map +1 -0
  50. package/dist/index.d.ts +243 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +271 -188
  53. package/dist/index.js.map +1 -0
  54. package/dist/json-BXNPTlcH.js +1106 -0
  55. package/dist/json-BXNPTlcH.js.map +1 -0
  56. package/dist/model/-private.d.ts +3 -0
  57. package/dist/model/-private.js +3 -1
  58. package/dist/model/migration-support.d.ts +335 -0
  59. package/dist/model/migration-support.d.ts.map +1 -0
  60. package/dist/model/migration-support.js +506 -564
  61. package/dist/model/migration-support.js.map +1 -0
  62. package/dist/model-62hn5_PD.d.ts +3107 -0
  63. package/dist/model-62hn5_PD.d.ts.map +1 -0
  64. package/dist/model-DcXZdNMu.js +683 -0
  65. package/dist/model-DcXZdNMu.js.map +1 -0
  66. package/dist/model-fragments-DSqu0ptR.js +334 -0
  67. package/dist/model-fragments-DSqu0ptR.js.map +1 -0
  68. package/dist/model-fragments.d.ts +294 -0
  69. package/dist/model-fragments.d.ts.map +1 -0
  70. package/dist/model-fragments.js +2 -75
  71. package/dist/model.d.ts +404 -0
  72. package/dist/model.d.ts.map +1 -0
  73. package/dist/model.js +3 -666
  74. package/{declarations/adapter/rest.d.ts → dist/rest-0NhtexIq.d.ts} +187 -103
  75. package/dist/rest-0NhtexIq.d.ts.map +1 -0
  76. package/dist/runtime--fcdnjmJ-DMTJ0Kb3.js +53 -0
  77. package/dist/runtime--fcdnjmJ-DMTJ0Kb3.js.map +1 -0
  78. package/dist/schema-provider-H4zNXtry.js +1929 -0
  79. package/dist/schema-provider-H4zNXtry.js.map +1 -0
  80. package/{declarations → dist}/serializer/json-api.d.ts +4 -1
  81. package/dist/serializer/json-api.d.ts.map +1 -0
  82. package/dist/serializer/json-api.js +527 -514
  83. package/dist/serializer/json-api.js.map +1 -0
  84. package/{declarations → dist}/serializer/json.d.ts +3 -0
  85. package/dist/serializer/json.d.ts.map +1 -0
  86. package/dist/serializer/json.js +3 -6
  87. package/{declarations/serializer/-private/embedded-records-mixin.d.ts → dist/serializer/rest.d.ts} +56 -1
  88. package/dist/serializer/rest.d.ts.map +1 -0
  89. package/dist/serializer/rest.js +958 -1200
  90. package/dist/serializer/rest.js.map +1 -0
  91. package/dist/serializer/transform.d.ts +313 -0
  92. package/dist/serializer/transform.d.ts.map +1 -0
  93. package/dist/serializer/transform.js +283 -260
  94. package/dist/serializer/transform.js.map +1 -0
  95. package/dist/serializer.d.ts +151 -0
  96. package/dist/serializer.d.ts.map +1 -0
  97. package/dist/serializer.js +205 -208
  98. package/dist/serializer.js.map +1 -0
  99. package/dist/store-C4qYzXei.js +473 -0
  100. package/dist/store-C4qYzXei.js.map +1 -0
  101. package/dist/store.d.ts +13 -0
  102. package/dist/store.d.ts.map +1 -0
  103. package/dist/store.js +1 -635
  104. package/dist/unpkg/dev/-private-CrEyBE-B.js +189 -0
  105. package/dist/unpkg/dev/-private-CrEyBE-B.js.map +1 -0
  106. package/dist/unpkg/dev/-private-vOhxVExH.js +896 -0
  107. package/dist/unpkg/dev/-private-vOhxVExH.js.map +1 -0
  108. package/dist/unpkg/dev/adapter/-private.js +3 -1
  109. package/dist/unpkg/dev/adapter/error.js +424 -310
  110. package/dist/unpkg/dev/adapter/error.js.map +1 -0
  111. package/dist/unpkg/dev/adapter/json-api.js +239 -245
  112. package/dist/unpkg/dev/adapter/json-api.js.map +1 -0
  113. package/dist/unpkg/dev/adapter/rest.js +935 -1098
  114. package/dist/unpkg/dev/adapter/rest.js.map +1 -0
  115. package/dist/unpkg/dev/adapter-oLwyr47q.js +1129 -0
  116. package/dist/unpkg/dev/adapter-oLwyr47q.js.map +1 -0
  117. package/dist/unpkg/dev/adapter.js +1 -1250
  118. package/dist/unpkg/dev/compat/-private.js +3 -1
  119. package/dist/unpkg/dev/compat/builders.js +204 -248
  120. package/dist/unpkg/dev/compat/builders.js.map +1 -0
  121. package/dist/unpkg/dev/compat/extensions.js +270 -232
  122. package/dist/unpkg/dev/compat/extensions.js.map +1 -0
  123. package/dist/unpkg/dev/compat/utils.js +188 -193
  124. package/dist/unpkg/dev/compat/utils.js.map +1 -0
  125. package/dist/unpkg/dev/compat-D48B8sXv.js +825 -0
  126. package/dist/unpkg/dev/compat-D48B8sXv.js.map +1 -0
  127. package/dist/unpkg/dev/compat.js +1 -1145
  128. package/dist/unpkg/dev/errors-8GnRWcxo.js +2127 -0
  129. package/dist/unpkg/dev/errors-8GnRWcxo.js.map +1 -0
  130. package/dist/unpkg/dev/index.js +270 -190
  131. package/dist/unpkg/dev/index.js.map +1 -0
  132. package/dist/unpkg/dev/json-DDJji3V3.js +1104 -0
  133. package/dist/unpkg/dev/json-DDJji3V3.js.map +1 -0
  134. package/dist/unpkg/dev/model/-private.js +3 -1
  135. package/dist/unpkg/dev/model/migration-support.js +483 -537
  136. package/dist/unpkg/dev/model/migration-support.js.map +1 -0
  137. package/dist/unpkg/dev/model-LK7ethC5.js +655 -0
  138. package/dist/unpkg/dev/model-LK7ethC5.js.map +1 -0
  139. package/dist/unpkg/dev/model-fragments-DSqu0ptR.js +334 -0
  140. package/dist/unpkg/dev/model-fragments-DSqu0ptR.js.map +1 -0
  141. package/dist/unpkg/dev/model-fragments.js +2 -75
  142. package/dist/unpkg/dev/model.js +3 -677
  143. package/dist/unpkg/dev/runtime--fcdnjmJ-DMTJ0Kb3.js +53 -0
  144. package/dist/unpkg/dev/runtime--fcdnjmJ-DMTJ0Kb3.js.map +1 -0
  145. package/dist/unpkg/dev/schema-provider-CRzoMoTO.js +1834 -0
  146. package/dist/unpkg/dev/schema-provider-CRzoMoTO.js.map +1 -0
  147. package/dist/unpkg/dev/serializer/json-api.js +514 -629
  148. package/dist/unpkg/dev/serializer/json-api.js.map +1 -0
  149. package/dist/unpkg/dev/serializer/json.js +3 -4
  150. package/dist/unpkg/dev/serializer/rest.js +954 -1197
  151. package/dist/unpkg/dev/serializer/rest.js.map +1 -0
  152. package/dist/unpkg/dev/serializer/transform.js +283 -260
  153. package/dist/unpkg/dev/serializer/transform.js.map +1 -0
  154. package/dist/unpkg/dev/serializer.js +205 -208
  155. package/dist/unpkg/dev/serializer.js.map +1 -0
  156. package/dist/unpkg/dev/store-D_V8-HQl.js +472 -0
  157. package/dist/unpkg/dev/store-D_V8-HQl.js.map +1 -0
  158. package/dist/unpkg/dev/store.js +1 -635
  159. package/dist/unpkg/dev/util-dSKEgQDp.js +12 -0
  160. package/dist/unpkg/dev/util-dSKEgQDp.js.map +1 -0
  161. package/dist/unpkg/dev/utils-DYC9utVJ.js +11 -0
  162. package/dist/unpkg/dev/utils-DYC9utVJ.js.map +1 -0
  163. package/dist/unpkg/dev-deprecated/-private-CrEyBE-B.js +189 -0
  164. package/dist/unpkg/dev-deprecated/-private-CrEyBE-B.js.map +1 -0
  165. package/dist/unpkg/dev-deprecated/-private-vOhxVExH.js +896 -0
  166. package/dist/unpkg/dev-deprecated/-private-vOhxVExH.js.map +1 -0
  167. package/dist/unpkg/dev-deprecated/adapter/-private.js +3 -1
  168. package/dist/unpkg/dev-deprecated/adapter/error.js +424 -310
  169. package/dist/unpkg/dev-deprecated/adapter/error.js.map +1 -0
  170. package/dist/unpkg/dev-deprecated/adapter/json-api.js +239 -245
  171. package/dist/unpkg/dev-deprecated/adapter/json-api.js.map +1 -0
  172. package/dist/unpkg/dev-deprecated/adapter/rest.js +935 -1098
  173. package/dist/unpkg/dev-deprecated/adapter/rest.js.map +1 -0
  174. package/dist/unpkg/dev-deprecated/adapter-oLwyr47q.js +1129 -0
  175. package/dist/unpkg/dev-deprecated/adapter-oLwyr47q.js.map +1 -0
  176. package/dist/unpkg/dev-deprecated/adapter.js +1 -1250
  177. package/dist/unpkg/dev-deprecated/compat/-private.js +3 -1
  178. package/dist/unpkg/dev-deprecated/compat/builders.js +204 -248
  179. package/dist/unpkg/dev-deprecated/compat/builders.js.map +1 -0
  180. package/dist/unpkg/dev-deprecated/compat/extensions.js +270 -232
  181. package/dist/unpkg/dev-deprecated/compat/extensions.js.map +1 -0
  182. package/dist/unpkg/dev-deprecated/compat/utils.js +188 -193
  183. package/dist/unpkg/dev-deprecated/compat/utils.js.map +1 -0
  184. package/dist/unpkg/dev-deprecated/compat-DGSurLh7.js +825 -0
  185. package/dist/unpkg/dev-deprecated/compat-DGSurLh7.js.map +1 -0
  186. package/dist/unpkg/dev-deprecated/compat.js +1 -1145
  187. package/dist/unpkg/dev-deprecated/errors-0ydn94s0.js +2128 -0
  188. package/dist/unpkg/dev-deprecated/errors-0ydn94s0.js.map +1 -0
  189. package/dist/unpkg/dev-deprecated/index.js +270 -189
  190. package/dist/unpkg/dev-deprecated/index.js.map +1 -0
  191. package/dist/unpkg/dev-deprecated/json-DDJji3V3.js +1104 -0
  192. package/dist/unpkg/dev-deprecated/json-DDJji3V3.js.map +1 -0
  193. package/dist/unpkg/dev-deprecated/model/-private.js +3 -1
  194. package/dist/unpkg/dev-deprecated/model/migration-support.js +494 -554
  195. package/dist/unpkg/dev-deprecated/model/migration-support.js.map +1 -0
  196. package/dist/unpkg/dev-deprecated/model-C1ts6Mod.js +660 -0
  197. package/dist/unpkg/dev-deprecated/model-C1ts6Mod.js.map +1 -0
  198. package/dist/unpkg/dev-deprecated/model-fragments-DSqu0ptR.js +334 -0
  199. package/dist/unpkg/dev-deprecated/model-fragments-DSqu0ptR.js.map +1 -0
  200. package/dist/unpkg/dev-deprecated/model-fragments.js +2 -75
  201. package/dist/unpkg/dev-deprecated/model.js +3 -681
  202. package/dist/unpkg/dev-deprecated/runtime--fcdnjmJ-DMTJ0Kb3.js +53 -0
  203. package/dist/unpkg/dev-deprecated/runtime--fcdnjmJ-DMTJ0Kb3.js.map +1 -0
  204. package/dist/unpkg/dev-deprecated/schema-provider-D2ESMsA8.js +1835 -0
  205. package/dist/unpkg/dev-deprecated/schema-provider-D2ESMsA8.js.map +1 -0
  206. package/dist/unpkg/dev-deprecated/serializer/json-api.js +514 -629
  207. package/dist/unpkg/dev-deprecated/serializer/json-api.js.map +1 -0
  208. package/dist/unpkg/dev-deprecated/serializer/json.js +3 -4
  209. package/dist/unpkg/dev-deprecated/serializer/rest.js +954 -1197
  210. package/dist/unpkg/dev-deprecated/serializer/rest.js.map +1 -0
  211. package/dist/unpkg/dev-deprecated/serializer/transform.js +283 -260
  212. package/dist/unpkg/dev-deprecated/serializer/transform.js.map +1 -0
  213. package/dist/unpkg/dev-deprecated/serializer.js +205 -208
  214. package/dist/unpkg/dev-deprecated/serializer.js.map +1 -0
  215. package/dist/unpkg/dev-deprecated/store-BX7GvXC_.js +472 -0
  216. package/dist/unpkg/dev-deprecated/store-BX7GvXC_.js.map +1 -0
  217. package/dist/unpkg/dev-deprecated/store.js +1 -635
  218. package/dist/unpkg/dev-deprecated/util-9mgEBJ3W.js +18 -0
  219. package/dist/unpkg/dev-deprecated/util-9mgEBJ3W.js.map +1 -0
  220. package/dist/unpkg/dev-deprecated/utils-Cl86-e7F.js +17 -0
  221. package/dist/unpkg/dev-deprecated/utils-Cl86-e7F.js.map +1 -0
  222. package/dist/unpkg/prod/-private-B4bxoTuK.js +160 -0
  223. package/dist/unpkg/prod/-private-B4bxoTuK.js.map +1 -0
  224. package/dist/unpkg/prod/-private-SfXkkHKd.js +745 -0
  225. package/dist/unpkg/prod/-private-SfXkkHKd.js.map +1 -0
  226. package/dist/unpkg/prod/adapter/-private.js +3 -1
  227. package/dist/unpkg/prod/adapter/error.js +421 -305
  228. package/dist/unpkg/prod/adapter/error.js.map +1 -0
  229. package/dist/unpkg/prod/adapter/json-api.js +236 -240
  230. package/dist/unpkg/prod/adapter/json-api.js.map +1 -0
  231. package/dist/unpkg/prod/adapter/rest.js +911 -1061
  232. package/dist/unpkg/prod/adapter/rest.js.map +1 -0
  233. package/dist/unpkg/prod/adapter-DQ9UA7FC.js +1111 -0
  234. package/dist/unpkg/prod/adapter-DQ9UA7FC.js.map +1 -0
  235. package/dist/unpkg/prod/adapter.js +1 -1217
  236. package/dist/unpkg/prod/compat/-private.js +3 -1
  237. package/dist/unpkg/prod/compat/builders.js +165 -183
  238. package/dist/unpkg/prod/compat/builders.js.map +1 -0
  239. package/dist/unpkg/prod/compat/extensions.js +258 -222
  240. package/dist/unpkg/prod/compat/extensions.js.map +1 -0
  241. package/dist/unpkg/prod/compat/utils.js +185 -188
  242. package/dist/unpkg/prod/compat/utils.js.map +1 -0
  243. package/dist/unpkg/prod/compat-DxiVkCUb.js +547 -0
  244. package/dist/unpkg/prod/compat-DxiVkCUb.js.map +1 -0
  245. package/dist/unpkg/prod/compat.js +1 -725
  246. package/dist/unpkg/prod/errors-CVXWrUjP.js +1977 -0
  247. package/dist/unpkg/prod/errors-CVXWrUjP.js.map +1 -0
  248. package/dist/unpkg/prod/index.js +249 -146
  249. package/dist/unpkg/prod/index.js.map +1 -0
  250. package/dist/unpkg/prod/json-BD1kRTfB.js +1080 -0
  251. package/dist/unpkg/prod/json-BD1kRTfB.js.map +1 -0
  252. package/dist/unpkg/prod/model/-private.js +3 -1
  253. package/dist/unpkg/prod/model/migration-support.js +479 -530
  254. package/dist/unpkg/prod/model/migration-support.js.map +1 -0
  255. package/dist/unpkg/prod/model-D3WMsNNE.js +603 -0
  256. package/dist/unpkg/prod/model-D3WMsNNE.js.map +1 -0
  257. package/dist/unpkg/prod/model-fragments-DSqu0ptR.js +334 -0
  258. package/dist/unpkg/prod/model-fragments-DSqu0ptR.js.map +1 -0
  259. package/dist/unpkg/prod/model-fragments.js +2 -75
  260. package/dist/unpkg/prod/model.js +3 -592
  261. package/dist/unpkg/prod/runtime--fcdnjmJ-DMTJ0Kb3.js +53 -0
  262. package/dist/unpkg/prod/runtime--fcdnjmJ-DMTJ0Kb3.js.map +1 -0
  263. package/dist/unpkg/prod/schema-provider-_pimTZ3P.js +1622 -0
  264. package/dist/unpkg/prod/schema-provider-_pimTZ3P.js.map +1 -0
  265. package/dist/unpkg/prod/serializer/json-api.js +497 -587
  266. package/dist/unpkg/prod/serializer/json-api.js.map +1 -0
  267. package/dist/unpkg/prod/serializer/json.js +3 -4
  268. package/dist/unpkg/prod/serializer/rest.js +938 -1167
  269. package/dist/unpkg/prod/serializer/rest.js.map +1 -0
  270. package/dist/unpkg/prod/serializer/transform.js +283 -260
  271. package/dist/unpkg/prod/serializer/transform.js.map +1 -0
  272. package/dist/unpkg/prod/serializer.js +205 -208
  273. package/dist/unpkg/prod/serializer.js.map +1 -0
  274. package/dist/unpkg/prod/store-RGGc1ilN.js +392 -0
  275. package/dist/unpkg/prod/store-RGGc1ilN.js.map +1 -0
  276. package/dist/unpkg/prod/store.js +1 -503
  277. package/dist/unpkg/prod/util-dSKEgQDp.js +12 -0
  278. package/dist/unpkg/prod/util-dSKEgQDp.js.map +1 -0
  279. package/dist/unpkg/prod/utils-DYC9utVJ.js +11 -0
  280. package/dist/unpkg/prod/utils-DYC9utVJ.js.map +1 -0
  281. package/dist/unpkg/prod-deprecated/-private-B4bxoTuK.js +160 -0
  282. package/dist/unpkg/prod-deprecated/-private-B4bxoTuK.js.map +1 -0
  283. package/dist/unpkg/prod-deprecated/-private-SfXkkHKd.js +745 -0
  284. package/dist/unpkg/prod-deprecated/-private-SfXkkHKd.js.map +1 -0
  285. package/dist/unpkg/prod-deprecated/adapter/-private.js +3 -1
  286. package/dist/unpkg/prod-deprecated/adapter/error.js +421 -305
  287. package/dist/unpkg/prod-deprecated/adapter/error.js.map +1 -0
  288. package/dist/unpkg/prod-deprecated/adapter/json-api.js +236 -240
  289. package/dist/unpkg/prod-deprecated/adapter/json-api.js.map +1 -0
  290. package/dist/unpkg/prod-deprecated/adapter/rest.js +911 -1061
  291. package/dist/unpkg/prod-deprecated/adapter/rest.js.map +1 -0
  292. package/{declarations/adapter.d.ts → dist/unpkg/prod-deprecated/adapter-DQ9UA7FC.js} +451 -110
  293. package/dist/unpkg/prod-deprecated/adapter-DQ9UA7FC.js.map +1 -0
  294. package/dist/unpkg/prod-deprecated/adapter.js +1 -1217
  295. package/dist/unpkg/prod-deprecated/compat/-private.js +3 -1
  296. package/dist/unpkg/prod-deprecated/compat/builders.js +165 -183
  297. package/dist/unpkg/prod-deprecated/compat/builders.js.map +1 -0
  298. package/dist/unpkg/prod-deprecated/compat/extensions.js +258 -222
  299. package/dist/unpkg/prod-deprecated/compat/extensions.js.map +1 -0
  300. package/dist/unpkg/prod-deprecated/compat/utils.js +185 -188
  301. package/dist/unpkg/prod-deprecated/compat/utils.js.map +1 -0
  302. package/dist/unpkg/prod-deprecated/compat-DxiVkCUb.js +547 -0
  303. package/dist/unpkg/prod-deprecated/compat-DxiVkCUb.js.map +1 -0
  304. package/dist/unpkg/prod-deprecated/compat.js +1 -725
  305. package/dist/unpkg/prod-deprecated/errors-9LXqpfRd.js +1978 -0
  306. package/dist/unpkg/prod-deprecated/errors-9LXqpfRd.js.map +1 -0
  307. package/dist/unpkg/prod-deprecated/index.js +249 -145
  308. package/dist/unpkg/prod-deprecated/index.js.map +1 -0
  309. package/dist/unpkg/prod-deprecated/json-BD1kRTfB.js +1080 -0
  310. package/dist/unpkg/prod-deprecated/json-BD1kRTfB.js.map +1 -0
  311. package/dist/unpkg/prod-deprecated/model/-private.js +3 -1
  312. package/dist/unpkg/prod-deprecated/model/migration-support.js +490 -547
  313. package/dist/unpkg/prod-deprecated/model/migration-support.js.map +1 -0
  314. package/dist/unpkg/prod-deprecated/model-aiVrr1fz.js +604 -0
  315. package/dist/unpkg/prod-deprecated/model-aiVrr1fz.js.map +1 -0
  316. package/dist/unpkg/prod-deprecated/model-fragments-DSqu0ptR.js +334 -0
  317. package/dist/unpkg/prod-deprecated/model-fragments-DSqu0ptR.js.map +1 -0
  318. package/dist/unpkg/prod-deprecated/model-fragments.js +2 -75
  319. package/dist/unpkg/prod-deprecated/model.js +3 -595
  320. package/dist/unpkg/prod-deprecated/runtime--fcdnjmJ-DMTJ0Kb3.js +53 -0
  321. package/dist/unpkg/prod-deprecated/runtime--fcdnjmJ-DMTJ0Kb3.js.map +1 -0
  322. package/dist/unpkg/prod-deprecated/schema-provider-DyfSd9Cv.js +1635 -0
  323. package/dist/unpkg/prod-deprecated/schema-provider-DyfSd9Cv.js.map +1 -0
  324. package/dist/unpkg/prod-deprecated/serializer/json-api.js +497 -587
  325. package/dist/unpkg/prod-deprecated/serializer/json-api.js.map +1 -0
  326. package/dist/unpkg/prod-deprecated/serializer/json.js +3 -4
  327. package/dist/unpkg/prod-deprecated/serializer/rest.js +938 -1167
  328. package/dist/unpkg/prod-deprecated/serializer/rest.js.map +1 -0
  329. package/dist/unpkg/prod-deprecated/serializer/transform.js +283 -260
  330. package/dist/unpkg/prod-deprecated/serializer/transform.js.map +1 -0
  331. package/dist/unpkg/prod-deprecated/serializer.js +205 -208
  332. package/dist/unpkg/prod-deprecated/serializer.js.map +1 -0
  333. package/dist/unpkg/prod-deprecated/store-0L2CkYzh.js +392 -0
  334. package/dist/unpkg/prod-deprecated/store-0L2CkYzh.js.map +1 -0
  335. package/dist/unpkg/prod-deprecated/store.js +1 -503
  336. package/dist/unpkg/prod-deprecated/util-CQQdHX3n.js +14 -0
  337. package/dist/unpkg/prod-deprecated/util-CQQdHX3n.js.map +1 -0
  338. package/dist/unpkg/prod-deprecated/utils-BMI_JwFP.js +13 -0
  339. package/dist/unpkg/prod-deprecated/utils-BMI_JwFP.js.map +1 -0
  340. package/dist/util-Bnx8nm-D.js +29 -0
  341. package/dist/util-Bnx8nm-D.js.map +1 -0
  342. package/dist/utils-ZAytYep8.js +28 -0
  343. package/dist/utils-ZAytYep8.js.map +1 -0
  344. package/package.json +21 -25
  345. package/declarations/adapter/-private/build-url-mixin.d.ts +0 -33
  346. package/declarations/adapter/-private/fastboot-interface.d.ts +0 -8
  347. package/declarations/adapter/-private/utils/continue-on-reject.d.ts +0 -1
  348. package/declarations/adapter/-private/utils/determine-body-promise.d.ts +0 -4
  349. package/declarations/adapter/-private/utils/fetch.d.ts +0 -8
  350. package/declarations/adapter/-private/utils/parse-response-headers.d.ts +0 -1
  351. package/declarations/adapter/-private/utils/serialize-into-hash.d.ts +0 -6
  352. package/declarations/adapter/-private/utils/serialize-query-params.d.ts +0 -5
  353. package/declarations/adapter/-private.d.ts +0 -5
  354. package/declarations/adapter/error.d.ts +0 -215
  355. package/declarations/compat/-private.d.ts +0 -13
  356. package/declarations/compat/builders/find-all.d.ts +0 -35
  357. package/declarations/compat/builders/find-record.d.ts +0 -56
  358. package/declarations/compat/builders/query.d.ts +0 -66
  359. package/declarations/compat/builders/save-record.d.ts +0 -34
  360. package/declarations/compat/builders/utils.d.ts +0 -3
  361. package/declarations/compat/builders.d.ts +0 -14
  362. package/declarations/compat/extensions.d.ts +0 -59
  363. package/declarations/compat/legacy-network-handler/fetch-manager.d.ts +0 -55
  364. package/declarations/compat/legacy-network-handler/identifier-has-id.d.ts +0 -2
  365. package/declarations/compat/legacy-network-handler/legacy-data-fetch.d.ts +0 -11
  366. package/declarations/compat/legacy-network-handler/legacy-data-utils.d.ts +0 -5
  367. package/declarations/compat/legacy-network-handler/legacy-network-handler.d.ts +0 -2
  368. package/declarations/compat/legacy-network-handler/minimum-adapter-interface.d.ts +0 -524
  369. package/declarations/compat/legacy-network-handler/minimum-serializer-interface.d.ts +0 -213
  370. package/declarations/compat/legacy-network-handler/serializer-response.d.ts +0 -6
  371. package/declarations/compat/legacy-network-handler/snapshot-record-array.d.ts +0 -110
  372. package/declarations/compat/legacy-network-handler/snapshot.d.ts +0 -255
  373. package/declarations/compat/utils.d.ts +0 -137
  374. package/declarations/compat.d.ts +0 -157
  375. package/declarations/index.d.ts +0 -102
  376. package/declarations/model/-private/attr.d.ts +0 -170
  377. package/declarations/model/-private/belongs-to.d.ts +0 -174
  378. package/declarations/model/-private/debug/assert-polymorphic-type.d.ts +0 -5
  379. package/declarations/model/-private/errors.d.ts +0 -289
  380. package/declarations/model/-private/has-many.d.ts +0 -162
  381. package/declarations/model/-private/hooks.d.ts +0 -10
  382. package/declarations/model/-private/legacy-relationships-support.d.ts +0 -47
  383. package/declarations/model/-private/model-for-mixin.d.ts +0 -3
  384. package/declarations/model/-private/model-methods.d.ts +0 -39
  385. package/declarations/model/-private/model.d.ts +0 -1228
  386. package/declarations/model/-private/notify-changes.d.ts +0 -4
  387. package/declarations/model/-private/promise-belongs-to.d.ts +0 -40
  388. package/declarations/model/-private/promise-many-array.d.ts +0 -106
  389. package/declarations/model/-private/record-state.d.ts +0 -58
  390. package/declarations/model/-private/references/belongs-to.d.ts +0 -488
  391. package/declarations/model/-private/references/has-many.d.ts +0 -498
  392. package/declarations/model/-private/schema-provider.d.ts +0 -56
  393. package/declarations/model/-private/type-utils.d.ts +0 -57
  394. package/declarations/model/-private/util.d.ts +0 -5
  395. package/declarations/model/-private.d.ts +0 -8
  396. package/declarations/model/migration-support.d.ts +0 -280
  397. package/declarations/model-fragments/extensions/fragment-array.d.ts +0 -16
  398. package/declarations/model-fragments/extensions/fragment.d.ts +0 -15
  399. package/declarations/model-fragments/hooks/model-for.d.ts +0 -20
  400. package/declarations/model-fragments/index.d.ts +0 -5
  401. package/declarations/model-fragments/instance-initializers/fragment-extensions.d.ts +0 -9
  402. package/declarations/model-fragments/utilities/with-array-defaults.d.ts +0 -15
  403. package/declarations/model-fragments/utilities/with-fragment-array-defaults.d.ts +0 -20
  404. package/declarations/model-fragments/utilities/with-fragment-defaults.d.ts +0 -19
  405. package/declarations/model-fragments/utilities/with-legacy.d.ts +0 -3
  406. package/declarations/model-fragments.d.ts +0 -9
  407. package/declarations/model.d.ts +0 -49
  408. package/declarations/serializer/-private/transforms/boolean.d.ts +0 -47
  409. package/declarations/serializer/-private/transforms/date.d.ts +0 -28
  410. package/declarations/serializer/-private/transforms/number.d.ts +0 -29
  411. package/declarations/serializer/-private/transforms/string.d.ts +0 -29
  412. package/declarations/serializer/-private/transforms/transform.d.ts +0 -118
  413. package/declarations/serializer/-private/utils.d.ts +0 -3
  414. package/declarations/serializer/rest.d.ts +0 -51
  415. package/declarations/serializer/transform.d.ts +0 -5
  416. package/declarations/serializer.d.ts +0 -254
  417. package/declarations/store/-private.d.ts +0 -223
  418. package/declarations/store.d.ts +0 -3
  419. package/dist/-private-BG3bMiKp.js +0 -1211
  420. package/dist/errors-Cz5KrzBk.js +0 -2566
  421. package/dist/hooks-D6diaM34.js +0 -74
  422. package/dist/json-ChdEfB0X.js +0 -1259
  423. package/dist/model-for-CqXsIKws.js +0 -221
  424. package/dist/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
  425. package/dist/schema-provider-DJCV_6AF.js +0 -2295
  426. package/dist/serialize-into-hash-DPZYoF-i.js +0 -261
  427. package/dist/unpkg/dev/-private-DtjBbEgy.js +0 -1206
  428. package/dist/unpkg/dev/errors-DmGGJr3T.js +0 -2562
  429. package/dist/unpkg/dev/hooks-CkYiE6Ud.js +0 -73
  430. package/dist/unpkg/dev/json-Cu1LNgmQ.js +0 -1256
  431. package/dist/unpkg/dev/model-for-CqXsIKws.js +0 -221
  432. package/dist/unpkg/dev/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
  433. package/dist/unpkg/dev/schema-provider-DDVYxmUV.js +0 -2186
  434. package/dist/unpkg/dev/serialize-into-hash-B2xDbuo5.js +0 -259
  435. package/dist/unpkg/dev/util-DvanW33H.js +0 -20
  436. package/dist/unpkg/dev/utils-BhvS1iTS.js +0 -8
  437. package/dist/unpkg/dev-deprecated/-private-DtjBbEgy.js +0 -1206
  438. package/dist/unpkg/dev-deprecated/errors-Spt6ubMd.js +0 -2565
  439. package/dist/unpkg/dev-deprecated/hooks-DOXegvhL.js +0 -73
  440. package/dist/unpkg/dev-deprecated/json-Cu1LNgmQ.js +0 -1256
  441. package/dist/unpkg/dev-deprecated/model-for-CqXsIKws.js +0 -221
  442. package/dist/unpkg/dev-deprecated/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
  443. package/dist/unpkg/dev-deprecated/schema-provider-BP6_8N-V.js +0 -2211
  444. package/dist/unpkg/dev-deprecated/serialize-into-hash-B2xDbuo5.js +0 -259
  445. package/dist/unpkg/dev-deprecated/util-CWr5WQOT.js +0 -24
  446. package/dist/unpkg/dev-deprecated/utils-C9PJehtL.js +0 -12
  447. package/dist/unpkg/prod/-private-BdyZaGEh.js +0 -971
  448. package/dist/unpkg/prod/errors-BGVFCBmi.js +0 -2314
  449. package/dist/unpkg/prod/hooks-BztVA_x0.js +0 -41
  450. package/dist/unpkg/prod/json-BWrZ5546.js +0 -1243
  451. package/dist/unpkg/prod/model-for-CqXsIKws.js +0 -221
  452. package/dist/unpkg/prod/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
  453. package/dist/unpkg/prod/schema-provider-DJtD_8jZ.js +0 -1861
  454. package/dist/unpkg/prod/serialize-into-hash-DGlzQteF.js +0 -215
  455. package/dist/unpkg/prod/util-DvanW33H.js +0 -20
  456. package/dist/unpkg/prod/utils-BhvS1iTS.js +0 -8
  457. package/dist/unpkg/prod-deprecated/-private-BdyZaGEh.js +0 -971
  458. package/dist/unpkg/prod-deprecated/errors-CdDaK81x.js +0 -2317
  459. package/dist/unpkg/prod-deprecated/hooks-yId87yyG.js +0 -41
  460. package/dist/unpkg/prod-deprecated/json-BWrZ5546.js +0 -1243
  461. package/dist/unpkg/prod-deprecated/model-for-CqXsIKws.js +0 -221
  462. package/dist/unpkg/prod-deprecated/runtime-BPCpkOf1-BKOwiRJp.js +0 -65
  463. package/dist/unpkg/prod-deprecated/schema-provider-CjX55uSY.js +0 -1904
  464. package/dist/unpkg/prod-deprecated/serialize-into-hash-DGlzQteF.js +0 -215
  465. package/dist/unpkg/prod-deprecated/util-B6cn-i93.js +0 -23
  466. package/dist/unpkg/prod-deprecated/utils-BUWwQwCh.js +0 -11
  467. package/dist/util-Dul6TZts.js +0 -35
  468. package/dist/utils-Cqw9eRj5.js +0 -23
@@ -1,1171 +1,1008 @@
1
- import { getOwner } from '@ember/application';
2
- import { computed } from '@ember/object';
3
- import { Adapter, BuildURLMixin } from '../adapter.js';
4
- import { b as serializeIntoHash, d as determineBodyPromise, g as getFetchFunction, s as serializeQueryParams, p as parseResponseHeaders } from "../serialize-into-hash-B2xDbuo5.js";
5
- import { InvalidError, ServerError, ConflictError, NotFoundError, ForbiddenError, UnauthorizedError, AdapterError, TimeoutError, AbortError } from './error.js';
6
- import { d as decorateMethodV2 } from "../runtime-BPCpkOf1-BKOwiRJp.js";
7
-
8
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
9
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
10
- /* eslint-disable @typescript-eslint/no-unsafe-return */
11
-
1
+ import { n as decorateMethodV2 } from "../runtime--fcdnjmJ-DMTJ0Kb3.js";
2
+ import { n as BuildURLMixin, t as Adapter } from "../adapter-oLwyr47q.js";
3
+ import { AbortError, AdapterError, ConflictError, ForbiddenError, InvalidError, NotFoundError, ServerError, TimeoutError, UnauthorizedError } from "./error.js";
4
+ import { a as determineBodyPromise, i as serializeQueryParams, n as getFetchFunction, o as parseResponseHeaders, t as serializeIntoHash } from "../-private-CrEyBE-B.js";
5
+ import { getOwner } from "@ember/application";
6
+ import { computed } from "@ember/object";
7
+
8
+ //#region src/adapter/rest.ts
9
+ /**
10
+ * The query params built by {@link RESTAdapter.buildQuery | buildQuery} for a
11
+ * `findAll`/`findRecord` request.
12
+ */
13
+ /**
14
+ * The options passed to the native `fetch` API by {@link RESTAdapter._fetchRequest | _fetchRequest}.
15
+ */
16
+ /**
17
+ * The options passed to jQuery's `$.ajax` by {@link RESTAdapter._ajaxRequest | _ajaxRequest}.
18
+ */
19
+ /**
20
+ * A minimal description of an in-flight request, used for building
21
+ * error messages when a request fails.
22
+ */
12
23
  const AdapterWithBuildURLMixin = Adapter.extend(BuildURLMixin);
13
-
14
24
  /**
15
- * :::danger
16
- ⚠️ **This is LEGACY documentation** for a feature that is no longer encouraged to be used.
17
- If starting a new app or thinking of implementing a new adapter, consider writing a
18
- {@link Handler} instead to be used with the {@link RequestManager}
19
- :::
20
-
21
- The REST adapter allows your store to communicate with an HTTP server by
22
- transmitting JSON via XHR.
23
-
24
- This adapter is designed around the idea that the JSON exchanged with
25
- the server should be conventional. It builds URLs in a manner that follows
26
- the structure of most common REST-style web services.
27
-
28
- ## Success and failure
29
-
30
- The REST adapter will consider a success any response with a status code
31
- of the 2xx family ("Success"), as well as 304 ("Not Modified"). Any other
32
- status code will be considered a failure.
33
-
34
- On success, the request promise will be resolved with the full response
35
- payload.
36
-
37
- Failed responses with status code 422 ("Unprocessable Entity") will be
38
- considered "invalid". The response will be discarded, except for the
39
- `errors` key. The request promise will be rejected with a `InvalidError`.
40
- This error object will encapsulate the saved `errors` value.
41
-
42
- Any other status codes will be treated as an "adapter error". The request
43
- promise will be rejected, similarly to the "invalid" case, but with
44
- an instance of `AdapterError` instead.
45
-
46
- ## JSON Structure
47
-
48
- The REST adapter expects the JSON returned from your server to follow
49
- these conventions.
50
-
51
- ### Object Root
52
-
53
- The JSON payload should be an object that contains the record inside a
54
- root property. For example, in response to a `GET` request for
55
- `/posts/1`, the JSON should look like this:
56
-
57
- ```js
58
- {
59
- "posts": {
60
- "id": 1,
61
- "title": "I'm Running to Reform the W3C",
62
- "author": "Yehuda Katz"
63
- }
64
- }
65
- ```
66
-
67
- Similarly, in response to a `GET` request for `/posts`, the JSON should
68
- look like this:
69
-
70
- ```js
71
- {
72
- "posts": [
73
- {
74
- "id": 1,
75
- "title": "I'm Running to Reform the W3C",
76
- "author": "Yehuda Katz"
77
- },
78
- {
79
- "id": 2,
80
- "title": "Rails is omakase",
81
- "author": "D2H"
82
- }
83
- ]
84
- }
85
- ```
86
-
87
- Note that the object root can be pluralized for both a single-object response
88
- and an array response: the REST adapter is not strict on this. Further, if the
89
- HTTP server responds to a `GET` request to `/posts/1` (e.g. the response to a
90
- `findRecord` query) with more than one object in the array, WarpDrive will
91
- only display the object with the matching ID.
92
-
93
- ### Conventional Names
94
-
95
- Attribute names in your JSON payload should be the camelCased versions of
96
- the attributes in your Ember.js models.
97
-
98
- For example, if you have a `Person` model:
99
-
100
- ```js [app/models/person.js]
101
- import { Model, attr } from '@warp-drive/legacy/model';
102
-
103
- export default Model.extend({
104
- firstName: attr('string'),
105
- lastName: attr('string'),
106
- occupation: attr('string')
107
- });
108
- ```
109
-
110
- The JSON returned should look like this:
111
-
112
- ```js
113
- {
114
- "people": {
115
- "id": 5,
116
- "firstName": "Zaphod",
117
- "lastName": "Beeblebrox",
118
- "occupation": "President"
119
- }
120
- }
121
- ```
122
-
123
- #### Relationships
124
-
125
- Relationships are usually represented by ids to the record in the
126
- relationship. The related records can then be sideloaded in the
127
- response under a key for the type.
128
-
129
- ```js
130
- {
131
- "posts": {
132
- "id": 5,
133
- "title": "I'm Running to Reform the W3C",
134
- "author": "Yehuda Katz",
135
- "comments": [1, 2]
136
- },
137
- "comments": [{
138
- "id": 1,
139
- "author": "User 1",
140
- "message": "First!",
141
- }, {
142
- "id": 2,
143
- "author": "User 2",
144
- "message": "Good Luck!",
145
- }]
146
- }
147
- ```
148
-
149
- If the records in the relationship are not known when the response
150
- is serialized it's also possible to represent the relationship as a
151
- URL using the `links` key in the response. WarpDrive will fetch
152
- this URL to resolve the relationship when it is accessed for the
153
- first time.
25
+ * :::danger
26
+ ⚠️ **This is LEGACY documentation** for a feature that is no longer encouraged to be used.
27
+ If starting a new app or thinking of implementing a new adapter, consider writing a
28
+ {@link Handler} instead to be used with the {@link RequestManager}
29
+ :::
154
30
 
155
- ```js
156
- {
157
- "posts": {
158
- "id": 5,
159
- "title": "I'm Running to Reform the W3C",
160
- "author": "Yehuda Katz",
161
- "links": {
162
- "comments": "/posts/5/comments"
163
- }
164
- }
165
- }
166
- ```
31
+ The REST adapter allows your store to communicate with an HTTP server by
32
+ transmitting JSON via XHR.
167
33
 
168
- ### Errors
34
+ This adapter is designed around the idea that the JSON exchanged with
35
+ the server should be conventional. It builds URLs in a manner that follows
36
+ the structure of most common REST-style web services.
169
37
 
170
- If a response is considered a failure, the JSON payload is expected to include
171
- a top-level key `errors`, detailing any specific issues. For example:
38
+ ## Success and failure
172
39
 
173
- ```js
174
- {
175
- "errors": {
176
- "msg": "Something went wrong"
177
- }
178
- }
179
- ```
40
+ The REST adapter will consider a success any response with a status code
41
+ of the 2xx family ("Success"), as well as 304 ("Not Modified"). Any other
42
+ status code will be considered a failure.
180
43
 
181
- This adapter does not make any assumptions as to the format of the `errors`
182
- object. It will simply be passed along as is, wrapped in an instance
183
- of `InvalidError` or `AdapterError`. The serializer can interpret it
184
- afterwards.
44
+ On success, the request promise will be resolved with the full response
45
+ payload.
185
46
 
186
- ## Customization
47
+ Failed responses with status code 422 ("Unprocessable Entity") will be
48
+ considered "invalid". The response will be discarded, except for the
49
+ `errors` key. The request promise will be rejected with a `InvalidError`.
50
+ This error object will encapsulate the saved `errors` value.
187
51
 
188
- ### Endpoint path customization
52
+ Any other status codes will be treated as an "adapter error". The request
53
+ promise will be rejected, similarly to the "invalid" case, but with
54
+ an instance of `AdapterError` instead.
189
55
 
190
- Endpoint paths can be prefixed with a `namespace` by setting the namespace
191
- property on the adapter:
56
+ ## JSON Structure
192
57
 
193
- ```js [app/adapters/application.js]
194
- import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
58
+ The REST adapter expects the JSON returned from your server to follow
59
+ these conventions.
195
60
 
196
- export default class ApplicationAdapter extends RESTAdapter {
197
- namespace = 'api/1';
198
- }
199
- ```
200
- Requests for the `Person` model would now target `/api/1/people/1`.
61
+ ### Object Root
201
62
 
202
- ### Host customization
63
+ The JSON payload should be an object that contains the record inside a
64
+ root property. For example, in response to a `GET` request for
65
+ `/posts/1`, the JSON should look like this:
203
66
 
204
- An adapter can target other hosts by setting the `host` property.
205
-
206
- ```js [app/adapters/application.js]
207
- import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
208
-
209
- export default class ApplicationAdapter extends RESTAdapter {
210
- host = 'https://api.example.com';
211
- }
212
- ```
213
-
214
- ### Headers customization
215
-
216
- Some APIs require HTTP headers, e.g. to provide an API key. Arbitrary
217
- headers can be set as key/value pairs on the `RESTAdapter`'s `headers`
218
- object and WarpDrive will send them along with each ajax request.
219
-
220
-
221
- ```js [app/adapters/application.js]
222
- import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
223
-
224
- export default class ApplicationAdapter extends RESTAdapter {
225
- get headers() {
226
- return {
227
- 'API_KEY': 'secret key',
228
- 'ANOTHER_HEADER': 'Some header value'
229
- };
230
- }
231
- }
232
- ```
233
-
234
- @public
235
- */
236
- class RESTAdapter extends AdapterWithBuildURLMixin {
237
- /**
238
- This property allows ajax to still be used instead when `false`.
239
- @default true
240
- @public
241
- */
242
- useFetch = true;
243
- _defaultContentType = 'application/json; charset=utf-8';
244
- get fastboot() {
245
- // Avoid computed property override deprecation in fastboot as suggested by:
246
- // https://deprecations.emberjs.com/v3.x/#toc_computed-property-override
247
- const fastboot = this._fastboot;
248
- if (fastboot) {
249
- return fastboot;
250
- }
251
- return this._fastboot = getOwner(this).lookup('service:fastboot');
252
- }
253
- static {
254
- decorateMethodV2(this.prototype, "fastboot", [computed()]);
255
- }
256
- set fastboot(value) {
257
- this._fastboot = value;
258
- }
259
-
260
- /**
261
- By default, the RESTAdapter will send the query params sorted alphabetically to the
262
- server.
263
- For example:
264
- ```js
265
- store.query('posts', { sort: 'price', category: 'pets' });
266
- ```
267
- will generate a requests like this `/posts?category=pets&sort=price`, even if the
268
- parameters were specified in a different order.
269
- That way the generated URL will be deterministic and that simplifies caching mechanisms
270
- in the backend.
271
- Setting `sortQueryParams` to a falsey value will respect the original order.
272
- In case you want to sort the query parameters with a different criteria, set
273
- `sortQueryParams` to your custom sort function.
274
- ```js [app/adapters/application.js]
275
- import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
276
- export default class ApplicationAdapter extends RESTAdapter {
277
- sortQueryParams(params) {
278
- let sortedKeys = Object.keys(params).sort().reverse();
279
- let len = sortedKeys.length, newParams = {};
280
- for (let i = 0; i < len; i++) {
281
- newParams[sortedKeys[i]] = params[sortedKeys[i]];
282
- }
283
- return newParams;
284
- }
285
- }
286
- ```
287
- @public
288
- */
289
- sortQueryParams(obj) {
290
- const keys = Object.keys(obj);
291
- const len = keys.length;
292
- if (len < 2) {
293
- return obj;
294
- }
295
- const newQueryParams = {};
296
- const sortedKeys = keys.sort();
297
- for (let i = 0; i < len; i++) {
298
- newQueryParams[sortedKeys[i]] = obj[sortedKeys[i]];
299
- }
300
- return newQueryParams;
301
- }
302
-
303
- /**
304
- By default the RESTAdapter will send each find request coming from a `store.find`
305
- or from accessing a relationship separately to the server. If your server supports passing
306
- ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests
307
- within a single runloop.
308
- For example, if you have an initial payload of:
309
- ```javascript
310
- {
311
- post: {
312
- id: 1,
313
- comments: [1, 2]
314
- }
315
- }
316
- ```
317
- By default calling `post.comments` will trigger the following requests(assuming the
318
- comments haven't been loaded before):
319
- ```
320
- GET /comments/1
321
- GET /comments/2
322
- ```
323
- If you set coalesceFindRequests to `true` it will instead trigger the following request:
324
- ```
325
- GET /comments?ids[]=1&ids[]=2
326
- ```
327
- Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`
328
- relationships accessed within the same runloop. If you set `coalesceFindRequests: true`
329
- ```javascript
330
- store.findRecord('comment', 1);
331
- store.findRecord('comment', 2);
332
- ```
333
- will also send a request to: `GET /comments?ids[]=1&ids[]=2`
334
- Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app
335
- `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.
336
- @public
337
- */
338
- get coalesceFindRequests() {
339
- const coalesceFindRequests = this._coalesceFindRequests;
340
- if (typeof coalesceFindRequests === 'boolean') {
341
- return coalesceFindRequests;
342
- }
343
- return this._coalesceFindRequests = false;
344
- }
345
- set coalesceFindRequests(value) {
346
- this._coalesceFindRequests = value;
347
- }
348
-
349
- /**
350
- Endpoint paths can be prefixed with a `namespace` by setting the namespace
351
- property on the adapter:
352
- ```js [app/adapters/application.js]
353
- import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
354
- export default class ApplicationAdapter extends RESTAdapter {
355
- namespace = 'api/1';
356
- }
357
- ```
358
- Requests for the `Post` model would now target `/api/1/post/`.
359
- @public
360
- */
361
-
362
- /**
363
- An adapter can target other hosts by setting the `host` property.
364
- ```js [app/adapters/application.js]
365
- import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
366
- export default class ApplicationAdapter extends RESTAdapter {
367
- host = 'https://api.example.com';
368
- }
369
- ```
370
- Requests for the `Post` model would now target `https://api.example.com/post/`.
371
- @public
372
- */
67
+ ```js
68
+ {
69
+ "posts": {
70
+ "id": 1,
71
+ "title": "I'm Running to Reform the W3C",
72
+ "author": "Yehuda Katz"
73
+ }
74
+ }
75
+ ```
76
+
77
+ Similarly, in response to a `GET` request for `/posts`, the JSON should
78
+ look like this:
79
+
80
+ ```js
81
+ {
82
+ "posts": [
83
+ {
84
+ "id": 1,
85
+ "title": "I'm Running to Reform the W3C",
86
+ "author": "Yehuda Katz"
87
+ },
88
+ {
89
+ "id": 2,
90
+ "title": "Rails is omakase",
91
+ "author": "D2H"
92
+ }
93
+ ]
94
+ }
95
+ ```
373
96
 
374
- /**
375
- Some APIs require HTTP headers, e.g. to provide an API
376
- key. Arbitrary headers can be set as key/value pairs on the
377
- `RESTAdapter`'s `headers` object and WarpDrive will send them
378
- along with each ajax request..
379
- ```js [app/adapters/application.js]
380
- import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
381
- export default class ApplicationAdapter extends RESTAdapter {
382
- get headers() {
383
- return {
384
- 'API_KEY': 'secret key',
385
- 'ANOTHER_HEADER': 'Some header value'
386
- };
387
- }
388
- }
389
- ```
390
- @public
391
- */
97
+ Note that the object root can be pluralized for both a single-object response
98
+ and an array response: the REST adapter is not strict on this. Further, if the
99
+ HTTP server responds to a `GET` request to `/posts/1` (e.g. the response to a
100
+ `findRecord` query) with more than one object in the array, WarpDrive will
101
+ only display the object with the matching ID.
392
102
 
393
- /**
394
- Called by the store in order to fetch the JSON for a given
395
- type and ID.
396
- The `findRecord` method makes an Ajax request to a URL computed by
397
- `buildURL`, and returns a promise for the resulting payload.
398
- This method performs an HTTP `GET` request with the id provided as part of the query string.
399
- @since 1.13.0
400
- @public
401
- */
402
- findRecord(store, type, id, snapshot) {
403
- const url = this.buildURL(type.modelName, id, snapshot, 'findRecord');
404
- const query = this.buildQuery(snapshot);
405
- return this.ajax(url, 'GET', {
406
- data: query
407
- });
408
- }
103
+ ### Conventional Names
409
104
 
410
- /**
411
- Called by the store in order to fetch a JSON array for all
412
- of the records for a given type.
413
- The `findAll` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
414
- promise for the resulting payload.
415
- @public
416
- */
417
- findAll(store, type, neverUsed, snapshotRecordArray) {
418
- const query = this.buildQuery(snapshotRecordArray);
419
- const url = this.buildURL(type.modelName, null, snapshotRecordArray, 'findAll');
420
- return this.ajax(url, 'GET', {
421
- data: query
422
- });
423
- }
105
+ Attribute names in your JSON payload should be the camelCased versions of
106
+ the attributes in your Ember.js models.
424
107
 
425
- /**
426
- Called by the store in order to fetch a JSON array for
427
- the records that match a particular query.
428
- The `query` method makes an Ajax (HTTP GET) request to a URL
429
- computed by `buildURL`, and returns a promise for the resulting
430
- payload.
431
- The `query` argument is a simple JavaScript object that will be passed directly
432
- to the server as parameters.
433
- @public
434
- */
435
- query(store, type, query) {
436
- const url = this.buildURL(type.modelName, null, null, 'query', query);
437
- if (this.sortQueryParams) {
438
- query = this.sortQueryParams(query);
439
- }
440
- return this.ajax(url, 'GET', {
441
- data: query
442
- });
443
- }
108
+ For example, if you have a `Person` model:
444
109
 
445
- /**
446
- Called by the store in order to fetch a JSON object for
447
- the record that matches a particular query.
448
- The `queryRecord` method makes an Ajax (HTTP GET) request to a URL
449
- computed by `buildURL`, and returns a promise for the resulting
450
- payload.
451
- The `query` argument is a simple JavaScript object that will be passed directly
452
- to the server as parameters.
453
- @since 1.13.0
454
- @public
455
- */
456
- queryRecord(store, type, query, adapterOptions) {
457
- const url = this.buildURL(type.modelName, null, null, 'queryRecord', query);
458
- if (this.sortQueryParams) {
459
- query = this.sortQueryParams(query);
460
- }
461
- return this.ajax(url, 'GET', {
462
- data: query
463
- });
464
- }
110
+ ```js [app/models/person.js]
111
+ import { Model, attr } from '@warp-drive/legacy/model';
465
112
 
466
- /**
467
- Called by the store in order to fetch several records together if `coalesceFindRequests` is true
468
- For example, if the original payload looks like:
469
- ```js
470
- {
471
- "id": 1,
472
- "title": "Rails is omakase",
473
- "comments": [ 1, 2, 3 ]
474
- }
475
- ```
476
- The IDs will be passed as a URL-encoded Array of IDs, in this form:
477
- ```
478
- ids[]=1&ids[]=2&ids[]=3
479
- ```
480
- Many servers, such as Rails and PHP, will automatically convert this URL-encoded array
481
- into an Array for you on the server-side. If you want to encode the
482
- IDs, differently, just override this (one-line) method.
483
- The `findMany` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
484
- promise for the resulting payload.
485
- @public
486
- */
487
- findMany(store, type, ids, snapshots) {
488
- const url = this.buildURL(type.modelName, ids, snapshots, 'findMany');
489
- return this.ajax(url, 'GET', {
490
- data: {
491
- ids: ids
492
- }
493
- });
494
- }
113
+ export default Model.extend({
114
+ firstName: attr('string'),
115
+ lastName: attr('string'),
116
+ occupation: attr('string')
117
+ });
118
+ ```
495
119
 
496
- /**
497
- Called by the store in order to fetch a JSON array for
498
- the unloaded records in a has-many relationship that were originally
499
- specified as a URL (inside of `links`).
500
- For example, if your original payload looks like this:
501
- ```js
502
- {
503
- "post": {
504
- "id": 1,
505
- "title": "Rails is omakase",
506
- "links": { "comments": "/posts/1/comments" }
507
- }
508
- }
509
- ```
510
- This method will be called with the parent record and `/posts/1/comments`.
511
- The `findHasMany` method will make an Ajax (HTTP GET) request to the originally specified URL.
512
- The format of your `links` value will influence the final request URL via the `urlPrefix` method:
513
- * Links beginning with `//`, `http://`, `https://`, will be used as is, with no further manipulation.
514
- * Links beginning with a single `/` will have the current adapter's `host` value prepended to it.
515
- * Links with no beginning `/` will have a parentURL prepended to it, via the current adapter's `buildURL`.
516
- @public
517
- */
518
- findHasMany(store, snapshot, url, relationship) {
519
- const id = snapshot.id;
520
- const type = snapshot.modelName;
521
- (test => {
522
- if (!test) {
523
- throw new Error(`Attempted to fetch the hasMany relationship for ${type}, but the record has no id`);
524
- }
525
- })(typeof id === 'string' && id.length > 0);
526
- url = this.urlPrefix(url, this.buildURL(type, id, snapshot, 'findHasMany'));
527
- return this.ajax(url, 'GET');
528
- }
120
+ The JSON returned should look like this:
529
121
 
530
- /**
531
- Called by the store in order to fetch the JSON for the unloaded record in a
532
- belongs-to relationship that was originally specified as a URL (inside of
533
- `links`).
534
- For example, if your original payload looks like this:
535
- ```js
536
- {
537
- "person": {
538
- "id": 1,
539
- "name": "Tom Dale",
540
- "links": { "group": "/people/1/group" }
541
- }
542
- }
543
- ```
544
- This method will be called with the parent record and `/people/1/group`.
545
- The `findBelongsTo` method will make an Ajax (HTTP GET) request to the originally specified URL.
546
- The format of your `links` value will influence the final request URL via the `urlPrefix` method:
547
- * Links beginning with `//`, `http://`, `https://`, will be used as is, with no further manipulation.
548
- * Links beginning with a single `/` will have the current adapter's `host` value prepended to it.
549
- * Links with no beginning `/` will have a parentURL prepended to it, via the current adapter's `buildURL`.
550
- @public
551
- */
552
- findBelongsTo(store, snapshot, url, relationship) {
553
- const id = snapshot.id;
554
- const type = snapshot.modelName;
555
- (test => {
556
- if (!test) {
557
- throw new Error(`Attempted to fetch the belongsTo relationship for ${type}, but the record has no id`);
558
- }
559
- })(typeof id === 'string' && id.length > 0);
560
- url = this.urlPrefix(url, this.buildURL(type, id, snapshot, 'findBelongsTo'));
561
- return this.ajax(url, 'GET');
562
- }
122
+ ```js
123
+ {
124
+ "people": {
125
+ "id": 5,
126
+ "firstName": "Zaphod",
127
+ "lastName": "Beeblebrox",
128
+ "occupation": "President"
129
+ }
130
+ }
131
+ ```
132
+
133
+ #### Relationships
134
+
135
+ Relationships are usually represented by ids to the record in the
136
+ relationship. The related records can then be sideloaded in the
137
+ response under a key for the type.
138
+
139
+ ```js
140
+ {
141
+ "posts": {
142
+ "id": 5,
143
+ "title": "I'm Running to Reform the W3C",
144
+ "author": "Yehuda Katz",
145
+ "comments": [1, 2]
146
+ },
147
+ "comments": [{
148
+ "id": 1,
149
+ "author": "User 1",
150
+ "message": "First!",
151
+ }, {
152
+ "id": 2,
153
+ "author": "User 2",
154
+ "message": "Good Luck!",
155
+ }]
156
+ }
157
+ ```
158
+
159
+ If the records in the relationship are not known when the response
160
+ is serialized it's also possible to represent the relationship as a
161
+ URL using the `links` key in the response. WarpDrive will fetch
162
+ this URL to resolve the relationship when it is accessed for the
163
+ first time.
164
+
165
+ ```js
166
+ {
167
+ "posts": {
168
+ "id": 5,
169
+ "title": "I'm Running to Reform the W3C",
170
+ "author": "Yehuda Katz",
171
+ "links": {
172
+ "comments": "/posts/5/comments"
173
+ }
174
+ }
175
+ }
176
+ ```
563
177
 
564
- /**
565
- Called by the store when a newly created record is
566
- saved via the `save` method on a model record instance.
567
- The `createRecord` method serializes the record and makes an Ajax (HTTP POST) request
568
- to a URL computed by `buildURL`.
569
- See `serialize` for information on how to customize the serialized form
570
- of a record.
571
- @public
572
- */
573
- createRecord(store, type, snapshot) {
574
- const url = this.buildURL(type.modelName, null, snapshot, 'createRecord');
575
- const data = serializeIntoHash(store, type, snapshot);
576
- return this.ajax(url, 'POST', {
577
- data
578
- });
579
- }
178
+ ### Errors
580
179
 
581
- /**
582
- Called by the store when an existing record is saved
583
- via the `save` method on a model record instance.
584
- The `updateRecord` method serializes the record and makes an Ajax (HTTP PUT) request
585
- to a URL computed by `buildURL`.
586
- See `serialize` for information on how to customize the serialized form
587
- of a record.
588
- @public
589
- */
590
- updateRecord(store, schema, snapshot) {
591
- const data = serializeIntoHash(store, schema, snapshot, {});
592
- const type = snapshot.modelName;
593
- const id = snapshot.id;
594
- (test => {
595
- if (!test) {
596
- throw new Error(`Attempted to update the ${type} record, but the record has no id`);
597
- }
598
- })(typeof id === 'string' && id.length > 0);
599
- const url = this.buildURL(type, id, snapshot, 'updateRecord');
600
- return this.ajax(url, 'PUT', {
601
- data
602
- });
603
- }
180
+ If a response is considered a failure, the JSON payload is expected to include
181
+ a top-level key `errors`, detailing any specific issues. For example:
604
182
 
605
- /**
606
- Called by the store when a record is deleted.
607
- The `deleteRecord` method makes an Ajax (HTTP DELETE) request to a URL computed by `buildURL`.
608
- @public
609
- */
610
- deleteRecord(store, schema, snapshot) {
611
- const type = snapshot.modelName;
612
- const id = snapshot.id;
613
- (test => {
614
- if (!test) {
615
- throw new Error(`Attempted to delete the ${type} record, but the record has no id`);
616
- }
617
- })(typeof id === 'string' && id.length > 0);
618
- return this.ajax(this.buildURL(type, id, snapshot, 'deleteRecord'), 'DELETE');
619
- }
183
+ ```js
184
+ {
185
+ "errors": {
186
+ "msg": "Something went wrong"
187
+ }
188
+ }
189
+ ```
620
190
 
621
- /**
622
- @private
623
- */
624
- _stripIDFromURL(store, snapshot) {
625
- const type = snapshot.modelName;
626
- const id = snapshot.id;
627
- (test => {
628
- if (!test) {
629
- throw new Error(`Attempted to strip the url from the ${type} record for coalescing, but the record has no id`);
630
- }
631
- })(typeof id === 'string' && id.length > 0);
632
- const url = this.buildURL(type, id, snapshot);
633
- const expandedURL = url.split('/');
634
- // Case when the url is of the format ...something/:id
635
- // We are decodeURIComponent-ing the lastSegment because if it represents
636
- // the id, it has been encodeURIComponent-ified within `buildURL`. If we
637
- // don't do this, then records with id having special characters are not
638
- // coalesced correctly (see GH #4190 for the reported bug)
639
- const lastSegment = expandedURL[expandedURL.length - 1];
640
- if (decodeURIComponent(lastSegment) === id) {
641
- expandedURL[expandedURL.length - 1] = '';
642
- } else if (id && endsWith(lastSegment, '?id=' + id)) {
643
- //Case when the url is of the format ...something?id=:id
644
- expandedURL[expandedURL.length - 1] = lastSegment.substring(0, lastSegment.length - id.length - 1);
645
- }
646
- return expandedURL.join('/');
647
- }
191
+ This adapter does not make any assumptions as to the format of the `errors`
192
+ object. It will simply be passed along as is, wrapped in an instance
193
+ of `InvalidError` or `AdapterError`. The serializer can interpret it
194
+ afterwards.
648
195
 
649
- // http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
650
- maxURLLength = 2048;
196
+ ## Customization
651
197
 
652
- /**
653
- Organize records into groups, each of which is to be passed to separate
654
- calls to `findMany`.
655
- This implementation groups together records that have the same base URL but
656
- differing ids. For example `/comments/1` and `/comments/2` will be grouped together
657
- because we know findMany can coalesce them together as `/comments?ids[]=1&ids[]=2`
658
- It also supports urls where ids are passed as a query param, such as `/comments?id=1`
659
- but not those where there is more than 1 query param such as `/comments?id=2&name=David`
660
- Currently only the query param of `id` is supported. If you need to support others, please
661
- override this or the `_stripIDFromURL` method.
662
- It does not group records that have differing base urls, such as for example: `/posts/1/comments/2`
663
- and `/posts/2/comments/3`
664
- @public
665
- @return an array of arrays of records, each of which is to be
666
- loaded separately by `findMany`.
667
- */
668
- groupRecordsForFindMany(store, snapshots) {
669
- const groups = new Map();
670
- const maxURLLength = this.maxURLLength;
671
- snapshots.forEach(snapshot => {
672
- const baseUrl = this._stripIDFromURL(store, snapshot);
673
- if (!groups.has(baseUrl)) {
674
- groups.set(baseUrl, []);
675
- }
676
- groups.get(baseUrl).push(snapshot);
677
- });
678
- const groupsArray = [];
679
- groups.forEach((group, key) => {
680
- const paramNameLength = '&ids%5B%5D='.length;
681
- const splitGroups = splitGroupToFitInUrl(store, this, group, maxURLLength, paramNameLength);
682
- splitGroups.forEach(splitGroup => groupsArray.push(splitGroup));
683
- });
684
- return groupsArray;
685
- }
198
+ ### Endpoint path customization
686
199
 
687
- /**
688
- Takes an ajax response, and returns the json payload or an error.
689
- By default this hook just returns the json payload passed to it.
690
- You might want to override it in two cases:
691
- 1. Your API might return useful results in the response headers.
692
- Response headers are passed in as the second argument.
693
- 2. Your API might return errors as successful responses with status code
694
- 200 and an Errors text or object. You can return a `InvalidError` or a
695
- `AdapterError` (or a sub class) from this hook and it will automatically
696
- reject the promise and put your record into the invalid or error state.
697
- Returning a `InvalidError` from this method will cause the
698
- record to transition into the `invalid` state and make the
699
- `errors` object available on the record. When returning an
700
- `InvalidError` the store will attempt to normalize the error data
701
- returned from the server using the serializer's `extractErrors`
702
- method.
703
- @since 1.13.0
704
- @public
705
- */
706
- handleResponse(status, headers, payload, requestData) {
707
- if (this.isSuccess(status, headers, payload)) {
708
- return payload;
709
- } else if (this.isInvalid(status, headers, payload)) {
710
- // @ts-expect-error needs cast to ApiError
711
- return new InvalidError(typeof payload === 'object' && 'errors' in payload ? payload.errors : undefined);
712
- }
713
- const errors = this.normalizeErrorResponse(status, headers, payload);
714
- const detailedMessage = this.generatedDetailedMessage(status, headers, payload, requestData);
715
- switch (status) {
716
- case 401:
717
- return new UnauthorizedError(errors, detailedMessage);
718
- case 403:
719
- return new ForbiddenError(errors, detailedMessage);
720
- case 404:
721
- return new NotFoundError(errors, detailedMessage);
722
- case 409:
723
- return new ConflictError(errors, detailedMessage);
724
- default:
725
- if (status >= 500) {
726
- return new ServerError(errors, detailedMessage);
727
- }
728
- }
729
- return new AdapterError(errors, detailedMessage);
730
- }
200
+ Endpoint paths can be prefixed with a `namespace` by setting the namespace
201
+ property on the adapter:
731
202
 
732
- /**
733
- Default `handleResponse` implementation uses this hook to decide if the
734
- response is a success.
735
- @since 1.13.0
736
- @public
737
- */
738
- isSuccess(status, _headers, _payload) {
739
- return status >= 200 && status < 300 || status === 304;
740
- }
203
+ ```js [app/adapters/application.js]
204
+ import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
741
205
 
742
- /**
743
- Default `handleResponse` implementation uses this hook to decide if the
744
- response is an invalid error.
745
- @since 1.13.0
746
- @public
747
- */
748
- isInvalid(status, _headers, _payload) {
749
- return status === 422;
750
- }
206
+ export default class ApplicationAdapter extends RESTAdapter {
207
+ namespace = 'api/1';
208
+ }
209
+ ```
210
+ Requests for the `Person` model would now target `/api/1/people/1`.
751
211
 
752
- /**
753
- Takes a URL, an HTTP method and a hash of data, and makes an
754
- HTTP request.
755
- When the server responds with a payload, WarpDrive will call into `extractSingle`
756
- or `extractArray` (depending on whether the original query was for one record or
757
- many records).
758
- By default, `ajax` method has the following behavior:
759
- * It sets the response `dataType` to `"json"`
760
- * If the HTTP method is not `"GET"`, it sets the `Content-Type` to be
761
- `application/json; charset=utf-8`
762
- * If the HTTP method is not `"GET"`, it stringifies the data passed in. The
763
- data is the serialized record in the case of a save.
764
- * Registers success and failure handlers.
765
- @private
766
- */
767
- async ajax(url, type, options = {}) {
768
- const requestData = {
769
- url: url,
770
- method: type
771
- };
772
- if (this.useFetch) {
773
- // @ts-expect-error poorly typed
774
- const hash = this.ajaxOptions(url, type, options);
775
- const response = await this._fetchRequest(hash);
776
- const payload = await determineBodyPromise(response, requestData);
777
- if (response.ok && !(payload instanceof Error)) {
778
- return fetchSuccessHandler(this, payload, response, requestData);
779
- } else {
780
- // eslint-disable-next-line @typescript-eslint/only-throw-error
781
- throw fetchErrorHandler(this, payload, response, null, requestData);
782
- }
783
- } else {
784
- return execjQAjax(this, requestData, options);
785
- }
786
- }
212
+ ### Host customization
787
213
 
788
- /**
789
- @private
790
- @param options jQuery ajax options to be used for the ajax request
791
- */
792
- _ajaxRequest(options) {
793
- (test => {
794
- if (!test) {
795
- throw new Error('You must install jQuery globally when `useFetch` is false');
796
- }
797
- })(typeof jQuery !== 'undefined');
798
- void jQuery.ajax(options);
799
- }
800
- /**
801
- @private
802
- */
803
- _fetchRequest(options) {
804
- const fetchFunction = getFetchFunction();
805
- return fetchFunction(options.url, options);
806
- }
807
- /**
808
- @private
809
- */
810
- _ajax(options) {
811
- if (this.useFetch) {
812
- void this._fetchRequest(options);
813
- } else {
814
- this._ajaxRequest(options);
815
- }
816
- }
214
+ An adapter can target other hosts by setting the `host` property.
817
215
 
818
- /**
819
- @private
820
- */
821
- ajaxOptions(url, method, options) {
822
- let reqOptions = Object.assign({
823
- url,
824
- method,
825
- type: method
826
- }, options);
827
- if (this.headers !== undefined) {
828
- // @ts-expect-error poorly typed
829
- reqOptions.headers = {
830
- ...this.headers,
831
- ...reqOptions.headers
832
- };
833
- } else if (!options.headers) {
834
- reqOptions.headers = {};
835
- }
216
+ ```js [app/adapters/application.js]
217
+ import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
836
218
 
837
- // @ts-expect-error poorly typed
838
- const contentType = reqOptions.contentType || this._defaultContentType;
839
- if (this.useFetch) {
840
- // @ts-expect-error poorly typed
841
- if (reqOptions.data && reqOptions.type !== 'GET' && reqOptions.headers) {
842
- if (!reqOptions.headers['Content-Type'] && !reqOptions.headers['content-type']) {
843
- reqOptions.headers['content-type'] = contentType;
844
- }
845
- }
846
- // @ts-expect-error poorly typed
847
- reqOptions = fetchOptions(reqOptions);
848
- } else {
849
- // GET requests without a body should not have a content-type header
850
- // and may be unexpected by a server
851
- // @ts-expect-error poorly typed
852
- if (reqOptions.data && reqOptions.type !== 'GET') {
853
- reqOptions = {
854
- ...reqOptions,
855
- contentType
856
- };
857
- }
858
- // @ts-expect-error poorly typed
859
- reqOptions = ajaxOptions(reqOptions, this);
860
- }
861
- reqOptions.url = this._ajaxURL(reqOptions.url);
862
- return reqOptions;
863
- }
219
+ export default class ApplicationAdapter extends RESTAdapter {
220
+ host = 'https://api.example.com';
221
+ }
222
+ ```
864
223
 
865
- /**
866
- * @private
867
- */
868
- _ajaxURL(url) {
869
- if (this.fastboot?.isFastBoot) {
870
- const httpRegex = /^https?:\/\//;
871
- const protocolRelativeRegex = /^\/\//;
872
- const protocol = this.fastboot.request.protocol;
873
- const host = this.fastboot.request.host;
874
- if (protocolRelativeRegex.test(url)) {
875
- return `${protocol}${url}`;
876
- } else if (!httpRegex.test(url)) {
877
- try {
878
- return `${protocol}//${host}${url}`;
879
- } catch (fbError) {
880
- throw new Error('You are using WarpDrive with no host defined in your adapter. This will attempt to use the host of the FastBoot request, which is not configured for the current host of this request. Please set the hostWhitelist property for in your environment.js. FastBoot Error: ' + fbError.message);
881
- }
882
- }
883
- }
884
- return url;
885
- }
224
+ ### Headers customization
886
225
 
887
- /**
888
- @private
889
- */
890
- parseErrorResponse(responseText) {
891
- let json = responseText;
892
- try {
893
- json = JSON.parse(responseText);
894
- } catch {
895
- // ignored
896
- }
897
- return json;
898
- }
226
+ Some APIs require HTTP headers, e.g. to provide an API key. Arbitrary
227
+ headers can be set as key/value pairs on the `RESTAdapter`'s `headers`
228
+ object and WarpDrive will send them along with each ajax request.
899
229
 
900
- /**
901
- @private
902
- @return errors payload
903
- */
904
- normalizeErrorResponse(status, _headers, payload) {
905
- if (payload && typeof payload === 'object' && 'errors' in payload && Array.isArray(payload.errors)) {
906
- return payload.errors;
907
- } else {
908
- return [{
909
- status: `${status}`,
910
- // Set to a string per the JSON API spec: https://jsonapi.org/format/#errors
911
- title: 'The backend responded with an error',
912
- // Detail is intended to be a string, but backends be non-compliant.
913
- // stringifying gives the user a more friendly error in this situation, whereas
914
- // they'd instead receive [object Object].
915
- // JSON.stringify will convert *anything* to a string without erroring.
916
- detail: typeof payload === 'string' ? payload : JSON.stringify(payload)
917
- }];
918
- }
919
- }
920
230
 
921
- /**
922
- Generates a detailed ("friendly") error message, with plenty
923
- of information for debugging (good luck!)
924
- @private
925
- @return detailed error message
926
- */
927
- generatedDetailedMessage(status, headers, payload, requestData) {
928
- let shortenedPayload;
929
- const payloadContentType = headers['content-type'] || 'Empty Content-Type';
930
- if (payloadContentType === 'text/html' && typeof payload === 'string' && payload.length > 250) {
931
- shortenedPayload = '[Omitted Lengthy HTML]';
932
- } else if (typeof payload === 'object' && payload !== null) {
933
- shortenedPayload = JSON.stringify(payload, null, 2);
934
- } else {
935
- shortenedPayload = payload;
936
- }
937
- const requestDescription = requestData.method + ' ' + requestData.url;
938
- const payloadDescription = 'Payload (' + payloadContentType + ')';
939
- return ['Ember Data Request ' + requestDescription + ' returned a ' + status, payloadDescription, shortenedPayload].join('\n');
940
- }
231
+ ```js [app/adapters/application.js]
232
+ import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
941
233
 
942
- /**
943
- Used by `findAll` and `findRecord` to build the query's `data` hash
944
- supplied to the ajax method.
945
- @since 2.5.0
946
- @public
947
- */
948
- buildQuery(snapshot) {
949
- const query = {};
950
- if (snapshot) {
951
- const {
952
- include
953
- } = snapshot;
954
- if (include) {
955
- // note: if user passed in an array, this will serialize like `?include[]=foo&include[]=bar`
956
- // but if user passed in a string, this will serialize like `?include=foo,bar`
957
- // users that want consistent behavior should override this method
958
- query.include = include;
959
- }
960
- }
961
- return query;
962
- }
234
+ export default class ApplicationAdapter extends RESTAdapter {
235
+ get headers() {
236
+ return {
237
+ 'API_KEY': 'secret key',
238
+ 'ANOTHER_HEADER': 'Some header value'
239
+ };
963
240
  }
241
+ }
242
+ ```
964
243
 
965
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
966
-
244
+ @public
245
+ */
246
+ var RESTAdapter = class extends AdapterWithBuildURLMixin {
247
+ /**
248
+ * @private
249
+ */
250
+ /**
251
+ * @private
252
+ */
253
+ /**
254
+ * See "Host customization" above.
255
+ */
256
+ /**
257
+ * See "Namespace customization" above.
258
+ */
259
+ /**
260
+ This property allows ajax to still be used instead when `false`.
261
+ @default true
262
+ @public
263
+ */
264
+ useFetch = true;
265
+ /**
266
+ * The `Content-Type` header used when serializing request bodies
267
+ * that don't otherwise specify one.
268
+ */
269
+ _defaultContentType = "application/json; charset=utf-8";
270
+ /**
271
+ * The FastBoot service instance, if running in a FastBoot environment.
272
+ * Lazily looked up on first access.
273
+ */
274
+ get fastboot() {
275
+ const fastboot = this._fastboot;
276
+ if (fastboot) return fastboot;
277
+ return this._fastboot = getOwner(this).lookup("service:fastboot");
278
+ }
279
+ /**
280
+ * Sets the FastBoot service instance to use.
281
+ */
282
+ static {
283
+ decorateMethodV2(this.prototype, "fastboot", [computed()]);
284
+ }
285
+ set fastboot(value) {
286
+ this._fastboot = value;
287
+ }
288
+ /**
289
+ By default, the RESTAdapter will send the query params sorted alphabetically to the
290
+ server.
291
+ For example:
292
+ ```js
293
+ store.query('posts', { sort: 'price', category: 'pets' });
294
+ ```
295
+ will generate a requests like this `/posts?category=pets&sort=price`, even if the
296
+ parameters were specified in a different order.
297
+ That way the generated URL will be deterministic and that simplifies caching mechanisms
298
+ in the backend.
299
+ Setting `sortQueryParams` to a falsey value will respect the original order.
300
+ In case you want to sort the query parameters with a different criteria, set
301
+ `sortQueryParams` to your custom sort function.
302
+ ```js [app/adapters/application.js]
303
+ import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
304
+ export default class ApplicationAdapter extends RESTAdapter {
305
+ sortQueryParams(params) {
306
+ let sortedKeys = Object.keys(params).sort().reverse();
307
+ let len = sortedKeys.length, newParams = {};
308
+ for (let i = 0; i < len; i++) {
309
+ newParams[sortedKeys[i]] = params[sortedKeys[i]];
310
+ }
311
+ return newParams;
312
+ }
313
+ }
314
+ ```
315
+ @public
316
+ */
317
+ sortQueryParams(obj) {
318
+ const keys = Object.keys(obj);
319
+ const len = keys.length;
320
+ if (len < 2) return obj;
321
+ const newQueryParams = {};
322
+ const sortedKeys = keys.sort();
323
+ for (let i = 0; i < len; i++) newQueryParams[sortedKeys[i]] = obj[sortedKeys[i]];
324
+ return newQueryParams;
325
+ }
326
+ /**
327
+ By default the RESTAdapter will send each find request coming from a `store.find`
328
+ or from accessing a relationship separately to the server. If your server supports passing
329
+ ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests
330
+ within a single runloop.
331
+ For example, if you have an initial payload of:
332
+ ```javascript
333
+ {
334
+ post: {
335
+ id: 1,
336
+ comments: [1, 2]
337
+ }
338
+ }
339
+ ```
340
+ By default calling `post.comments` will trigger the following requests(assuming the
341
+ comments haven't been loaded before):
342
+ ```
343
+ GET /comments/1
344
+ GET /comments/2
345
+ ```
346
+ If you set coalesceFindRequests to `true` it will instead trigger the following request:
347
+ ```
348
+ GET /comments?ids[]=1&ids[]=2
349
+ ```
350
+ Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`
351
+ relationships accessed within the same runloop. If you set `coalesceFindRequests: true`
352
+ ```javascript
353
+ store.findRecord('comment', 1);
354
+ store.findRecord('comment', 2);
355
+ ```
356
+ will also send a request to: `GET /comments?ids[]=1&ids[]=2`
357
+ Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app
358
+ `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.
359
+ @public
360
+ */
361
+ get coalesceFindRequests() {
362
+ const coalesceFindRequests = this._coalesceFindRequests;
363
+ if (typeof coalesceFindRequests === "boolean") return coalesceFindRequests;
364
+ return this._coalesceFindRequests = false;
365
+ }
366
+ set coalesceFindRequests(value) {
367
+ this._coalesceFindRequests = value;
368
+ }
369
+ /**
370
+ Endpoint paths can be prefixed with a `namespace` by setting the namespace
371
+ property on the adapter:
372
+ ```js [app/adapters/application.js]
373
+ import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
374
+ export default class ApplicationAdapter extends RESTAdapter {
375
+ namespace = 'api/1';
376
+ }
377
+ ```
378
+ Requests for the `Post` model would now target `/api/1/post/`.
379
+ @public
380
+ */
381
+ /**
382
+ An adapter can target other hosts by setting the `host` property.
383
+ ```js [app/adapters/application.js]
384
+ import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
385
+ export default class ApplicationAdapter extends RESTAdapter {
386
+ host = 'https://api.example.com';
387
+ }
388
+ ```
389
+ Requests for the `Post` model would now target `https://api.example.com/post/`.
390
+ @public
391
+ */
392
+ /**
393
+ Some APIs require HTTP headers, e.g. to provide an API
394
+ key. Arbitrary headers can be set as key/value pairs on the
395
+ `RESTAdapter`'s `headers` object and WarpDrive will send them
396
+ along with each ajax request..
397
+ ```js [app/adapters/application.js]
398
+ import { RESTAdapter } from '@warp-drive/legacy/adapter/rest';
399
+ export default class ApplicationAdapter extends RESTAdapter {
400
+ get headers() {
401
+ return {
402
+ 'API_KEY': 'secret key',
403
+ 'ANOTHER_HEADER': 'Some header value'
404
+ };
405
+ }
406
+ }
407
+ ```
408
+ @public
409
+ */
410
+ /**
411
+ Called by the store in order to fetch the JSON for a given
412
+ type and ID.
413
+ The `findRecord` method makes an Ajax request to a URL computed by
414
+ `buildURL`, and returns a promise for the resulting payload.
415
+ This method performs an HTTP `GET` request with the id provided as part of the query string.
416
+ @since 1.13.0
417
+ @public
418
+ */
419
+ findRecord(store, type, id, snapshot) {
420
+ const url = this.buildURL(type.modelName, id, snapshot, "findRecord");
421
+ const query = this.buildQuery(snapshot);
422
+ return this.ajax(url, "GET", { data: query });
423
+ }
424
+ /**
425
+ Called by the store in order to fetch a JSON array for all
426
+ of the records for a given type.
427
+ The `findAll` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
428
+ promise for the resulting payload.
429
+ @public
430
+ */
431
+ findAll(store, type, neverUsed, snapshotRecordArray) {
432
+ const query = this.buildQuery(snapshotRecordArray);
433
+ const url = this.buildURL(type.modelName, null, snapshotRecordArray, "findAll");
434
+ return this.ajax(url, "GET", { data: query });
435
+ }
436
+ /**
437
+ Called by the store in order to fetch a JSON array for
438
+ the records that match a particular query.
439
+ The `query` method makes an Ajax (HTTP GET) request to a URL
440
+ computed by `buildURL`, and returns a promise for the resulting
441
+ payload.
442
+ The `query` argument is a simple JavaScript object that will be passed directly
443
+ to the server as parameters.
444
+ @public
445
+ */
446
+ query(store, type, query) {
447
+ const url = this.buildURL(type.modelName, null, null, "query", query);
448
+ if (this.sortQueryParams) query = this.sortQueryParams(query);
449
+ return this.ajax(url, "GET", { data: query });
450
+ }
451
+ /**
452
+ Called by the store in order to fetch a JSON object for
453
+ the record that matches a particular query.
454
+ The `queryRecord` method makes an Ajax (HTTP GET) request to a URL
455
+ computed by `buildURL`, and returns a promise for the resulting
456
+ payload.
457
+ The `query` argument is a simple JavaScript object that will be passed directly
458
+ to the server as parameters.
459
+ @since 1.13.0
460
+ @public
461
+ */
462
+ queryRecord(store, type, query, adapterOptions) {
463
+ const url = this.buildURL(type.modelName, null, null, "queryRecord", query);
464
+ if (this.sortQueryParams) query = this.sortQueryParams(query);
465
+ return this.ajax(url, "GET", { data: query });
466
+ }
467
+ /**
468
+ Called by the store in order to fetch several records together if `coalesceFindRequests` is true
469
+ For example, if the original payload looks like:
470
+ ```js
471
+ {
472
+ "id": 1,
473
+ "title": "Rails is omakase",
474
+ "comments": [ 1, 2, 3 ]
475
+ }
476
+ ```
477
+ The IDs will be passed as a URL-encoded Array of IDs, in this form:
478
+ ```
479
+ ids[]=1&ids[]=2&ids[]=3
480
+ ```
481
+ Many servers, such as Rails and PHP, will automatically convert this URL-encoded array
482
+ into an Array for you on the server-side. If you want to encode the
483
+ IDs, differently, just override this (one-line) method.
484
+ The `findMany` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
485
+ promise for the resulting payload.
486
+ @public
487
+ */
488
+ findMany(store, type, ids, snapshots) {
489
+ const url = this.buildURL(type.modelName, ids, snapshots, "findMany");
490
+ return this.ajax(url, "GET", { data: { ids } });
491
+ }
492
+ /**
493
+ Called by the store in order to fetch a JSON array for
494
+ the unloaded records in a has-many relationship that were originally
495
+ specified as a URL (inside of `links`).
496
+ For example, if your original payload looks like this:
497
+ ```js
498
+ {
499
+ "post": {
500
+ "id": 1,
501
+ "title": "Rails is omakase",
502
+ "links": { "comments": "/posts/1/comments" }
503
+ }
504
+ }
505
+ ```
506
+ This method will be called with the parent record and `/posts/1/comments`.
507
+ The `findHasMany` method will make an Ajax (HTTP GET) request to the originally specified URL.
508
+ The format of your `links` value will influence the final request URL via the `urlPrefix` method:
509
+ * Links beginning with `//`, `http://`, `https://`, will be used as is, with no further manipulation.
510
+ * Links beginning with a single `/` will have the current adapter's `host` value prepended to it.
511
+ * Links with no beginning `/` will have a parentURL prepended to it, via the current adapter's `buildURL`.
512
+ @public
513
+ */
514
+ findHasMany(store, snapshot, url, relationship) {
515
+ const id = snapshot.id;
516
+ const type = snapshot.modelName;
517
+ ((test) => {
518
+ if (!test) throw new Error(`Attempted to fetch the hasMany relationship for ${type}, but the record has no id`);
519
+ })(typeof id === "string" && id.length > 0);
520
+ url = this.urlPrefix(url, this.buildURL(type, id, snapshot, "findHasMany"));
521
+ return this.ajax(url, "GET");
522
+ }
523
+ /**
524
+ Called by the store in order to fetch the JSON for the unloaded record in a
525
+ belongs-to relationship that was originally specified as a URL (inside of
526
+ `links`).
527
+ For example, if your original payload looks like this:
528
+ ```js
529
+ {
530
+ "person": {
531
+ "id": 1,
532
+ "name": "Tom Dale",
533
+ "links": { "group": "/people/1/group" }
534
+ }
535
+ }
536
+ ```
537
+ This method will be called with the parent record and `/people/1/group`.
538
+ The `findBelongsTo` method will make an Ajax (HTTP GET) request to the originally specified URL.
539
+ The format of your `links` value will influence the final request URL via the `urlPrefix` method:
540
+ * Links beginning with `//`, `http://`, `https://`, will be used as is, with no further manipulation.
541
+ * Links beginning with a single `/` will have the current adapter's `host` value prepended to it.
542
+ * Links with no beginning `/` will have a parentURL prepended to it, via the current adapter's `buildURL`.
543
+ @public
544
+ */
545
+ findBelongsTo(store, snapshot, url, relationship) {
546
+ const id = snapshot.id;
547
+ const type = snapshot.modelName;
548
+ ((test) => {
549
+ if (!test) throw new Error(`Attempted to fetch the belongsTo relationship for ${type}, but the record has no id`);
550
+ })(typeof id === "string" && id.length > 0);
551
+ url = this.urlPrefix(url, this.buildURL(type, id, snapshot, "findBelongsTo"));
552
+ return this.ajax(url, "GET");
553
+ }
554
+ /**
555
+ Called by the store when a newly created record is
556
+ saved via the `save` method on a model record instance.
557
+ The `createRecord` method serializes the record and makes an Ajax (HTTP POST) request
558
+ to a URL computed by `buildURL`.
559
+ See `serialize` for information on how to customize the serialized form
560
+ of a record.
561
+ @public
562
+ */
563
+ createRecord(store, type, snapshot) {
564
+ const url = this.buildURL(type.modelName, null, snapshot, "createRecord");
565
+ const data = serializeIntoHash(store, type, snapshot);
566
+ return this.ajax(url, "POST", { data });
567
+ }
568
+ /**
569
+ Called by the store when an existing record is saved
570
+ via the `save` method on a model record instance.
571
+ The `updateRecord` method serializes the record and makes an Ajax (HTTP PUT) request
572
+ to a URL computed by `buildURL`.
573
+ See `serialize` for information on how to customize the serialized form
574
+ of a record.
575
+ @public
576
+ */
577
+ updateRecord(store, schema, snapshot) {
578
+ const data = serializeIntoHash(store, schema, snapshot, {});
579
+ const type = snapshot.modelName;
580
+ const id = snapshot.id;
581
+ ((test) => {
582
+ if (!test) throw new Error(`Attempted to update the ${type} record, but the record has no id`);
583
+ })(typeof id === "string" && id.length > 0);
584
+ const url = this.buildURL(type, id, snapshot, "updateRecord");
585
+ return this.ajax(url, "PUT", { data });
586
+ }
587
+ /**
588
+ Called by the store when a record is deleted.
589
+ The `deleteRecord` method makes an Ajax (HTTP DELETE) request to a URL computed by `buildURL`.
590
+ @public
591
+ */
592
+ deleteRecord(store, schema, snapshot) {
593
+ const type = snapshot.modelName;
594
+ const id = snapshot.id;
595
+ ((test) => {
596
+ if (!test) throw new Error(`Attempted to delete the ${type} record, but the record has no id`);
597
+ })(typeof id === "string" && id.length > 0);
598
+ return this.ajax(this.buildURL(type, id, snapshot, "deleteRecord"), "DELETE");
599
+ }
600
+ /**
601
+ @private
602
+ */
603
+ _stripIDFromURL(store, snapshot) {
604
+ const type = snapshot.modelName;
605
+ const id = snapshot.id;
606
+ ((test) => {
607
+ if (!test) throw new Error(`Attempted to strip the url from the ${type} record for coalescing, but the record has no id`);
608
+ })(typeof id === "string" && id.length > 0);
609
+ const expandedURL = this.buildURL(type, id, snapshot).split("/");
610
+ const lastSegment = expandedURL[expandedURL.length - 1];
611
+ if (decodeURIComponent(lastSegment) === id) expandedURL[expandedURL.length - 1] = "";
612
+ else if (id && endsWith(lastSegment, "?id=" + id)) expandedURL[expandedURL.length - 1] = lastSegment.substring(0, lastSegment.length - id.length - 1);
613
+ return expandedURL.join("/");
614
+ }
615
+ /**
616
+ * The maximum URL length to allow when coalescing `findRecord` requests
617
+ * into a single `findMany` request via {@link RESTAdapter.groupRecordsForFindMany | groupRecordsForFindMany}.
618
+ * Requests that would exceed this length are split into multiple groups.
619
+ *
620
+ * See http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
621
+ */
622
+ maxURLLength = 2048;
623
+ /**
624
+ Organize records into groups, each of which is to be passed to separate
625
+ calls to `findMany`.
626
+ This implementation groups together records that have the same base URL but
627
+ differing ids. For example `/comments/1` and `/comments/2` will be grouped together
628
+ because we know findMany can coalesce them together as `/comments?ids[]=1&ids[]=2`
629
+ It also supports urls where ids are passed as a query param, such as `/comments?id=1`
630
+ but not those where there is more than 1 query param such as `/comments?id=2&name=David`
631
+ Currently only the query param of `id` is supported. If you need to support others, please
632
+ override this or the `_stripIDFromURL` method.
633
+ It does not group records that have differing base urls, such as for example: `/posts/1/comments/2`
634
+ and `/posts/2/comments/3`
635
+ @public
636
+ @return an array of arrays of records, each of which is to be
637
+ loaded separately by `findMany`.
638
+ */
639
+ groupRecordsForFindMany(store, snapshots) {
640
+ const groups = /* @__PURE__ */ new Map();
641
+ const maxURLLength = this.maxURLLength;
642
+ snapshots.forEach((snapshot) => {
643
+ const baseUrl = this._stripIDFromURL(store, snapshot);
644
+ if (!groups.has(baseUrl)) groups.set(baseUrl, []);
645
+ groups.get(baseUrl).push(snapshot);
646
+ });
647
+ const groupsArray = [];
648
+ groups.forEach((group, key) => {
649
+ splitGroupToFitInUrl(store, this, group, maxURLLength, 11).forEach((splitGroup) => groupsArray.push(splitGroup));
650
+ });
651
+ return groupsArray;
652
+ }
653
+ /**
654
+ Takes an ajax response, and returns the json payload or an error.
655
+ By default this hook just returns the json payload passed to it.
656
+ You might want to override it in two cases:
657
+ 1. Your API might return useful results in the response headers.
658
+ Response headers are passed in as the second argument.
659
+ 2. Your API might return errors as successful responses with status code
660
+ 200 and an Errors text or object. You can return a `InvalidError` or a
661
+ `AdapterError` (or a sub class) from this hook and it will automatically
662
+ reject the promise and put your record into the invalid or error state.
663
+ Returning a `InvalidError` from this method will cause the
664
+ record to transition into the `invalid` state and make the
665
+ `errors` object available on the record. When returning an
666
+ `InvalidError` the store will attempt to normalize the error data
667
+ returned from the server using the serializer's `extractErrors`
668
+ method.
669
+ @since 1.13.0
670
+ @public
671
+ */
672
+ handleResponse(status, headers, payload, requestData) {
673
+ if (this.isSuccess(status, headers, payload)) return payload;
674
+ else if (this.isInvalid(status, headers, payload)) {
675
+ const errorPayload = payload ?? {};
676
+ return new InvalidError(typeof errorPayload === "object" && "errors" in errorPayload ? errorPayload.errors : void 0);
677
+ }
678
+ const errors = this.normalizeErrorResponse(status, headers, payload);
679
+ const detailedMessage = this.generatedDetailedMessage(status, headers, payload, requestData);
680
+ switch (status) {
681
+ case 401: return new UnauthorizedError(errors, detailedMessage);
682
+ case 403: return new ForbiddenError(errors, detailedMessage);
683
+ case 404: return new NotFoundError(errors, detailedMessage);
684
+ case 409: return new ConflictError(errors, detailedMessage);
685
+ default: if (status >= 500) return new ServerError(errors, detailedMessage);
686
+ }
687
+ return new AdapterError(errors, detailedMessage);
688
+ }
689
+ /**
690
+ Default `handleResponse` implementation uses this hook to decide if the
691
+ response is a success.
692
+ @since 1.13.0
693
+ @public
694
+ */
695
+ isSuccess(status, _headers, _payload) {
696
+ return status >= 200 && status < 300 || status === 304;
697
+ }
698
+ /**
699
+ Default `handleResponse` implementation uses this hook to decide if the
700
+ response is an invalid error.
701
+ @since 1.13.0
702
+ @public
703
+ */
704
+ isInvalid(status, _headers, _payload) {
705
+ return status === 422;
706
+ }
707
+ /**
708
+ Takes a URL, an HTTP method and a hash of data, and makes an
709
+ HTTP request.
710
+ When the server responds with a payload, WarpDrive will call into `extractSingle`
711
+ or `extractArray` (depending on whether the original query was for one record or
712
+ many records).
713
+ By default, `ajax` method has the following behavior:
714
+ * It sets the response `dataType` to `"json"`
715
+ * If the HTTP method is not `"GET"`, it sets the `Content-Type` to be
716
+ `application/json; charset=utf-8`
717
+ * If the HTTP method is not `"GET"`, it stringifies the data passed in. The
718
+ data is the serialized record in the case of a save.
719
+ * Registers success and failure handlers.
720
+ @private
721
+ */
722
+ async ajax(url, type, options = {}) {
723
+ const requestData = {
724
+ url,
725
+ method: type
726
+ };
727
+ if (this.useFetch) {
728
+ const hash = this.ajaxOptions(url, type, options);
729
+ const response = await this._fetchRequest(hash);
730
+ const payload = await determineBodyPromise(response, requestData);
731
+ if (response.ok && !(payload instanceof Error)) return fetchSuccessHandler(this, payload, response, requestData);
732
+ else throw fetchErrorHandler(this, payload, response, null, requestData);
733
+ } else return execjQAjax(this, requestData, options);
734
+ }
735
+ /**
736
+ @private
737
+ @param options jQuery ajax options to be used for the ajax request
738
+ */
739
+ _ajaxRequest(options) {
740
+ ((test) => {
741
+ if (!test) throw new Error("You must install jQuery globally when `useFetch` is false");
742
+ })(typeof jQuery !== "undefined");
743
+ jQuery.ajax(options);
744
+ }
745
+ /**
746
+ @private
747
+ */
748
+ _fetchRequest(options) {
749
+ return getFetchFunction()(options.url, options);
750
+ }
751
+ /**
752
+ @private
753
+ */
754
+ _ajax(options) {
755
+ if (this.useFetch) this._fetchRequest(options);
756
+ else this._ajaxRequest(options);
757
+ }
758
+ /**
759
+ @private
760
+ */
761
+ ajaxOptions(url, method, options) {
762
+ let reqOptions = Object.assign({
763
+ url,
764
+ method,
765
+ type: method
766
+ }, options);
767
+ if (this.headers !== void 0) reqOptions.headers = {
768
+ ...this.headers,
769
+ ...reqOptions.headers
770
+ };
771
+ else if (!options.headers) reqOptions.headers = {};
772
+ const contentType = reqOptions.contentType || this._defaultContentType;
773
+ if (this.useFetch) {
774
+ if (reqOptions.data && reqOptions.type !== "GET" && reqOptions.headers) {
775
+ if (!reqOptions.headers["Content-Type"] && !reqOptions.headers["content-type"]) reqOptions.headers["content-type"] = contentType;
776
+ }
777
+ reqOptions = fetchOptions(reqOptions, this);
778
+ } else {
779
+ if (reqOptions.data && reqOptions.type !== "GET") reqOptions = {
780
+ ...reqOptions,
781
+ contentType
782
+ };
783
+ reqOptions = ajaxOptions(reqOptions, this);
784
+ }
785
+ reqOptions.url = this._ajaxURL(reqOptions.url);
786
+ return reqOptions;
787
+ }
788
+ /**
789
+ * @private
790
+ */
791
+ _ajaxURL(url) {
792
+ if (this.fastboot?.isFastBoot) {
793
+ const httpRegex = /^https?:\/\//;
794
+ const protocolRelativeRegex = /^\/\//;
795
+ const protocol = this.fastboot.request.protocol;
796
+ const host = this.fastboot.request.host;
797
+ if (protocolRelativeRegex.test(url)) return `${protocol}${url}`;
798
+ else if (!httpRegex.test(url)) try {
799
+ return `${protocol}//${host}${url}`;
800
+ } catch (fbError) {
801
+ throw new Error("You are using WarpDrive with no host defined in your adapter. This will attempt to use the host of the FastBoot request, which is not configured for the current host of this request. Please set the hostWhitelist property for in your environment.js. FastBoot Error: " + fbError.message, { cause: fbError });
802
+ }
803
+ }
804
+ return url;
805
+ }
806
+ /**
807
+ @private
808
+ */
809
+ parseErrorResponse(responseText) {
810
+ let json = responseText;
811
+ try {
812
+ json = JSON.parse(responseText);
813
+ } catch {}
814
+ return json;
815
+ }
816
+ /**
817
+ @private
818
+ @return errors payload
819
+ */
820
+ normalizeErrorResponse(status, _headers, payload) {
821
+ if (payload && typeof payload === "object" && "errors" in payload && Array.isArray(payload.errors)) return payload.errors;
822
+ else return [{
823
+ status: `${status}`,
824
+ title: "The backend responded with an error",
825
+ detail: typeof payload === "string" ? payload : JSON.stringify(payload)
826
+ }];
827
+ }
828
+ /**
829
+ Generates a detailed ("friendly") error message, with plenty
830
+ of information for debugging (good luck!)
831
+ @private
832
+ @return detailed error message
833
+ */
834
+ generatedDetailedMessage(status, headers, payload, requestData) {
835
+ let shortenedPayload;
836
+ const payloadContentType = headers["content-type"] || "Empty Content-Type";
837
+ if (payloadContentType === "text/html" && typeof payload === "string" && payload.length > 250) shortenedPayload = "[Omitted Lengthy HTML]";
838
+ else if (typeof payload === "object" && payload !== null) shortenedPayload = JSON.stringify(payload, null, 2);
839
+ else shortenedPayload = payload;
840
+ const requestDescription = requestData.method + " " + requestData.url;
841
+ const payloadDescription = "Payload (" + payloadContentType + ")";
842
+ return [
843
+ "Ember Data Request " + requestDescription + " returned a " + status,
844
+ payloadDescription,
845
+ shortenedPayload
846
+ ].join("\n");
847
+ }
848
+ /**
849
+ Used by `findAll` and `findRecord` to build the query's `data` hash
850
+ supplied to the ajax method.
851
+ @since 2.5.0
852
+ @public
853
+ */
854
+ buildQuery(snapshot) {
855
+ const query = {};
856
+ if (snapshot) {
857
+ const { include } = snapshot;
858
+ if (include) query.include = include;
859
+ }
860
+ return query;
861
+ }
862
+ };
967
863
  function ajaxSuccess(adapter, payload, requestData, responseData) {
968
- let response;
969
- try {
970
- response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData);
971
- } catch (error) {
972
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
973
- return Promise.reject(error);
974
- }
975
- if (response && response.isAdapterError) {
976
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
977
- return Promise.reject(response);
978
- } else {
979
- return response;
980
- }
864
+ let response;
865
+ try {
866
+ response = adapter.handleResponse(responseData.status, responseData.headers, payload, requestData);
867
+ } catch (error) {
868
+ return Promise.reject(error);
869
+ }
870
+ if (response && response.isAdapterError) return Promise.reject(response);
871
+ else return response;
981
872
  }
982
873
  function ajaxError(adapter, payload, requestData, responseData) {
983
- let error;
984
- if (responseData.errorThrown instanceof Error && payload !== '') {
985
- error = responseData.errorThrown;
986
- } else if (responseData.textStatus === 'timeout') {
987
- error = new TimeoutError();
988
- } else if (responseData.textStatus === 'abort' || responseData.status === 0) {
989
- error = handleAbort(requestData, responseData);
990
- } else {
991
- try {
992
- error = adapter.handleResponse(responseData.status, responseData.headers, payload || responseData.errorThrown, requestData);
993
- } catch (e) {
994
- error = e;
995
- }
996
- }
997
- return error;
874
+ let error;
875
+ if (responseData.errorThrown instanceof Error && payload !== "") error = responseData.errorThrown;
876
+ else if (responseData.textStatus === "timeout") error = new TimeoutError();
877
+ else if (responseData.textStatus === "abort" || responseData.status === 0) error = handleAbort(requestData, responseData);
878
+ else try {
879
+ error = adapter.handleResponse(responseData.status, responseData.headers, payload || responseData.errorThrown, requestData);
880
+ } catch (e) {
881
+ error = e;
882
+ }
883
+ return error;
998
884
  }
999
-
1000
- // Adapter abort error to include any relevent info, e.g. request/response:
1001
885
  function handleAbort(requestData, responseData) {
1002
- const {
1003
- method,
1004
- url,
1005
- errorThrown
1006
- } = requestData;
1007
- const {
1008
- status
1009
- } = responseData;
1010
- const msg = `Request failed: ${method} ${url} ${String(errorThrown ?? '')}`;
1011
- const errors = [{
1012
- title: 'Adapter Error',
1013
- detail: msg.trim(),
1014
- status
1015
- }];
1016
- return new AbortError(errors);
886
+ const { method, url, errorThrown } = requestData;
887
+ const { status } = responseData;
888
+ const errors = [{
889
+ title: "Adapter Error",
890
+ detail: `Request failed: ${method} ${url} ${String(errorThrown ?? "")}`.trim(),
891
+ status
892
+ }];
893
+ return new AbortError(errors);
1017
894
  }
1018
-
1019
- //From http://stackoverflow.com/questions/280634/endswith-in-javascript
1020
895
  function endsWith(string, suffix) {
1021
- if (typeof String.prototype.endsWith !== 'function') {
1022
- return string.includes(suffix, string.length - suffix.length);
1023
- } else {
1024
- return string.endsWith(suffix);
1025
- }
896
+ if (typeof String.prototype.endsWith !== "function") return string.includes(suffix, string.length - suffix.length);
897
+ else return string.endsWith(suffix);
1026
898
  }
1027
899
  function fetchSuccessHandler(adapter, payload, response, requestData) {
1028
- const responseData = fetchResponseData(response);
1029
- return ajaxSuccess(adapter, payload, requestData, responseData);
900
+ return ajaxSuccess(adapter, payload, requestData, fetchResponseData(response));
1030
901
  }
1031
902
  function fetchErrorHandler(adapter, payload, response, errorThrown, requestData) {
1032
- const responseData = fetchResponseData(response);
1033
- if (responseData.status === 200 && payload instanceof Error) {
1034
- responseData.errorThrown = payload;
1035
- // @ts-expect-error poorly typed
1036
- payload = responseData.errorThrown.payload;
1037
- } else {
1038
- responseData.errorThrown = errorThrown;
1039
- if (typeof payload === 'string') {
1040
- payload = adapter.parseErrorResponse(payload);
1041
- }
1042
- }
1043
- return ajaxError(adapter, payload, requestData, responseData);
903
+ const responseData = fetchResponseData(response);
904
+ if (responseData.status === 200 && payload instanceof Error) {
905
+ responseData.errorThrown = payload;
906
+ payload = responseData.errorThrown.payload;
907
+ } else {
908
+ responseData.errorThrown = errorThrown;
909
+ if (typeof payload === "string") payload = adapter.parseErrorResponse(payload);
910
+ }
911
+ return ajaxError(adapter, payload, requestData, responseData);
1044
912
  }
1045
913
  function ajaxSuccessHandler(adapter, payload, jqXHR, requestData) {
1046
- const responseData = ajaxResponseData(jqXHR);
1047
- return ajaxSuccess(adapter, payload, requestData, responseData);
914
+ return ajaxSuccess(adapter, payload, requestData, ajaxResponseData(jqXHR));
1048
915
  }
1049
916
  function ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData) {
1050
- const responseData = ajaxResponseData(jqXHR);
1051
- responseData.errorThrown = errorThrown;
1052
- const payload = adapter.parseErrorResponse(jqXHR.responseText);
1053
- {
1054
- const message = `The server returned an empty string for ${requestData.method} ${requestData.url}, which cannot be parsed into a valid JSON. Return either null or {}.`;
1055
- const validJSONString = !(responseData.textStatus === 'parsererror' && payload === '');
1056
- console.warn(message, validJSONString, {
1057
- id: 'ds.adapter.returned-empty-string-as-JSON'
1058
- });
1059
- }
1060
- return ajaxError(adapter, payload, requestData, responseData);
917
+ const responseData = ajaxResponseData(jqXHR);
918
+ responseData.errorThrown = errorThrown;
919
+ const payload = adapter.parseErrorResponse(jqXHR.responseText);
920
+ {
921
+ const message = `The server returned an empty string for ${requestData.method} ${requestData.url}, which cannot be parsed into a valid JSON. Return either null or {}.`;
922
+ const validJSONString = !(responseData.textStatus === "parsererror" && payload === "");
923
+ console.warn(message, validJSONString, { id: "ds.adapter.returned-empty-string-as-JSON" });
924
+ }
925
+ return ajaxError(adapter, payload, requestData, responseData);
1061
926
  }
1062
927
  function fetchResponseData(response) {
1063
- return {
1064
- status: response.status,
1065
- textStatus: response.statusText,
1066
- headers: headersToObject(response.headers)
1067
- };
928
+ return {
929
+ status: response.status,
930
+ textStatus: response.statusText,
931
+ headers: headersToObject(response.headers)
932
+ };
1068
933
  }
1069
934
  function ajaxResponseData(jqXHR) {
1070
- return {
1071
- status: jqXHR.status,
1072
- textStatus: jqXHR.statusText,
1073
- headers: parseResponseHeaders(jqXHR.getAllResponseHeaders())
1074
- };
935
+ return {
936
+ status: jqXHR.status,
937
+ textStatus: jqXHR.statusText,
938
+ headers: parseResponseHeaders(jqXHR.getAllResponseHeaders())
939
+ };
1075
940
  }
1076
941
  function headersToObject(headers) {
1077
- const headersObject = {};
1078
- if (headers) {
1079
- headers.forEach((value, key) => headersObject[key] = value);
1080
- }
1081
- return headersObject;
942
+ const headersObject = {};
943
+ if (headers) headers.forEach((value, key) => headersObject[key] = value);
944
+ return headersObject;
1082
945
  }
1083
-
1084
946
  /**
1085
- * Helper function that translates the options passed to `jQuery.ajax` into a format that `fetch` expects.
1086
- *
1087
- * @private
1088
- */
947
+ * Helper function that translates the options passed to `jQuery.ajax` into a format that `fetch` expects.
948
+ *
949
+ * @private
950
+ */
1089
951
  function fetchOptions(options, adapter) {
1090
- options.credentials = options.credentials || 'same-origin';
1091
- if (options.data) {
1092
- // GET and HEAD requests can't have a `body`
1093
- if (options.method === 'GET' || options.method === 'HEAD') {
1094
- // If no options are passed, WarpDrive sets `data` to an empty object, which we test for.
1095
- if (Object.keys(options.data).length && options.url) {
1096
- // Test if there are already query params in the url (mimics jQuey.ajax).
1097
- const queryParamDelimiter = options.url.includes('?') ? '&' : '?';
1098
- options.url += `${queryParamDelimiter}${serializeQueryParams(options.data)}`;
1099
- }
1100
- } else {
1101
- // NOTE: a request's body cannot be an object, so we stringify it if it is.
1102
- // JSON.stringify removes keys with values of `undefined` (mimics jQuery.ajax).
1103
- // If the data is not a POJO (it's a String, FormData, etc), we just set it.
1104
- // If the data is a string, we assume it's a stringified object.
1105
-
1106
- /* We check for Objects this way because we want the logic inside the consequent to run
1107
- * if `options.data` is a POJO, not if it is a data structure whose `typeof` returns "object"
1108
- * when it's not (Array, FormData, etc). The reason we don't use `options.data.constructor`
1109
- * to check is in case `data` is an object with no prototype (e.g. created with null).
1110
- */
1111
- if (Object.prototype.toString.call(options.data) === '[object Object]') {
1112
- options.body = JSON.stringify(options.data);
1113
- } else {
1114
- // @ts-expect-error poorly typed
1115
- options.body = options.data;
1116
- }
1117
- }
1118
- }
1119
- return options;
952
+ options.credentials = options.credentials || "same-origin";
953
+ if (options.data) {
954
+ if (options.method === "GET" || options.method === "HEAD") {
955
+ if (Object.keys(options.data).length && options.url) {
956
+ const queryParamDelimiter = options.url.includes("?") ? "&" : "?";
957
+ options.url += `${queryParamDelimiter}${serializeQueryParams(options.data)}`;
958
+ }
959
+ } else if (Object.prototype.toString.call(options.data) === "[object Object]") options.body = JSON.stringify(options.data);
960
+ else options.body = options.data;
961
+ }
962
+ return options;
1120
963
  }
1121
964
  function ajaxOptions(options, adapter) {
1122
- options.dataType = 'json';
1123
- options.context = adapter;
1124
- if (options.data && options.type !== 'GET') {
1125
- options.data = JSON.stringify(options.data);
1126
- }
1127
- options.beforeSend = function (xhr) {
1128
- if (options.headers) {
1129
- Object.keys(options.headers).forEach(key => {
1130
- const headerValue = options.headers && options.headers[key];
1131
- const isString = value => typeof value === 'string';
1132
- if (isString(headerValue)) {
1133
- xhr.setRequestHeader(key, headerValue);
1134
- }
1135
- });
1136
- }
1137
- };
1138
- return options;
965
+ options.dataType = "json";
966
+ options.context = adapter;
967
+ if (options.data && options.type !== "GET") options.data = JSON.stringify(options.data);
968
+ options.beforeSend = function(xhr) {
969
+ if (options.headers) Object.keys(options.headers).forEach((key) => {
970
+ const headerValue = options.headers && options.headers[key];
971
+ const isString = (value) => typeof value === "string";
972
+ if (isString(headerValue)) xhr.setRequestHeader(key, headerValue);
973
+ });
974
+ };
975
+ return options;
1139
976
  }
1140
977
  function execjQAjax(adapter, requestData, options) {
1141
- const hash = adapter.ajaxOptions(requestData.url, requestData.method, options);
1142
- return new Promise((resolve, reject) => {
1143
- hash.success = function (payload, textStatus, jqXHR) {
1144
- const response = ajaxSuccessHandler(adapter, payload, jqXHR, requestData);
1145
- resolve(response);
1146
- };
1147
- hash.error = function (jqXHR, textStatus, errorThrown) {
1148
- const error = ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData);
1149
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
1150
- reject(error);
1151
- };
1152
- adapter._ajax(hash);
1153
- });
978
+ const hash = adapter.ajaxOptions(requestData.url, requestData.method, options);
979
+ return new Promise((resolve, reject) => {
980
+ hash.success = function(payload, textStatus, jqXHR) {
981
+ resolve(ajaxSuccessHandler(adapter, payload, jqXHR, requestData));
982
+ };
983
+ hash.error = function(jqXHR, textStatus, errorThrown) {
984
+ reject(ajaxErrorHandler(adapter, jqXHR, errorThrown, requestData));
985
+ };
986
+ adapter._ajax(hash);
987
+ });
1154
988
  }
1155
989
  function splitGroupToFitInUrl(store, adapter, group, maxURLLength, paramNameLength) {
1156
- let idsSize = 0;
1157
- const baseUrl = adapter._stripIDFromURL(store, group[0]);
1158
- const splitGroups = [[]];
1159
- group.forEach(snapshot => {
1160
- const additionalLength = encodeURIComponent(snapshot.id).length + paramNameLength;
1161
- if (baseUrl.length + idsSize + additionalLength >= maxURLLength) {
1162
- idsSize = 0;
1163
- splitGroups.push([]);
1164
- }
1165
- idsSize += additionalLength;
1166
- const lastGroupIndex = splitGroups.length - 1;
1167
- splitGroups[lastGroupIndex].push(snapshot);
1168
- });
1169
- return splitGroups;
990
+ let idsSize = 0;
991
+ const baseUrl = adapter._stripIDFromURL(store, group[0]);
992
+ const splitGroups = [[]];
993
+ group.forEach((snapshot) => {
994
+ const additionalLength = encodeURIComponent(snapshot.id).length + paramNameLength;
995
+ if (baseUrl.length + idsSize + additionalLength >= maxURLLength) {
996
+ idsSize = 0;
997
+ splitGroups.push([]);
998
+ }
999
+ idsSize += additionalLength;
1000
+ const lastGroupIndex = splitGroups.length - 1;
1001
+ splitGroups[lastGroupIndex].push(snapshot);
1002
+ });
1003
+ return splitGroups;
1170
1004
  }
1171
- export { RESTAdapter, fetchOptions };
1005
+
1006
+ //#endregion
1007
+ export { RESTAdapter, fetchOptions };
1008
+ //# sourceMappingURL=rest.js.map