@qoretechnologies/reqraft 0.10.53 → 0.10.54-pr.115.gaf0d7a7

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 (291) hide show
  1. package/.claude/CLAUDE.md +25 -0
  2. package/.tasks/INDEX.md +1 -0
  3. package/.tasks/STORY_NETWORK_ISOLATION.md +98 -0
  4. package/README.md +1 -1
  5. package/design/FORM_ENGINE_EXPRESSIONS.md +110 -0
  6. package/design/FORM_ENGINE_FIELD_MIGRATION.md +155 -1
  7. package/design/RENDER_EXPRESSION_TRANSPORT.md +76 -10
  8. package/design/SMART_EDITOR_UX.md +21 -0
  9. package/dist/components/dpqlEditor/DpqlEditor.d.ts.map +1 -1
  10. package/dist/components/dpqlEditor/DpqlEditor.js +3 -3
  11. package/dist/components/dpqlEditor/DpqlEditor.js.map +1 -1
  12. package/dist/components/dpqlEditor/dpqlHelpers.d.ts +6 -0
  13. package/dist/components/dpqlEditor/dpqlHelpers.d.ts.map +1 -1
  14. package/dist/components/dpqlEditor/dpqlHelpers.js +21 -2
  15. package/dist/components/dpqlEditor/dpqlHelpers.js.map +1 -1
  16. package/dist/components/dpqlEditor/dpqlProbe.d.ts +37 -0
  17. package/dist/components/dpqlEditor/dpqlProbe.d.ts.map +1 -0
  18. package/dist/components/dpqlEditor/dpqlProbe.js +203 -0
  19. package/dist/components/dpqlEditor/dpqlProbe.js.map +1 -0
  20. package/dist/components/dpqlEditor/dpqlTags.d.ts +8 -0
  21. package/dist/components/dpqlEditor/dpqlTags.d.ts.map +1 -1
  22. package/dist/components/dpqlEditor/dpqlTags.js +5 -1
  23. package/dist/components/dpqlEditor/dpqlTags.js.map +1 -1
  24. package/dist/components/dpqlEditor/index.d.ts +4 -0
  25. package/dist/components/dpqlEditor/index.d.ts.map +1 -1
  26. package/dist/components/dpqlEditor/index.js +5 -1
  27. package/dist/components/dpqlEditor/index.js.map +1 -1
  28. package/dist/components/dpqlEditor/types.d.ts +42 -2
  29. package/dist/components/dpqlEditor/types.d.ts.map +1 -1
  30. package/dist/components/dpqlEditor/types.js +0 -4
  31. package/dist/components/dpqlEditor/types.js.map +1 -1
  32. package/dist/components/dpqlEditor/useDpqlProbe.d.ts +4 -0
  33. package/dist/components/dpqlEditor/useDpqlProbe.d.ts.map +1 -0
  34. package/dist/components/dpqlEditor/useDpqlProbe.js +29 -0
  35. package/dist/components/dpqlEditor/useDpqlProbe.js.map +1 -0
  36. package/dist/components/dpqlEditor/useDpqlSession.d.ts +5 -2
  37. package/dist/components/dpqlEditor/useDpqlSession.d.ts.map +1 -1
  38. package/dist/components/dpqlEditor/useDpqlSession.js +8 -2
  39. package/dist/components/dpqlEditor/useDpqlSession.js.map +1 -1
  40. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  41. package/dist/components/form/engine/CompactRow.js +192 -45
  42. package/dist/components/form/engine/CompactRow.js.map +1 -1
  43. package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
  44. package/dist/components/form/engine/CompactToolbar.js +5 -2
  45. package/dist/components/form/engine/CompactToolbar.js.map +1 -1
  46. package/dist/components/form/engine/FormEngine.d.ts +160 -12
  47. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  48. package/dist/components/form/engine/FormEngine.js +380 -78
  49. package/dist/components/form/engine/FormEngine.js.map +1 -1
  50. package/dist/components/form/engine/FormFieldsSkeleton.d.ts +48 -0
  51. package/dist/components/form/engine/FormFieldsSkeleton.d.ts.map +1 -0
  52. package/dist/components/form/engine/FormFieldsSkeleton.js +38 -0
  53. package/dist/components/form/engine/FormFieldsSkeleton.js.map +1 -0
  54. package/dist/components/form/engine/OptionFieldMessages.d.ts +17 -2
  55. package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
  56. package/dist/components/form/engine/OptionFieldMessages.js +73 -12
  57. package/dist/components/form/engine/OptionFieldMessages.js.map +1 -1
  58. package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
  59. package/dist/components/form/engine/_structuredData/SchemaDataView.js +7 -1
  60. package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
  61. package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
  62. package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
  63. package/dist/components/form/engine/readFirst.d.ts +42 -1
  64. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  65. package/dist/components/form/engine/readFirst.js +74 -7
  66. package/dist/components/form/engine/readFirst.js.map +1 -1
  67. package/dist/components/form/engine/rendererTypes.d.ts +13 -0
  68. package/dist/components/form/engine/rendererTypes.d.ts.map +1 -1
  69. package/dist/components/form/engine/rendererTypes.js.map +1 -1
  70. package/dist/components/form/engine/rowMenuContext.d.ts +78 -0
  71. package/dist/components/form/engine/rowMenuContext.d.ts.map +1 -0
  72. package/dist/components/form/engine/rowMenuContext.js +103 -0
  73. package/dist/components/form/engine/rowMenuContext.js.map +1 -0
  74. package/dist/components/form/engine/typeChoices.d.ts +42 -0
  75. package/dist/components/form/engine/typeChoices.d.ts.map +1 -0
  76. package/dist/components/form/engine/typeChoices.js +31 -0
  77. package/dist/components/form/engine/typeChoices.js.map +1 -0
  78. package/dist/components/form/expressions/DpqlRendering.d.ts +26 -0
  79. package/dist/components/form/expressions/DpqlRendering.d.ts.map +1 -0
  80. package/dist/components/form/expressions/DpqlRendering.js +53 -0
  81. package/dist/components/form/expressions/DpqlRendering.js.map +1 -0
  82. package/dist/components/form/expressions/ExpressionField.d.ts +7 -1
  83. package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
  84. package/dist/components/form/expressions/ExpressionField.js +203 -45
  85. package/dist/components/form/expressions/ExpressionField.js.map +1 -1
  86. package/dist/components/form/expressions/argumentPresence.d.ts +97 -0
  87. package/dist/components/form/expressions/argumentPresence.d.ts.map +1 -0
  88. package/dist/components/form/expressions/argumentPresence.js +203 -0
  89. package/dist/components/form/expressions/argumentPresence.js.map +1 -0
  90. package/dist/components/form/expressions/builder/argumentLabel.d.ts.map +1 -1
  91. package/dist/components/form/expressions/builder/argumentLabel.js +9 -4
  92. package/dist/components/form/expressions/builder/argumentLabel.js.map +1 -1
  93. package/dist/components/form/expressions/builder/index.d.ts +15 -2
  94. package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
  95. package/dist/components/form/expressions/builder/index.js +20 -58
  96. package/dist/components/form/expressions/builder/index.js.map +1 -1
  97. package/dist/components/form/expressions/builder/renderTemplate.d.ts +4 -1
  98. package/dist/components/form/expressions/builder/renderTemplate.d.ts.map +1 -1
  99. package/dist/components/form/expressions/builder/renderTemplate.js +10 -67
  100. package/dist/components/form/expressions/builder/renderTemplate.js.map +1 -1
  101. package/dist/components/form/expressions/dpqlMockLanguage.d.ts +76 -0
  102. package/dist/components/form/expressions/dpqlMockLanguage.d.ts.map +1 -0
  103. package/dist/components/form/expressions/dpqlMockLanguage.js +525 -0
  104. package/dist/components/form/expressions/dpqlMockLanguage.js.map +1 -0
  105. package/dist/components/form/expressions/dpqlMockLsp.d.ts +31 -2
  106. package/dist/components/form/expressions/dpqlMockLsp.d.ts.map +1 -1
  107. package/dist/components/form/expressions/dpqlMockLsp.js +86 -80
  108. package/dist/components/form/expressions/dpqlMockLsp.js.map +1 -1
  109. package/dist/components/form/expressions/mockExpressions.d.ts.map +1 -1
  110. package/dist/components/form/expressions/mockExpressions.js +8 -4
  111. package/dist/components/form/expressions/mockExpressions.js.map +1 -1
  112. package/dist/components/form/expressions/renderExpressionToText.d.ts +1 -1
  113. package/dist/components/form/expressions/renderExpressionToText.d.ts.map +1 -1
  114. package/dist/components/form/expressions/renderExpressionToText.js +95 -19
  115. package/dist/components/form/expressions/renderExpressionToText.js.map +1 -1
  116. package/dist/components/form/expressions/types.d.ts +7 -0
  117. package/dist/components/form/expressions/types.d.ts.map +1 -1
  118. package/dist/components/form/expressions/useRenderExpression.d.ts +7 -16
  119. package/dist/components/form/expressions/useRenderExpression.d.ts.map +1 -1
  120. package/dist/components/form/expressions/useRenderExpression.js +50 -126
  121. package/dist/components/form/expressions/useRenderExpression.js.map +1 -1
  122. package/dist/components/form/fields/Field.d.ts.map +1 -1
  123. package/dist/components/form/fields/Field.js +3 -1
  124. package/dist/components/form/fields/Field.js.map +1 -1
  125. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +11 -1
  126. package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
  127. package/dist/components/form/fields/allowed-values/AllowedValues.js +14 -2
  128. package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
  129. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  130. package/dist/components/form/fields/auto/AutoFormField.js +91 -28
  131. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  132. package/dist/components/form/fields/date/Date.d.ts +1 -1
  133. package/dist/components/form/fields/date/Date.d.ts.map +1 -1
  134. package/dist/components/form/fields/date/Date.js +16 -2
  135. package/dist/components/form/fields/date/Date.js.map +1 -1
  136. package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
  137. package/dist/components/form/fields/long-string/LongString.js +14 -2
  138. package/dist/components/form/fields/long-string/LongString.js.map +1 -1
  139. package/dist/components/form/fields/rich-text/RichText.d.ts +35 -2
  140. package/dist/components/form/fields/rich-text/RichText.d.ts.map +1 -1
  141. package/dist/components/form/fields/rich-text/RichText.js +153 -12
  142. package/dist/components/form/fields/rich-text/RichText.js.map +1 -1
  143. package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts +2 -1
  144. package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts.map +1 -1
  145. package/dist/components/form/fields/template/ReadOnlyTemplateTag.js +3 -2
  146. package/dist/components/form/fields/template/ReadOnlyTemplateTag.js.map +1 -1
  147. package/dist/components/form/fields/template/TemplateField.d.ts +34 -2
  148. package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
  149. package/dist/components/form/fields/template/TemplateField.js +604 -58
  150. package/dist/components/form/fields/template/TemplateField.js.map +1 -1
  151. package/dist/components/form/index.d.ts +1 -0
  152. package/dist/components/form/index.d.ts.map +1 -1
  153. package/dist/components/form/index.js +1 -0
  154. package/dist/components/form/index.js.map +1 -1
  155. package/dist/components/smartEditor/SmartEditor.d.ts.map +1 -1
  156. package/dist/components/smartEditor/SmartEditor.js +29 -8
  157. package/dist/components/smartEditor/SmartEditor.js.map +1 -1
  158. package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts +8 -0
  159. package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts.map +1 -1
  160. package/dist/components/smartEditor/__fixtures__/mockLspServer.js +53 -10
  161. package/dist/components/smartEditor/__fixtures__/mockLspServer.js.map +1 -1
  162. package/dist/components/smartEditor/useLspSession.d.ts +5 -1
  163. package/dist/components/smartEditor/useLspSession.d.ts.map +1 -1
  164. package/dist/components/smartEditor/useLspSession.js +16 -2
  165. package/dist/components/smartEditor/useLspSession.js.map +1 -1
  166. package/dist/helpers/dpqlDetection.d.ts +58 -0
  167. package/dist/helpers/dpqlDetection.d.ts.map +1 -0
  168. package/dist/helpers/dpqlDetection.js +164 -0
  169. package/dist/helpers/dpqlDetection.js.map +1 -0
  170. package/dist/helpers/optionUiTypes.d.ts +19 -3
  171. package/dist/helpers/optionUiTypes.d.ts.map +1 -1
  172. package/dist/helpers/optionUiTypes.js +20 -1
  173. package/dist/helpers/optionUiTypes.js.map +1 -1
  174. package/dist/helpers/options.d.ts +37 -0
  175. package/dist/helpers/options.d.ts.map +1 -1
  176. package/dist/helpers/options.js +78 -1
  177. package/dist/helpers/options.js.map +1 -1
  178. package/dist/helpers/templateItems.d.ts +47 -0
  179. package/dist/helpers/templateItems.d.ts.map +1 -0
  180. package/dist/helpers/templateItems.js +88 -0
  181. package/dist/helpers/templateItems.js.map +1 -0
  182. package/dist/helpers/templateText.d.ts +37 -0
  183. package/dist/helpers/templateText.d.ts.map +1 -0
  184. package/dist/helpers/templateText.js +64 -0
  185. package/dist/helpers/templateText.js.map +1 -0
  186. package/dist/helpers/templates.d.ts +19 -11
  187. package/dist/helpers/templates.d.ts.map +1 -1
  188. package/dist/helpers/templates.js +46 -29
  189. package/dist/helpers/templates.js.map +1 -1
  190. package/dist/helpers/validations.d.ts.map +1 -1
  191. package/dist/helpers/validations.js +56 -9
  192. package/dist/helpers/validations.js.map +1 -1
  193. package/dist/hooks/useArgSchema.d.ts +2 -1
  194. package/dist/hooks/useArgSchema.d.ts.map +1 -1
  195. package/dist/hooks/useFetch/useFetch.d.ts +3 -1
  196. package/dist/hooks/useFetch/useFetch.d.ts.map +1 -1
  197. package/dist/hooks/useFetch/useFetch.js +47 -9
  198. package/dist/hooks/useFetch/useFetch.js.map +1 -1
  199. package/dist/hooks/useTemplates.d.ts +20 -0
  200. package/dist/hooks/useTemplates.d.ts.map +1 -1
  201. package/dist/hooks/useTemplates.js +34 -2
  202. package/dist/hooks/useTemplates.js.map +1 -1
  203. package/dist/index.d.ts +2 -1
  204. package/dist/index.d.ts.map +1 -1
  205. package/dist/index.js +5 -1
  206. package/dist/index.js.map +1 -1
  207. package/dist/stories/storyNetwork.d.ts +36 -0
  208. package/dist/stories/storyNetwork.d.ts.map +1 -0
  209. package/dist/stories/storyNetwork.js +82 -0
  210. package/dist/stories/storyNetwork.js.map +1 -0
  211. package/dist/utils/fetch.d.ts +151 -1
  212. package/dist/utils/fetch.d.ts.map +1 -1
  213. package/dist/utils/fetch.js +256 -44
  214. package/dist/utils/fetch.js.map +1 -1
  215. package/dist/utils/lspClient.d.ts +6 -0
  216. package/dist/utils/lspClient.d.ts.map +1 -1
  217. package/dist/utils/lspClient.js +62 -11
  218. package/dist/utils/lspClient.js.map +1 -1
  219. package/dist/utils/websocket.d.ts +6 -0
  220. package/dist/utils/websocket.d.ts.map +1 -1
  221. package/dist/utils/websocket.js +15 -7
  222. package/dist/utils/websocket.js.map +1 -1
  223. package/package.json +2 -2
  224. package/src/components/dpqlEditor/DpqlEditor.stories.tsx +3 -119
  225. package/src/components/dpqlEditor/DpqlEditor.tsx +5 -2
  226. package/src/components/dpqlEditor/dpqlHelpers.ts +20 -1
  227. package/src/components/dpqlEditor/dpqlProbe.ts +165 -0
  228. package/src/components/dpqlEditor/dpqlTags.ts +13 -0
  229. package/src/components/dpqlEditor/index.ts +4 -0
  230. package/src/components/dpqlEditor/types.ts +38 -2
  231. package/src/components/dpqlEditor/useDpqlProbe.ts +33 -0
  232. package/src/components/dpqlEditor/useDpqlSession.ts +20 -4
  233. package/src/components/form/engine/CompactRow.tsx +240 -51
  234. package/src/components/form/engine/CompactToolbar.tsx +10 -3
  235. package/src/components/form/engine/FormEngine.stories.tsx +431 -124
  236. package/src/components/form/engine/FormEngine.tsx +508 -90
  237. package/src/components/form/engine/FormFieldsSkeleton.tsx +76 -0
  238. package/src/components/form/engine/OptionFieldMessages.tsx +103 -12
  239. package/src/components/form/engine/_structuredData/SchemaDataView.tsx +11 -0
  240. package/src/components/form/engine/compactToolbarContext.ts +1 -1
  241. package/src/components/form/engine/readFirst.ts +86 -7
  242. package/src/components/form/engine/rendererTypes.ts +12 -0
  243. package/src/components/form/engine/rowMenuContext.ts +159 -0
  244. package/src/components/form/engine/typeChoices.ts +61 -0
  245. package/src/components/form/expressions/DpqlRendering.tsx +85 -0
  246. package/src/components/form/expressions/ExpressionField.stories.tsx +826 -48
  247. package/src/components/form/expressions/ExpressionField.tsx +266 -54
  248. package/src/components/form/expressions/argumentPresence.ts +200 -0
  249. package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +31 -14
  250. package/src/components/form/expressions/builder/argumentLabel.tsx +10 -4
  251. package/src/components/form/expressions/builder/index.tsx +39 -77
  252. package/src/components/form/expressions/builder/renderTemplate.tsx +23 -56
  253. package/src/components/form/expressions/dpqlMockLanguage.ts +565 -0
  254. package/src/components/form/expressions/dpqlMockLsp.ts +109 -83
  255. package/src/components/form/expressions/mockExpressions.ts +8 -4
  256. package/src/components/form/expressions/renderExpressionToText.ts +112 -22
  257. package/src/components/form/expressions/types.ts +7 -0
  258. package/src/components/form/expressions/useRenderExpression.ts +43 -127
  259. package/src/components/form/fields/Field.tsx +3 -2
  260. package/src/components/form/fields/allowed-values/AllowedValues.tsx +13 -2
  261. package/src/components/form/fields/auto/AutoFormField.stories.tsx +85 -18
  262. package/src/components/form/fields/auto/AutoFormField.tsx +90 -20
  263. package/src/components/form/fields/date/Date.tsx +17 -1
  264. package/src/components/form/fields/long-string/LongString.tsx +15 -3
  265. package/src/components/form/fields/rich-text/RichText.tsx +235 -30
  266. package/src/components/form/fields/template/ReadOnlyTemplateTag.tsx +4 -2
  267. package/src/components/form/fields/template/TemplateField.stories.tsx +93 -14
  268. package/src/components/form/fields/template/TemplateField.tsx +823 -129
  269. package/src/components/form/index.tsx +1 -0
  270. package/src/components/log/Log.stories.tsx +2 -1
  271. package/src/components/smartEditor/SmartEditor.tsx +41 -9
  272. package/src/components/smartEditor/__fixtures__/mockLspServer.ts +52 -3
  273. package/src/components/smartEditor/useLspSession.ts +21 -3
  274. package/src/helpers/dpqlDetection.ts +209 -0
  275. package/src/helpers/optionUiTypes.ts +22 -0
  276. package/src/helpers/options.ts +70 -0
  277. package/src/helpers/templateItems.ts +81 -0
  278. package/src/helpers/templateText.ts +92 -0
  279. package/src/helpers/templates.ts +47 -37
  280. package/src/helpers/validations.ts +59 -9
  281. package/src/hooks/useFetch/useFetch.stories.tsx +6 -5
  282. package/src/hooks/useFetch/useFetch.tsx +53 -7
  283. package/src/hooks/useStorage/useStorage.stories.tsx +2 -1
  284. package/src/hooks/useTemplates.ts +41 -0
  285. package/src/hooks/useWebSocket/useWebsocket.stories.tsx +2 -1
  286. package/src/index.tsx +14 -1
  287. package/src/stores/currentUser/currentUser.stories.tsx +2 -1
  288. package/src/stories/storyNetwork.ts +92 -0
  289. package/src/utils/fetch.ts +311 -21
  290. package/src/utils/lspClient.ts +68 -11
  291. package/src/utils/websocket.ts +20 -9
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
3
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
4
+ if (ar || !(i in from)) {
5
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
6
+ ar[i] = from[i];
7
+ }
8
+ }
9
+ return to.concat(ar || Array.prototype.slice.call(from));
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.GLOBAL_STORY_MOCK_DATA = exports.storySocketUrl = exports.storyApiUrl = exports.STORY_QORUS_INSTANCE = void 0;
13
+ // Copyright 2026 Qore Technologies, s.r.o.
14
+ // Where a story's network goes: the instance its Reqraft points at, the URLs
15
+ // its mocks must intercept, and the requests every story is mocked for.
16
+ //
17
+ // `query()` and `ReqraftWebSocket` build absolute URLs from the configured
18
+ // instance, and both mock layers match on the host as well as the path —
19
+ // storybook-addon-mock keys on `host + pathname`, mock-socket on the URL minus
20
+ // its query. A mock written against a hard-coded host stops matching the moment
21
+ // the instance is overridden, and the request goes out to the real network
22
+ // instead, silently. Build mock URLs with the helpers below.
23
+ var useQorusTypes_1 = require("../hooks/useQorusTypes");
24
+ var fetch_1 = require("../utils/fetch");
25
+ var websocket_1 = require("../utils/websocket");
26
+ /**
27
+ * The instance every story's Reqraft is initialized with. Override it with
28
+ * `REACT_APP_QORUS_INSTANCE` (or `QORUS_INSTANCE`) to run live stories against
29
+ * your own Qorus; mocks built from it follow the override.
30
+ */
31
+ exports.STORY_QORUS_INSTANCE = process.env.REACT_APP_QORUS_INSTANCE || 'https://hq.qoretechnologies.com:8092/';
32
+ /** The URL `query()` requests for `path`. */
33
+ var storyApiUrl = function (path) {
34
+ return (0, fetch_1.buildReqraftApiUrl)(exports.STORY_QORUS_INSTANCE, path);
35
+ };
36
+ exports.storyApiUrl = storyApiUrl;
37
+ /**
38
+ * The URL `ReqraftWebSocket` dials for `path`, token omitted — mock-socket
39
+ * matches servers without the query string.
40
+ */
41
+ var storySocketUrl = function (path) {
42
+ return (0, websocket_1.buildReqraftSocketUrl)(exports.STORY_QORUS_INSTANCE, path);
43
+ };
44
+ exports.storySocketUrl = storySocketUrl;
45
+ /** A GET of `path` answered with `response`. */
46
+ var mockGet = function (path, response) { return [
47
+ { url: (0, exports.storyApiUrl)(path), method: 'GET', status: 200, response: response },
48
+ ]; };
49
+ /**
50
+ * The type catalogue, pinned to the built-in list. `useQorusTypes` uses a
51
+ * reachable server's list *instead of* the built-in one, so an unmocked story
52
+ * renders whichever labels that server happens to have — and every FormEngine
53
+ * shows its loading skeleton until the request settles, which against an
54
+ * unreachable instance is never.
55
+ */
56
+ var QORUS_TYPE_INFO_MOCK_DATA = mockGet('system/qorus-type-info', useQorusTypes_1.defaultQorusTypes);
57
+ /**
58
+ * The system expression catalogue, empty. `useExpressions` fetches it whenever
59
+ * functions are allowed — even when the story passes its own list, which is
60
+ * merged in as extras — and TemplateField shows a skeleton in place of "Use
61
+ * Expression" until it arrives. Stories that need functions provide them
62
+ * (`expressions`, or their own `mockData` for this URL).
63
+ */
64
+ var EXPRESSIONS_CATALOGUE_MOCK_DATA = mockGet('system?action=expressions&context=ui', []);
65
+ /**
66
+ * `ReqraftWebSocket`'s server probe, which every reconnect attempt awaits
67
+ * before it dials. Unanswered, no attempt is ever made — a mock socket server
68
+ * that comes back is never reconnected to, and one that stays down is never
69
+ * given up on. The probe only needs an answer; its body is not read.
70
+ */
71
+ var SERVER_STATUS_MOCK_DATA = mockGet('system/pid', {});
72
+ /**
73
+ * Requests components make on their own, whatever the story is about —
74
+ * mounting a FormEngine fetches the type catalogue; allowing functions fetches
75
+ * the expression catalogue; a reconnecting socket probes the server.
76
+ * Registered for every story as storybook-addon-mock's `globalMockData`
77
+ * (`.storybook/preview.tsx`, and mirrored for the Vitest run in
78
+ * `.storybook/vitest.setup.ts`); a story's own `mockData` entry for the same
79
+ * URL takes precedence.
80
+ */
81
+ exports.GLOBAL_STORY_MOCK_DATA = __spreadArray(__spreadArray(__spreadArray([], QORUS_TYPE_INFO_MOCK_DATA, true), EXPRESSIONS_CATALOGUE_MOCK_DATA, true), SERVER_STATUS_MOCK_DATA, true);
82
+ //# sourceMappingURL=storyNetwork.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storyNetwork.js","sourceRoot":"","sources":["../../src/stories/storyNetwork.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2C;AAC3C,6EAA6E;AAC7E,wEAAwE;AACxE,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,+EAA+E;AAC/E,gFAAgF;AAChF,2EAA2E;AAC3E,6DAA6D;AAC7D,wDAA2D;AAC3D,wCAAoD;AACpD,gDAA2D;AAgB3D;;;;GAIG;AACU,QAAA,oBAAoB,GAC/B,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,uCAAuC,CAAC;AAElF,6CAA6C;AACtC,IAAM,WAAW,GAAG,UAAC,IAAY;IACtC,OAAA,IAAA,0BAAkB,EAAC,4BAAoB,EAAE,IAAI,CAAC;AAA9C,CAA8C,CAAC;AADpC,QAAA,WAAW,eACyB;AAEjD;;;GAGG;AACI,IAAM,cAAc,GAAG,UAAC,IAAY;IACzC,OAAA,IAAA,iCAAqB,EAAC,4BAAoB,EAAE,IAAI,CAAC;AAAjD,CAAiD,CAAC;AADvC,QAAA,cAAc,kBACyB;AAEpD,gDAAgD;AAChD,IAAM,OAAO,GAAG,UAAC,IAAY,EAAE,QAA4B,IAA0B,OAAA;IACnF,EAAE,GAAG,EAAE,IAAA,mBAAW,EAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,UAAA,EAAE;CACjE,EAFoF,CAEpF,CAAC;AAEF;;;;;;GAMG;AACH,IAAM,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,EAAE,iCAAiB,CAAC,CAAC;AAEvF;;;;;;GAMG;AACH,IAAM,+BAA+B,GAAG,OAAO,CAAC,sCAAsC,EAAE,EAAE,CAAC,CAAC;AAE5F;;;;;GAKG;AACH,IAAM,uBAAuB,GAAG,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;AAE1D;;;;;;;;GAQG;AACU,QAAA,sBAAsB,iDAC9B,yBAAyB,SACzB,+BAA+B,SAC/B,uBAAuB,QAC1B"}
@@ -10,19 +10,169 @@ export interface IReqraftFetchResponse<T> {
10
10
  ok: boolean;
11
11
  code?: number;
12
12
  error?: any;
13
+ /**
14
+ * The parsed error body on a non-ok response, when the server sent JSON.
15
+ *
16
+ * Qorus errors carry `{ err, desc }`; `error` above is only the HTTP reason
17
+ * phrase, which is why a caller that wanted the sentence had to reach into
18
+ * `data`. Consumers that need the code (`err`) or the message (`desc`) should
19
+ * read this rather than re-parsing.
20
+ */
21
+ errorBody?: Record<string, any>;
22
+ /**
23
+ * The response text when the body was NOT valid JSON. A non-JSON error would
24
+ * otherwise arrive as `{}` with only a reason phrase, discarding whatever the
25
+ * server actually said.
26
+ */
27
+ rawText?: string;
13
28
  response: Response;
14
29
  }
15
30
  export declare const fetchConfig: IReqraftFetchConfig;
16
31
  export declare const setupFetch: ({ instance, instanceToken, instanceRbacDisabled, unauthorizedRedirect, }: IReqraftFetchConfig) => void;
32
+ /**
33
+ * The API path a caller asked for, without the leading slash the prefix already
34
+ * carries.
35
+ *
36
+ * `doFetchData` builds `${instance}api/latest/${url}`, and that prefix ENDS in a
37
+ * slash — so a caller writing `/dataprovider/arg_schemas/x` produced
38
+ * `api/latest//dataprovider/arg_schemas/x`. Qorus serves it, which is how both
39
+ * spellings survived side by side (`useArgSchema` writes one, `CompactRow` and
40
+ * `AutoFormField` the other), but it is not harmless: the query cache is keyed
41
+ * on the url, so `/x` and `x` were two cache entries and two requests for one
42
+ * resource.
43
+ *
44
+ * Normalised here, once, rather than at each call site — the convention is
45
+ * invisible from a caller's point of view and the next one would get it wrong
46
+ * again. Only applied when the prefix is added: a caller that opts out of the
47
+ * prefix owns its whole path, leading slash included.
48
+ */
49
+ export declare const reqraftApiPath: (url: string, noApiPrefix?: boolean) => string;
50
+ /**
51
+ * The one cache key for a request, used by every caller in every downstream
52
+ * project so that one resource is one entry and one in-flight request.
53
+ *
54
+ * `instance` and the token take part because both change WHICH server and WHOSE
55
+ * data answers: a call that overrides the instance, or that carries an explicit
56
+ * token, is a different resource that happens to share a path.
57
+ */
58
+ export declare const reqraftCacheKey: ({ url, method, body, noApiPrefix, instance, token, }: Pick<IReqraftQueryConfig, 'url' | 'method' | 'body' | 'noApiPrefix' | 'instance' | 'token'>) => string;
59
+ /**
60
+ * The URL `query()` requests for `url` on `instance` — the single definition.
61
+ * Story mocks build their URLs with it too, so they cannot drift from what the
62
+ * code actually dials.
63
+ *
64
+ * `noApiPrefix` means the caller owns the WHOLE url — an absolute address for
65
+ * another service, which is the only thing reqraft itself uses it for
66
+ * (`useExpressions` sets it exactly when `expressionsUrl` is `http(s)://…`).
67
+ * Prepending the instance there built `https://instance:8011/https://other/…`.
68
+ */
69
+ export declare const buildReqraftApiUrl: (instance: string, url: string, noApiPrefix?: boolean) => string;
17
70
  export interface IReqraftQueryConfig {
18
71
  url: string;
19
72
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
20
73
  body?: Record<string | number, any>;
21
74
  cache?: boolean;
22
75
  queryClient?: QueryClient;
76
+ /**
77
+ * The `url` is a complete address and is used verbatim — neither the instance
78
+ * nor `api/latest/` is prepended, and its leading slash is left alone. For
79
+ * reaching a service that is not this Qorus instance.
80
+ */
23
81
  noApiPrefix?: boolean;
24
82
  /** Override the global instance URL for this single call (e.g. to target a different port). */
25
83
  instance?: string;
84
+ /** Extra request headers, merged over the default `Content-Type`. */
85
+ headers?: Record<string, string>;
86
+ /**
87
+ * A bearer token for THIS call, instead of the configured instance token —
88
+ * for a route that is authenticated as somebody other than the current app
89
+ * session. Takes part in the cache key.
90
+ */
91
+ token?: string;
92
+ /**
93
+ * An explicit cache key, for a caller that must group or separate requests
94
+ * differently from the default `path:method:body` identity.
95
+ */
96
+ cacheKey?: string;
97
+ /**
98
+ * How long a cached response counts as fresh, in ms. Defaults to 5 minutes
99
+ * when `cache` is on. `Infinity` keeps it for the life of the page — what a
100
+ * caller wants for a catalogue that cannot change without a server restart.
101
+ */
102
+ staleTime?: number;
103
+ /**
104
+ * Whether a 401 on this request should send the page to
105
+ * `fetchConfig.unauthorizedRedirect`. Defaults to `true`.
106
+ *
107
+ * A 401 only means "this app's session expired" when the request actually
108
+ * carried this app's credential. A call that targets another service, or that
109
+ * hands over an explicit token, proves nothing about the session — signing the
110
+ * user out because an unrelated credential was refused is wrong. Callers that
111
+ * own their own auth policy (or that must never navigate, such as a test
112
+ * runner or a Storybook preview) pass `false`.
113
+ */
114
+ redirectOnUnauthorized?: boolean;
26
115
  }
27
- export declare function query<T>({ url, method, body, cache, queryClient, noApiPrefix, instance, }: IReqraftQueryConfig): Promise<IReqraftFetchResponse<T>>;
116
+ /**
117
+ * The single request mechanism.
118
+ *
119
+ * Every request in reqraft AND in the projects built on it goes through here,
120
+ * so that one resource has one cache entry and one in-flight request no matter
121
+ * which library, hook or component asked for it. A downstream project that
122
+ * keeps its own fetch helper (qorus-ide's `fetchData` is the one this was
123
+ * written for) should adapt onto this rather than hold a second cache: two
124
+ * caches over one API cannot see each other's in-flight requests, so any
125
+ * resource both libraries want is fetched twice by construction.
126
+ */
127
+ /**
128
+ * Put a resource the HOST already has into the cache `query` reads.
129
+ *
130
+ * The comment on `query` states the problem: two caches over one API cannot see
131
+ * each other's in-flight requests, so any resource both libraries want is
132
+ * fetched twice by construction. This is the seam that lets a host settle it
133
+ * without either side giving up its own loader.
134
+ *
135
+ * The case it was written for: the Qorus IDE warm-starts
136
+ * `/system/qorus-type-info` from `index.html`, before the bundle has even
137
+ * parsed, because its whole boot gates on it — and then reqraft's own
138
+ * `useQorusTypes` asked for it again on the first form's mount. Measured on the
139
+ * live IDE at 419ms and 2777ms, the same URL, the same answer.
140
+ *
141
+ * Seeding is enough to stop the second request: `query` goes through
142
+ * `fetchQuery` with a `staleTime`, and a fresh entry is returned without the
143
+ * query function ever running. `useFetch` reads the same cache directly, so it
144
+ * also skips its loading state and renders the answer on its first paint.
145
+ *
146
+ * Only for a resource the host has genuinely FETCHED. Seeding a guess would
147
+ * make every consumer believe a request had succeeded.
148
+ */
149
+ export declare const seedQueryCache: <T>({ url, method, body, noApiPrefix, instance, token, data, queryClient, }: Pick<IReqraftQueryConfig, 'url' | 'method' | 'body' | 'noApiPrefix' | 'instance' | 'token' | 'queryClient'> & {
150
+ data: T;
151
+ }) => void;
152
+ export declare function query<T>({ url, method, body, cache, queryClient, noApiPrefix, instance, headers, token, cacheKey, staleTime, redirectOnUnauthorized, }: IReqraftQueryConfig): Promise<IReqraftFetchResponse<T>>;
153
+ export interface IReqraftRawResponse {
154
+ ok: boolean;
155
+ code?: number;
156
+ error?: string;
157
+ /** The response bytes. Undefined on a non-ok response. */
158
+ blob?: Blob;
159
+ /** The `Content-Type` the bytes were served with, without parameters. */
160
+ mime?: string;
161
+ }
162
+ /**
163
+ * Fetch a resource whose body is NOT JSON — a file, an export, a log.
164
+ *
165
+ * Shares `doFetchData` with `query`, which owns the API prefix, the bearer token
166
+ * and `credentials: 'include'`. The point is that raw responses do not become a
167
+ * second, drifting copy of that auth handling.
168
+ *
169
+ * Nothing is cached: these payloads are large and read once.
170
+ *
171
+ * @param accept the `Accept` header. Endpoints that negotiate on the file's own
172
+ * MIME type answer **406** unless the caller accepts that type, and the caller
173
+ * usually cannot know it ahead of time, so this accepts anything by default.
174
+ */
175
+ export declare function queryRaw({ url, method, body, noApiPrefix, instance, headers, token, accept, redirectOnUnauthorized, }: Omit<IReqraftQueryConfig, 'cache' | 'queryClient' | 'cacheKey' | 'staleTime'> & {
176
+ accept?: string;
177
+ }): Promise<IReqraftRawResponse>;
28
178
  //# sourceMappingURL=fetch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,MAAM,CAAC;CACjE;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,IAAI,EAAE,CAAC,CAAC;IACR,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,mBAIzB,CAAC;AAIF,eAAO,MAAM,UAAU,6EAKpB,mBAAmB,SAQrB,CAAC;AAgCF,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,KAAK,CAAC,CAAC,EAAE,EAC7B,GAAG,EACH,MAAc,EACd,IAAI,EACJ,KAAY,EACZ,WAAgC,EAChC,WAAmB,EACnB,QAAQ,GACT,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAmDzD"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
14
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
15
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -36,7 +47,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
36
47
  }
37
48
  };
38
49
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.query = exports.setupFetch = exports.fetchConfig = void 0;
50
+ exports.queryRaw = exports.query = exports.seedQueryCache = exports.buildReqraftApiUrl = exports.reqraftCacheKey = exports.reqraftApiPath = exports.setupFetch = exports.fetchConfig = void 0;
40
51
  var ReqraftProvider_1 = require("../providers/ReqraftProvider");
41
52
  exports.fetchConfig = {
42
53
  instance: window.location.origin + '/',
@@ -54,22 +65,89 @@ var setupFetch = function (_a) {
54
65
  }
55
66
  };
56
67
  exports.setupFetch = setupFetch;
68
+ /**
69
+ * The API path a caller asked for, without the leading slash the prefix already
70
+ * carries.
71
+ *
72
+ * `doFetchData` builds `${instance}api/latest/${url}`, and that prefix ENDS in a
73
+ * slash — so a caller writing `/dataprovider/arg_schemas/x` produced
74
+ * `api/latest//dataprovider/arg_schemas/x`. Qorus serves it, which is how both
75
+ * spellings survived side by side (`useArgSchema` writes one, `CompactRow` and
76
+ * `AutoFormField` the other), but it is not harmless: the query cache is keyed
77
+ * on the url, so `/x` and `x` were two cache entries and two requests for one
78
+ * resource.
79
+ *
80
+ * Normalised here, once, rather than at each call site — the convention is
81
+ * invisible from a caller's point of view and the next one would get it wrong
82
+ * again. Only applied when the prefix is added: a caller that opts out of the
83
+ * prefix owns its whole path, leading slash included.
84
+ */
85
+ var reqraftApiPath = function (url, noApiPrefix) {
86
+ if (noApiPrefix === void 0) { noApiPrefix = false; }
87
+ return noApiPrefix ? url : url.replace(/^\/+/, '');
88
+ };
89
+ exports.reqraftApiPath = reqraftApiPath;
90
+ /**
91
+ * A cheap, stable, non-reversible marker for a bearer token.
92
+ *
93
+ * Two callers holding DIFFERENT tokens are two identities and must not share a
94
+ * cached response, so the token has to take part in the cache key — but a raw
95
+ * token in a key is a credential sitting in devtools' query inspector. djb2 is
96
+ * enough to tell two tokens apart, which is all the key needs.
97
+ */
98
+ var tokenMarker = function (token) {
99
+ if (!token) {
100
+ return '';
101
+ }
102
+ var hash = 5381;
103
+ for (var index = 0; index < token.length; index++) {
104
+ hash = ((hash << 5) + hash + token.charCodeAt(index)) | 0;
105
+ }
106
+ return ":t".concat((hash >>> 0).toString(36));
107
+ };
108
+ /**
109
+ * The one cache key for a request, used by every caller in every downstream
110
+ * project so that one resource is one entry and one in-flight request.
111
+ *
112
+ * `instance` and the token take part because both change WHICH server and WHOSE
113
+ * data answers: a call that overrides the instance, or that carries an explicit
114
+ * token, is a different resource that happens to share a path.
115
+ */
116
+ var reqraftCacheKey = function (_a) {
117
+ var url = _a.url, _b = _a.method, method = _b === void 0 ? 'GET' : _b, body = _a.body, noApiPrefix = _a.noApiPrefix, instance = _a.instance, token = _a.token;
118
+ return "".concat((0, exports.reqraftApiPath)(url, noApiPrefix), ":").concat(method, ":").concat(JSON.stringify(body || {})).concat(instance && instance !== exports.fetchConfig.instance ? ":@".concat(instance) : '').concat(tokenMarker(token));
119
+ };
120
+ exports.reqraftCacheKey = reqraftCacheKey;
121
+ /**
122
+ * The URL `query()` requests for `url` on `instance` — the single definition.
123
+ * Story mocks build their URLs with it too, so they cannot drift from what the
124
+ * code actually dials.
125
+ *
126
+ * `noApiPrefix` means the caller owns the WHOLE url — an absolute address for
127
+ * another service, which is the only thing reqraft itself uses it for
128
+ * (`useExpressions` sets it exactly when `expressionsUrl` is `http(s)://…`).
129
+ * Prepending the instance there built `https://instance:8011/https://other/…`.
130
+ */
131
+ var buildReqraftApiUrl = function (instance, url, noApiPrefix) {
132
+ if (noApiPrefix === void 0) { noApiPrefix = false; }
133
+ return noApiPrefix ? url : "".concat(instance, "api/latest/").concat((0, exports.reqraftApiPath)(url));
134
+ };
135
+ exports.buildReqraftApiUrl = buildReqraftApiUrl;
57
136
  function doFetchData(url_1) {
58
- return __awaiter(this, arguments, void 0, function (url, method, body, noApiPrefix, instance) {
59
- var headers;
137
+ return __awaiter(this, arguments, void 0, function (url, method, body, noApiPrefix, instance, headers, token) {
138
+ var finalHeaders, finalToken;
60
139
  if (method === void 0) { method = 'GET'; }
61
140
  if (noApiPrefix === void 0) { noApiPrefix = false; }
62
141
  if (instance === void 0) { instance = exports.fetchConfig.instance; }
63
142
  return __generator(this, function (_a) {
64
- headers = {
65
- 'Content-Type': 'application/json',
66
- };
67
- if (exports.fetchConfig.instanceToken && !exports.fetchConfig.instanceRbacDisabled) {
68
- headers['Authorization'] = "Bearer ".concat(exports.fetchConfig.instanceToken);
143
+ finalHeaders = __assign({ 'Content-Type': 'application/json' }, (headers !== null && headers !== void 0 ? headers : {}));
144
+ finalToken = token !== null && token !== void 0 ? token : (exports.fetchConfig.instanceRbacDisabled ? undefined : exports.fetchConfig.instanceToken);
145
+ if (finalToken && !finalHeaders['Authorization']) {
146
+ finalHeaders['Authorization'] = "Bearer ".concat(finalToken);
69
147
  }
70
- return [2 /*return*/, fetch("".concat(instance).concat(noApiPrefix ? '' : 'api/latest/').concat(url), {
148
+ return [2 /*return*/, fetch((0, exports.buildReqraftApiUrl)(instance, url, noApiPrefix), {
71
149
  method: method,
72
- headers: headers,
150
+ headers: finalHeaders,
73
151
  body: JSON.stringify(body),
74
152
  credentials: 'include',
75
153
  }).catch(function (error) {
@@ -81,61 +159,132 @@ function doFetchData(url_1) {
81
159
  });
82
160
  });
83
161
  }
162
+ /**
163
+ * Reads a response body without consuming it, and says whether it was JSON.
164
+ *
165
+ * `data` stays `{}` for a body that is empty or not JSON, which is the contract
166
+ * reqraft's consumers have always been given. The text is handed back separately
167
+ * as `rawText` so an error that was not JSON still carries whatever the server
168
+ * said, instead of being flattened to a bare reason phrase.
169
+ */
170
+ var readBody = function (response) { return __awaiter(void 0, void 0, void 0, function () {
171
+ var rawText;
172
+ return __generator(this, function (_a) {
173
+ switch (_a.label) {
174
+ case 0: return [4 /*yield*/, response.clone().text()];
175
+ case 1:
176
+ rawText = _a.sent();
177
+ try {
178
+ return [2 /*return*/, { data: JSON.parse(rawText) }];
179
+ }
180
+ catch (_error) {
181
+ return [2 /*return*/, { data: {}, rawText: rawText }];
182
+ }
183
+ return [2 /*return*/];
184
+ }
185
+ });
186
+ }); };
187
+ /**
188
+ * The single request mechanism.
189
+ *
190
+ * Every request in reqraft AND in the projects built on it goes through here,
191
+ * so that one resource has one cache entry and one in-flight request no matter
192
+ * which library, hook or component asked for it. A downstream project that
193
+ * keeps its own fetch helper (qorus-ide's `fetchData` is the one this was
194
+ * written for) should adapt onto this rather than hold a second cache: two
195
+ * caches over one API cannot see each other's in-flight requests, so any
196
+ * resource both libraries want is fetched twice by construction.
197
+ */
198
+ /**
199
+ * Put a resource the HOST already has into the cache `query` reads.
200
+ *
201
+ * The comment on `query` states the problem: two caches over one API cannot see
202
+ * each other's in-flight requests, so any resource both libraries want is
203
+ * fetched twice by construction. This is the seam that lets a host settle it
204
+ * without either side giving up its own loader.
205
+ *
206
+ * The case it was written for: the Qorus IDE warm-starts
207
+ * `/system/qorus-type-info` from `index.html`, before the bundle has even
208
+ * parsed, because its whole boot gates on it — and then reqraft's own
209
+ * `useQorusTypes` asked for it again on the first form's mount. Measured on the
210
+ * live IDE at 419ms and 2777ms, the same URL, the same answer.
211
+ *
212
+ * Seeding is enough to stop the second request: `query` goes through
213
+ * `fetchQuery` with a `staleTime`, and a fresh entry is returned without the
214
+ * query function ever running. `useFetch` reads the same cache directly, so it
215
+ * also skips its loading state and renders the answer on its first paint.
216
+ *
217
+ * Only for a resource the host has genuinely FETCHED. Seeding a guess would
218
+ * make every consumer believe a request had succeeded.
219
+ */
220
+ var seedQueryCache = function (_a) {
221
+ var url = _a.url, _b = _a.method, method = _b === void 0 ? 'GET' : _b, body = _a.body, noApiPrefix = _a.noApiPrefix, instance = _a.instance, token = _a.token, data = _a.data, _c = _a.queryClient, queryClient = _c === void 0 ? ReqraftProvider_1.ReqraftQueryClient : _c;
222
+ var key = (0, exports.reqraftCacheKey)({ url: url, method: method, body: body, noApiPrefix: noApiPrefix, instance: instance, token: token });
223
+ queryClient.setQueryData([key], {
224
+ data: data,
225
+ rawText: undefined,
226
+ ok: true,
227
+ status: 200,
228
+ statusText: 'OK',
229
+ response: undefined,
230
+ });
231
+ };
232
+ exports.seedQueryCache = seedQueryCache;
84
233
  function query(_a) {
85
234
  return __awaiter(this, arguments, void 0, function (_b) {
86
- var shouldCache, cacheKey, requestData;
235
+ var shouldCache, key, requestData;
87
236
  var _this = this;
88
- var url = _b.url, _c = _b.method, method = _c === void 0 ? 'GET' : _c, body = _b.body, _d = _b.cache, cache = _d === void 0 ? true : _d, _e = _b.queryClient, queryClient = _e === void 0 ? ReqraftProvider_1.ReqraftQueryClient : _e, _f = _b.noApiPrefix, noApiPrefix = _f === void 0 ? false : _f, instance = _b.instance;
89
- return __generator(this, function (_g) {
90
- switch (_g.label) {
237
+ var url = _b.url, _c = _b.method, method = _c === void 0 ? 'GET' : _c, body = _b.body, _d = _b.cache, cache = _d === void 0 ? true : _d, _e = _b.queryClient, queryClient = _e === void 0 ? ReqraftProvider_1.ReqraftQueryClient : _e, _f = _b.noApiPrefix, noApiPrefix = _f === void 0 ? false : _f, instance = _b.instance, headers = _b.headers, token = _b.token, cacheKey = _b.cacheKey, staleTime = _b.staleTime, _g = _b.redirectOnUnauthorized, redirectOnUnauthorized = _g === void 0 ? true : _g;
238
+ return __generator(this, function (_h) {
239
+ switch (_h.label) {
91
240
  case 0:
92
241
  shouldCache = method === 'DELETE' || method === 'POST' ? false : cache;
93
- cacheKey = "".concat(url, ":").concat(method, ":").concat(JSON.stringify(body || {}));
242
+ key = cacheKey !== null && cacheKey !== void 0 ? cacheKey : (0, exports.reqraftCacheKey)({ url: url, method: method, body: body, noApiPrefix: noApiPrefix, instance: instance, token: token });
94
243
  return [4 /*yield*/, queryClient.fetchQuery({
95
- queryKey: [cacheKey],
244
+ queryKey: [key],
96
245
  queryFn: function () { return __awaiter(_this, void 0, void 0, function () {
97
- var response, clone, data, error_1;
98
- return __generator(this, function (_a) {
99
- switch (_a.label) {
100
- case 0: return [4 /*yield*/, doFetchData(url, method, body, noApiPrefix, instance)];
246
+ var response, _a, data, rawText;
247
+ return __generator(this, function (_b) {
248
+ switch (_b.label) {
249
+ case 0: return [4 /*yield*/, doFetchData(url, method, body, noApiPrefix, instance, headers, token)];
101
250
  case 1:
102
- response = _a.sent();
103
- if (response.status === 401 && exports.fetchConfig.unauthorizedRedirect) {
104
- window.location.href = exports.fetchConfig.unauthorizedRedirect(window.location);
251
+ response = _b.sent();
252
+ if (response.status === 401 && redirectOnUnauthorized && exports.fetchConfig.unauthorizedRedirect) {
253
+ // `replace`, not an assignment: the page being left is dead, and a
254
+ // history entry for it means Back lands on a view that can only 401
255
+ // again.
256
+ window.location.replace(exports.fetchConfig.unauthorizedRedirect(window.location));
105
257
  }
106
- clone = response.clone();
107
- _a.label = 2;
258
+ return [4 /*yield*/, readBody(response)];
108
259
  case 2:
109
- _a.trys.push([2, 4, , 5]);
110
- return [4 /*yield*/, clone.json()];
111
- case 3:
112
- data = _a.sent();
113
- return [3 /*break*/, 5];
114
- case 4:
115
- error_1 = _a.sent();
116
- data = {};
117
- return [3 /*break*/, 5];
118
- case 5: return [2 /*return*/, {
119
- data: data,
120
- ok: response.ok,
121
- status: response.status,
122
- statusText: response.statusText,
123
- response: response,
124
- }];
260
+ _a = _b.sent(), data = _a.data, rawText = _a.rawText;
261
+ return [2 /*return*/, {
262
+ data: data,
263
+ rawText: rawText,
264
+ ok: response.ok,
265
+ status: response.status,
266
+ statusText: response.statusText,
267
+ response: response,
268
+ }];
125
269
  }
126
270
  });
127
271
  }); },
128
- staleTime: shouldCache ? CACHE_EXPIRATION_TIME : 0,
272
+ staleTime: shouldCache ? (staleTime !== null && staleTime !== void 0 ? staleTime : CACHE_EXPIRATION_TIME) : 0,
129
273
  })];
130
274
  case 1:
131
- requestData = _g.sent();
275
+ requestData = _h.sent();
132
276
  if (!requestData.ok) {
133
- queryClient.invalidateQueries({ queryKey: [cacheKey] });
277
+ queryClient.invalidateQueries({ queryKey: [key] });
134
278
  return [2 /*return*/, {
135
279
  data: requestData.data,
136
280
  ok: false,
137
281
  code: requestData.status,
138
282
  error: requestData.statusText,
283
+ // Only when the body really was JSON: `data` is `{}` for a non-JSON body,
284
+ // and an empty object masquerading as a parsed error tells a caller
285
+ // nothing while looking like it did.
286
+ errorBody: requestData.rawText === undefined ? requestData.data : undefined,
287
+ rawText: requestData.rawText,
139
288
  response: requestData.response,
140
289
  }];
141
290
  }
@@ -143,6 +292,7 @@ function query(_a) {
143
292
  data: requestData.data,
144
293
  ok: true,
145
294
  code: requestData.status,
295
+ rawText: requestData.rawText,
146
296
  response: requestData.response,
147
297
  }];
148
298
  }
@@ -150,4 +300,66 @@ function query(_a) {
150
300
  });
151
301
  }
152
302
  exports.query = query;
303
+ /**
304
+ * Fetch a resource whose body is NOT JSON — a file, an export, a log.
305
+ *
306
+ * Shares `doFetchData` with `query`, which owns the API prefix, the bearer token
307
+ * and `credentials: 'include'`. The point is that raw responses do not become a
308
+ * second, drifting copy of that auth handling.
309
+ *
310
+ * Nothing is cached: these payloads are large and read once.
311
+ *
312
+ * @param accept the `Accept` header. Endpoints that negotiate on the file's own
313
+ * MIME type answer **406** unless the caller accepts that type, and the caller
314
+ * usually cannot know it ahead of time, so this accepts anything by default.
315
+ */
316
+ function queryRaw(_a) {
317
+ return __awaiter(this, arguments, void 0, function (_b) {
318
+ var response, error, _error_1, error_1;
319
+ var _c;
320
+ var _d, _e;
321
+ var url = _b.url, _f = _b.method, method = _f === void 0 ? 'GET' : _f, body = _b.body, _g = _b.noApiPrefix, noApiPrefix = _g === void 0 ? false : _g, instance = _b.instance, headers = _b.headers, token = _b.token, _h = _b.accept, accept = _h === void 0 ? '*/*' : _h, _j = _b.redirectOnUnauthorized, redirectOnUnauthorized = _j === void 0 ? true : _j;
322
+ return __generator(this, function (_k) {
323
+ switch (_k.label) {
324
+ case 0:
325
+ _k.trys.push([0, 8, , 9]);
326
+ return [4 /*yield*/, doFetchData(url, method, body, noApiPrefix, instance, __assign({ Accept: accept }, (headers !== null && headers !== void 0 ? headers : {})), token)];
327
+ case 1:
328
+ response = _k.sent();
329
+ if (response.status === 401 && redirectOnUnauthorized && exports.fetchConfig.unauthorizedRedirect) {
330
+ window.location.replace(exports.fetchConfig.unauthorizedRedirect(window.location));
331
+ }
332
+ if (!!response.ok) return [3 /*break*/, 6];
333
+ error = void 0;
334
+ _k.label = 2;
335
+ case 2:
336
+ _k.trys.push([2, 4, , 5]);
337
+ return [4 /*yield*/, response.json()];
338
+ case 3:
339
+ // an error body is still JSON even when the success body is not
340
+ error = (_d = (_k.sent()).desc) !== null && _d !== void 0 ? _d : response.statusText;
341
+ return [3 /*break*/, 5];
342
+ case 4:
343
+ _error_1 = _k.sent();
344
+ error = response.statusText;
345
+ return [3 /*break*/, 5];
346
+ case 5: return [2 /*return*/, { ok: false, code: response.status, error: error }];
347
+ case 6:
348
+ _c = {
349
+ ok: true,
350
+ code: response.status
351
+ };
352
+ return [4 /*yield*/, response.blob()];
353
+ case 7: return [2 /*return*/, (_c.blob = _k.sent(),
354
+ _c.mime = ((_e = response.headers.get('content-type')) !== null && _e !== void 0 ? _e : '').split(';')[0].trim() || undefined,
355
+ _c)];
356
+ case 8:
357
+ error_1 = _k.sent();
358
+ return [2 /*return*/, { ok: false, error: error_1 instanceof Error ? error_1.message : String(error_1) }];
359
+ case 9: return [2 /*return*/];
360
+ }
361
+ });
362
+ });
363
+ }
364
+ exports.queryRaw = queryRaw;
153
365
  //# sourceMappingURL=fetch.js.map