@multiplatform.one/frappe-ui 7.28.0 → 7.29.0

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 (618) hide show
  1. package/dist/cjs/ChartCard.native.js.map +1 -1
  2. package/dist/cjs/FileBrowser/AttachLibrary.native.js.map +1 -1
  3. package/dist/cjs/FileBrowser/folderTree.native.js.map +1 -1
  4. package/dist/cjs/FileBrowser/index.cjs +20 -3
  5. package/dist/cjs/FileBrowser/index.native.js +20 -3
  6. package/dist/cjs/FileBrowser/index.native.js.map +1 -1
  7. package/dist/cjs/FileBrowser/types.native.js.map +1 -1
  8. package/dist/cjs/FileBrowser/viewPersistence.native.js.map +1 -1
  9. package/dist/cjs/FormSidebar.native.js.map +1 -1
  10. package/dist/cjs/FrappeAssignment.native.js.map +1 -1
  11. package/dist/cjs/FrappeCalendar.cjs +3 -2
  12. package/dist/cjs/FrappeCalendar.native.js +3 -2
  13. package/dist/cjs/FrappeCalendar.native.js.map +1 -1
  14. package/dist/cjs/FrappeChartCard.native.js.map +1 -1
  15. package/dist/cjs/FrappeConnectionIndicator.native.js.map +1 -1
  16. package/dist/cjs/FrappeDashboard.native.js.map +1 -1
  17. package/dist/cjs/FrappeForm.cjs +148 -464
  18. package/dist/cjs/FrappeForm.native.js +153 -634
  19. package/dist/cjs/FrappeForm.native.js.map +1 -1
  20. package/dist/cjs/FrappeFormActions.native.js.map +1 -1
  21. package/dist/cjs/FrappeFormConnections.native.js.map +1 -1
  22. package/dist/cjs/FrappeGantt.native.js.map +1 -1
  23. package/dist/cjs/FrappeImageView.native.js.map +1 -1
  24. package/dist/cjs/FrappeInsights.native.js.map +1 -1
  25. package/dist/cjs/FrappeKPICard.native.js.map +1 -1
  26. package/dist/cjs/FrappeKanban.native.js.map +1 -1
  27. package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
  28. package/dist/cjs/FrappeList.native.js.map +1 -1
  29. package/dist/cjs/FrappeListView.cjs +5 -27
  30. package/dist/cjs/FrappeListView.native.js +11 -32
  31. package/dist/cjs/FrappeListView.native.js.map +1 -1
  32. package/dist/cjs/FrappeNotConfigured.native.js.map +1 -1
  33. package/dist/cjs/FrappeProvider.native.js.map +1 -1
  34. package/dist/cjs/FrappeReconnectIndicator.native.js.map +1 -1
  35. package/dist/cjs/FrappeRecordView.native.js.map +1 -1
  36. package/dist/cjs/FrappeReportBuilder.cjs +523 -309
  37. package/dist/cjs/FrappeReportBuilder.native.js +658 -353
  38. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  39. package/dist/cjs/FrappeReportView.cjs +35 -234
  40. package/dist/cjs/FrappeReportView.native.js +42 -286
  41. package/dist/cjs/FrappeReportView.native.js.map +1 -1
  42. package/dist/cjs/FrappeRowsReader.native.js.map +1 -1
  43. package/dist/cjs/FrappeTable.native.js.map +1 -1
  44. package/dist/cjs/FrappeTreeView.native.js.map +1 -1
  45. package/dist/cjs/SyncErrorNotice.native.js.map +1 -1
  46. package/dist/cjs/commentActions.native.js.map +1 -1
  47. package/dist/cjs/components/attachments.native.js.map +1 -1
  48. package/dist/cjs/components/tags.native.js.map +1 -1
  49. package/dist/cjs/components/timeline.native.js.map +1 -1
  50. package/dist/cjs/dependsOn.cjs +2 -2
  51. package/dist/cjs/dependsOn.native.js +1 -2
  52. package/dist/cjs/dependsOn.native.js.map +1 -1
  53. package/dist/cjs/desk/DeskFormPage.native.js.map +1 -1
  54. package/dist/cjs/desk/DeskFormSidebar.native.js.map +1 -1
  55. package/dist/cjs/desk/DeskListPage.native.js.map +1 -1
  56. package/dist/cjs/desk/DeskShell.native.js.map +1 -1
  57. package/dist/cjs/desk/DeskSidebar.native.js.map +1 -1
  58. package/dist/cjs/desk/awesomebar.native.js.map +1 -1
  59. package/dist/cjs/fieldOverrides.native.js.map +1 -1
  60. package/dist/cjs/fieldRegistry.native.js +31 -31
  61. package/dist/cjs/fieldRegistry.native.js.map +1 -1
  62. package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
  63. package/dist/cjs/fields/Check/index.native.js.map +1 -1
  64. package/dist/cjs/fields/CodeEditor/index.native.js.map +1 -1
  65. package/dist/cjs/fields/Color/index.native.js.map +1 -1
  66. package/dist/cjs/fields/Data/index.native.js.map +1 -1
  67. package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
  68. package/dist/cjs/fields/Date/types.native.js.map +1 -1
  69. package/dist/cjs/fields/Date/wire.native.js.map +1 -1
  70. package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
  71. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  72. package/dist/cjs/fields/DynamicLink.native.js.map +1 -1
  73. package/dist/cjs/fields/FileUpload.native.js.map +1 -1
  74. package/dist/cjs/fields/FileUploadField/index.native.js.map +1 -1
  75. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  76. package/dist/cjs/fields/HTML/index.native.js.map +1 -1
  77. package/dist/cjs/fields/Heading/index.native.js.map +1 -1
  78. package/dist/cjs/fields/Icon/index.native.js.map +1 -1
  79. package/dist/cjs/fields/Link.native.js.map +1 -1
  80. package/dist/cjs/fields/LinkTree.native.js.map +1 -1
  81. package/dist/cjs/fields/LongText/index.native.js.map +1 -1
  82. package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
  83. package/dist/cjs/fields/Numeric/index.native.js.map +1 -1
  84. package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
  85. package/dist/cjs/fields/Password/index.native.js.map +1 -1
  86. package/dist/cjs/fields/Phone/index.native.js.map +1 -1
  87. package/dist/cjs/fields/Progress/index.native.js.map +1 -1
  88. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  89. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  90. package/dist/cjs/fields/ReadOnly/index.native.js.map +1 -1
  91. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  92. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  93. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  94. package/dist/cjs/fields/SmallText/index.native.js.map +1 -1
  95. package/dist/cjs/fields/Switch/index.native.js.map +1 -1
  96. package/dist/cjs/fields/TableMultiSelect.native.js.map +1 -1
  97. package/dist/cjs/fields/TextEditor/types.native.js.map +1 -1
  98. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  99. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  100. package/dist/cjs/fields/shared/EditorPreviewPanes.cjs +2 -2
  101. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js +2 -2
  102. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  103. package/dist/cjs/filterFields.native.js.map +1 -1
  104. package/dist/cjs/formEngine/createPrefill.native.js.map +1 -1
  105. package/dist/cjs/formEngine/dirtyTracking.native.js.map +1 -1
  106. package/dist/cjs/formEngine/docLifecycle.native.js.map +1 -1
  107. package/dist/cjs/formEngine/docPermissions.cjs +20 -0
  108. package/dist/cjs/formEngine/docPermissions.native.js +69 -0
  109. package/dist/cjs/formEngine/docPermissions.native.js.map +1 -1
  110. package/dist/cjs/formEngine/doctypeMeta.native.js.map +1 -1
  111. package/dist/cjs/formEngine/fetchFrom.native.js.map +1 -1
  112. package/dist/cjs/formEngine/fieldPermissions.native.js.map +1 -1
  113. package/dist/cjs/formEngine/formActions.native.js.map +1 -1
  114. package/dist/cjs/formEngine/formLayout.native.js.map +1 -1
  115. package/dist/cjs/formEngine/index.cjs +2 -0
  116. package/dist/cjs/formEngine/index.native.js +2 -0
  117. package/dist/cjs/formEngine/index.native.js.map +1 -1
  118. package/dist/cjs/formEngine/useAmendedAs.native.js.map +1 -1
  119. package/dist/cjs/formEngine/useDocRights.native.js.map +1 -1
  120. package/dist/cjs/formEngine/useFormEngine.native.js.map +1 -1
  121. package/dist/cjs/formEngine/useSessionRoles.native.js.map +1 -1
  122. package/dist/cjs/frappeConnections.native.js.map +1 -1
  123. package/dist/cjs/frappeEventColor.native.js.map +1 -1
  124. package/dist/cjs/frappeNavigation.native.js.map +1 -1
  125. package/dist/cjs/frappeStoryTarget.native.js.map +1 -1
  126. package/dist/cjs/frappeUsers.native.js.map +1 -1
  127. package/dist/cjs/index.cjs +67 -7
  128. package/dist/cjs/index.native.js +101 -41
  129. package/dist/cjs/index.native.js.map +1 -1
  130. package/dist/cjs/insights/InsightsFacetTags.native.js.map +1 -1
  131. package/dist/cjs/insights/InsightsKpiBand.native.js.map +1 -1
  132. package/dist/cjs/insights/InsightsLeaders.native.js.map +1 -1
  133. package/dist/cjs/insights/InsightsRecords.native.js.map +1 -1
  134. package/dist/cjs/insights/InsightsTable.native.js.map +1 -1
  135. package/dist/cjs/insights/insightsData.native.js.map +1 -1
  136. package/dist/cjs/insights/insightsRecord.native.js.map +1 -1
  137. package/dist/cjs/list/FacetBadge.native.js.map +1 -1
  138. package/dist/cjs/list/FacetRail.native.js.map +1 -1
  139. package/dist/cjs/list/ImageWell.native.js.map +1 -1
  140. package/dist/cjs/list/ListControls.native.js.map +1 -1
  141. package/dist/cjs/list/ListToastHost.native.js.map +1 -1
  142. package/dist/cjs/list/RangeFilter.native.js.map +1 -1
  143. package/dist/cjs/list/ShufflePanel.native.js.map +1 -1
  144. package/dist/cjs/list/facetReading.native.js.map +1 -1
  145. package/dist/cjs/list/favorites.native.js.map +1 -1
  146. package/dist/cjs/list/listColumns.native.js.map +1 -1
  147. package/dist/cjs/list/listFields.native.js.map +1 -1
  148. package/dist/cjs/list/listFormat.native.js.map +1 -1
  149. package/dist/cjs/list/listState.native.js.map +1 -1
  150. package/dist/cjs/list/recordLook.native.js.map +1 -1
  151. package/dist/cjs/list/statusColors.native.js.map +1 -1
  152. package/dist/cjs/list/useListControls.native.js.map +1 -1
  153. package/dist/cjs/liveErrors.cjs +8 -2
  154. package/dist/cjs/liveErrors.native.js +8 -2
  155. package/dist/cjs/liveErrors.native.js.map +1 -1
  156. package/dist/cjs/measures.cjs +31 -0
  157. package/dist/cjs/measures.native.js +34 -0
  158. package/dist/cjs/measures.native.js.map +1 -0
  159. package/dist/cjs/record/RecordBars.native.js.map +1 -1
  160. package/dist/cjs/record/RecordGallery.native.js.map +1 -1
  161. package/dist/cjs/record/RecordHero.native.js.map +1 -1
  162. package/dist/cjs/record/RecordPage.native.js.map +1 -1
  163. package/dist/cjs/record/RecordPager.native.js.map +1 -1
  164. package/dist/cjs/record/RecordRows.native.js.map +1 -1
  165. package/dist/cjs/record/recordData.native.js.map +1 -1
  166. package/dist/cjs/record/recordSections.native.js.map +1 -1
  167. package/dist/cjs/recordShape.cjs +103 -0
  168. package/dist/cjs/recordShape.native.js +115 -0
  169. package/dist/cjs/recordShape.native.js.map +1 -0
  170. package/dist/cjs/report/ReportGrid.cjs +453 -0
  171. package/dist/cjs/report/ReportGrid.native.js +510 -0
  172. package/dist/cjs/report/ReportGrid.native.js.map +1 -0
  173. package/dist/cjs/report/ReportViewToolbar.cjs +253 -0
  174. package/dist/cjs/report/ReportViewToolbar.native.js +303 -0
  175. package/dist/cjs/report/ReportViewToolbar.native.js.map +1 -0
  176. package/dist/cjs/report/queryReport.cjs +444 -0
  177. package/dist/cjs/report/queryReport.native.js +588 -0
  178. package/dist/cjs/report/queryReport.native.js.map +1 -0
  179. package/dist/cjs/report/queryReportColumns.cjs +131 -0
  180. package/dist/cjs/report/queryReportColumns.native.js +159 -0
  181. package/dist/cjs/report/queryReportColumns.native.js.map +1 -0
  182. package/dist/cjs/report/reportViewModel.cjs +386 -0
  183. package/dist/cjs/report/reportViewModel.native.js +657 -0
  184. package/dist/cjs/report/reportViewModel.native.js.map +1 -0
  185. package/dist/cjs/report/savedReports.cjs +137 -0
  186. package/dist/cjs/report/savedReports.native.js +169 -0
  187. package/dist/cjs/report/savedReports.native.js.map +1 -0
  188. package/dist/cjs/report/useFrappeReport.cjs +184 -0
  189. package/dist/cjs/report/useFrappeReport.native.js +214 -0
  190. package/dist/cjs/report/useFrappeReport.native.js.map +1 -0
  191. package/dist/cjs/report/useQueryReport.cjs +201 -0
  192. package/dist/cjs/report/useQueryReport.native.js +233 -0
  193. package/dist/cjs/report/useQueryReport.native.js.map +1 -0
  194. package/dist/cjs/resolveControl.native.js.map +1 -1
  195. package/dist/cjs/schemaForm/SchemaWizard.native.js.map +1 -1
  196. package/dist/cjs/schemaForm/applyFieldOrder.native.js.map +1 -1
  197. package/dist/cjs/schemaForm/index.native.js +1 -1
  198. package/dist/cjs/schemaForm/index.native.js.map +1 -1
  199. package/dist/cjs/shared/devWarn.native.js.map +1 -1
  200. package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
  201. package/dist/cjs/syncError.native.js.map +1 -1
  202. package/dist/cjs/useConnectionFilters.native.js.map +1 -1
  203. package/dist/cjs/useFrappeAggregate.native.js.map +1 -1
  204. package/dist/cjs/useFrappeFacets.native.js.map +1 -1
  205. package/dist/cjs/useFrappeForm.cjs +558 -0
  206. package/dist/cjs/useFrappeForm.native.js +714 -0
  207. package/dist/cjs/useFrappeForm.native.js.map +1 -0
  208. package/dist/cjs/useFrappePagination.native.js.map +1 -1
  209. package/dist/cjs/useFrappeRows.native.js.map +1 -1
  210. package/dist/esm/ChartCard.native.js.map +1 -1
  211. package/dist/esm/FileBrowser/AttachLibrary.native.js.map +1 -1
  212. package/dist/esm/FileBrowser/folderTree.native.js.map +1 -1
  213. package/dist/esm/FileBrowser/index.mjs +20 -3
  214. package/dist/esm/FileBrowser/index.mjs.map +1 -1
  215. package/dist/esm/FileBrowser/index.native.js +20 -3
  216. package/dist/esm/FileBrowser/index.native.js.map +1 -1
  217. package/dist/esm/FileBrowser/types.native.js.map +1 -1
  218. package/dist/esm/FileBrowser/viewPersistence.native.js.map +1 -1
  219. package/dist/esm/FormSidebar.native.js.map +1 -1
  220. package/dist/esm/FrappeAssignment.native.js.map +1 -1
  221. package/dist/esm/FrappeCalendar.mjs +4 -3
  222. package/dist/esm/FrappeCalendar.mjs.map +1 -1
  223. package/dist/esm/FrappeCalendar.native.js +4 -3
  224. package/dist/esm/FrappeCalendar.native.js.map +1 -1
  225. package/dist/esm/FrappeChartCard.native.js.map +1 -1
  226. package/dist/esm/FrappeConnectionIndicator.native.js.map +1 -1
  227. package/dist/esm/FrappeDashboard.native.js.map +1 -1
  228. package/dist/esm/FrappeForm.mjs +151 -467
  229. package/dist/esm/FrappeForm.mjs.map +1 -1
  230. package/dist/esm/FrappeForm.native.js +155 -636
  231. package/dist/esm/FrappeForm.native.js.map +1 -1
  232. package/dist/esm/FrappeFormActions.native.js.map +1 -1
  233. package/dist/esm/FrappeFormConnections.native.js.map +1 -1
  234. package/dist/esm/FrappeGantt.native.js.map +1 -1
  235. package/dist/esm/FrappeImageView.native.js.map +1 -1
  236. package/dist/esm/FrappeInsights.native.js.map +1 -1
  237. package/dist/esm/FrappeKPICard.native.js.map +1 -1
  238. package/dist/esm/FrappeKanban.native.js.map +1 -1
  239. package/dist/esm/FrappeLikedBy.native.js.map +1 -1
  240. package/dist/esm/FrappeList.native.js.map +1 -1
  241. package/dist/esm/FrappeListView.mjs +6 -28
  242. package/dist/esm/FrappeListView.mjs.map +1 -1
  243. package/dist/esm/FrappeListView.native.js +12 -33
  244. package/dist/esm/FrappeListView.native.js.map +1 -1
  245. package/dist/esm/FrappeNotConfigured.native.js.map +1 -1
  246. package/dist/esm/FrappeProvider.native.js.map +1 -1
  247. package/dist/esm/FrappeReconnectIndicator.native.js.map +1 -1
  248. package/dist/esm/FrappeRecordView.native.js.map +1 -1
  249. package/dist/esm/FrappeReportBuilder.mjs +526 -312
  250. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  251. package/dist/esm/FrappeReportBuilder.native.js +661 -356
  252. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  253. package/dist/esm/FrappeReportView.mjs +30 -229
  254. package/dist/esm/FrappeReportView.mjs.map +1 -1
  255. package/dist/esm/FrappeReportView.native.js +34 -278
  256. package/dist/esm/FrappeReportView.native.js.map +1 -1
  257. package/dist/esm/FrappeRowsReader.native.js.map +1 -1
  258. package/dist/esm/FrappeTable.native.js.map +1 -1
  259. package/dist/esm/FrappeTreeView.native.js.map +1 -1
  260. package/dist/esm/SyncErrorNotice.native.js.map +1 -1
  261. package/dist/esm/commentActions.native.js.map +1 -1
  262. package/dist/esm/components/attachments.native.js.map +1 -1
  263. package/dist/esm/components/tags.native.js.map +1 -1
  264. package/dist/esm/components/timeline.native.js.map +1 -1
  265. package/dist/esm/dependsOn.mjs +2 -2
  266. package/dist/esm/dependsOn.mjs.map +1 -1
  267. package/dist/esm/dependsOn.native.js +1 -2
  268. package/dist/esm/dependsOn.native.js.map +1 -1
  269. package/dist/esm/desk/DeskFormPage.native.js.map +1 -1
  270. package/dist/esm/desk/DeskFormSidebar.native.js.map +1 -1
  271. package/dist/esm/desk/DeskListPage.native.js.map +1 -1
  272. package/dist/esm/desk/DeskShell.native.js.map +1 -1
  273. package/dist/esm/desk/DeskSidebar.native.js.map +1 -1
  274. package/dist/esm/desk/awesomebar.native.js.map +1 -1
  275. package/dist/esm/fieldOverrides.native.js.map +1 -1
  276. package/dist/esm/fieldRegistry.native.js.map +1 -1
  277. package/dist/esm/fields/Barcode/index.native.js.map +1 -1
  278. package/dist/esm/fields/Check/index.native.js.map +1 -1
  279. package/dist/esm/fields/CodeEditor/index.native.js.map +1 -1
  280. package/dist/esm/fields/Color/index.native.js.map +1 -1
  281. package/dist/esm/fields/Data/index.native.js.map +1 -1
  282. package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
  283. package/dist/esm/fields/Date/types.native.js.map +1 -1
  284. package/dist/esm/fields/Date/wire.native.js.map +1 -1
  285. package/dist/esm/fields/DateRange/index.native.js.map +1 -1
  286. package/dist/esm/fields/Duration/index.native.js.map +1 -1
  287. package/dist/esm/fields/DynamicLink.native.js.map +1 -1
  288. package/dist/esm/fields/FileUpload.native.js.map +1 -1
  289. package/dist/esm/fields/FileUploadField/index.native.js.map +1 -1
  290. package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
  291. package/dist/esm/fields/HTML/index.native.js.map +1 -1
  292. package/dist/esm/fields/Heading/index.native.js.map +1 -1
  293. package/dist/esm/fields/Icon/index.native.js.map +1 -1
  294. package/dist/esm/fields/Link.native.js.map +1 -1
  295. package/dist/esm/fields/LinkTree.native.js.map +1 -1
  296. package/dist/esm/fields/LongText/index.native.js.map +1 -1
  297. package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
  298. package/dist/esm/fields/Numeric/index.native.js.map +1 -1
  299. package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
  300. package/dist/esm/fields/Password/index.native.js.map +1 -1
  301. package/dist/esm/fields/Phone/index.native.js.map +1 -1
  302. package/dist/esm/fields/Progress/index.native.js.map +1 -1
  303. package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
  304. package/dist/esm/fields/Rating/index.native.js.map +1 -1
  305. package/dist/esm/fields/ReadOnly/index.native.js.map +1 -1
  306. package/dist/esm/fields/Select/index.native.js.map +1 -1
  307. package/dist/esm/fields/Signature/index.native.js.map +1 -1
  308. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  309. package/dist/esm/fields/SmallText/index.native.js.map +1 -1
  310. package/dist/esm/fields/Switch/index.native.js.map +1 -1
  311. package/dist/esm/fields/TableMultiSelect.native.js.map +1 -1
  312. package/dist/esm/fields/TextEditor/types.native.js.map +1 -1
  313. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  314. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  315. package/dist/esm/fields/shared/EditorPreviewPanes.mjs +2 -2
  316. package/dist/esm/fields/shared/EditorPreviewPanes.mjs.map +1 -1
  317. package/dist/esm/fields/shared/EditorPreviewPanes.native.js +2 -2
  318. package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  319. package/dist/esm/filterFields.native.js.map +1 -1
  320. package/dist/esm/formEngine/createPrefill.native.js.map +1 -1
  321. package/dist/esm/formEngine/dirtyTracking.native.js.map +1 -1
  322. package/dist/esm/formEngine/docLifecycle.native.js.map +1 -1
  323. package/dist/esm/formEngine/docPermissions.mjs +19 -1
  324. package/dist/esm/formEngine/docPermissions.mjs.map +1 -1
  325. package/dist/esm/formEngine/docPermissions.native.js +68 -1
  326. package/dist/esm/formEngine/docPermissions.native.js.map +1 -1
  327. package/dist/esm/formEngine/doctypeMeta.native.js.map +1 -1
  328. package/dist/esm/formEngine/fetchFrom.native.js.map +1 -1
  329. package/dist/esm/formEngine/fieldPermissions.native.js.map +1 -1
  330. package/dist/esm/formEngine/formActions.native.js.map +1 -1
  331. package/dist/esm/formEngine/formLayout.native.js.map +1 -1
  332. package/dist/esm/formEngine/index.mjs +2 -2
  333. package/dist/esm/formEngine/index.mjs.map +1 -1
  334. package/dist/esm/formEngine/index.native.js +2 -2
  335. package/dist/esm/formEngine/index.native.js.map +1 -1
  336. package/dist/esm/formEngine/useAmendedAs.native.js.map +1 -1
  337. package/dist/esm/formEngine/useDocRights.native.js.map +1 -1
  338. package/dist/esm/formEngine/useFormEngine.native.js.map +1 -1
  339. package/dist/esm/formEngine/useSessionRoles.native.js.map +1 -1
  340. package/dist/esm/frappeConnections.native.js.map +1 -1
  341. package/dist/esm/frappeEventColor.native.js.map +1 -1
  342. package/dist/esm/frappeNavigation.native.js.map +1 -1
  343. package/dist/esm/frappeStoryTarget.native.js.map +1 -1
  344. package/dist/esm/frappeUsers.native.js.map +1 -1
  345. package/dist/esm/index.mjs +16 -4
  346. package/dist/esm/index.mjs.map +1 -1
  347. package/dist/esm/index.native.js +16 -4
  348. package/dist/esm/index.native.js.map +1 -1
  349. package/dist/esm/insights/InsightsFacetTags.native.js.map +1 -1
  350. package/dist/esm/insights/InsightsKpiBand.native.js.map +1 -1
  351. package/dist/esm/insights/InsightsLeaders.native.js.map +1 -1
  352. package/dist/esm/insights/InsightsRecords.native.js.map +1 -1
  353. package/dist/esm/insights/InsightsTable.native.js.map +1 -1
  354. package/dist/esm/insights/insightsData.native.js.map +1 -1
  355. package/dist/esm/insights/insightsRecord.native.js.map +1 -1
  356. package/dist/esm/list/FacetBadge.native.js.map +1 -1
  357. package/dist/esm/list/FacetRail.native.js.map +1 -1
  358. package/dist/esm/list/ImageWell.native.js.map +1 -1
  359. package/dist/esm/list/ListControls.native.js.map +1 -1
  360. package/dist/esm/list/ListToastHost.native.js.map +1 -1
  361. package/dist/esm/list/RangeFilter.native.js.map +1 -1
  362. package/dist/esm/list/ShufflePanel.native.js.map +1 -1
  363. package/dist/esm/list/facetReading.native.js.map +1 -1
  364. package/dist/esm/list/favorites.native.js.map +1 -1
  365. package/dist/esm/list/listColumns.native.js.map +1 -1
  366. package/dist/esm/list/listFields.native.js.map +1 -1
  367. package/dist/esm/list/listFormat.native.js.map +1 -1
  368. package/dist/esm/list/listState.native.js.map +1 -1
  369. package/dist/esm/list/recordLook.native.js.map +1 -1
  370. package/dist/esm/list/statusColors.native.js.map +1 -1
  371. package/dist/esm/list/useListControls.native.js.map +1 -1
  372. package/dist/esm/liveErrors.mjs +8 -3
  373. package/dist/esm/liveErrors.mjs.map +1 -1
  374. package/dist/esm/liveErrors.native.js +8 -3
  375. package/dist/esm/liveErrors.native.js.map +1 -1
  376. package/dist/esm/measures.mjs +5 -0
  377. package/dist/esm/measures.mjs.map +1 -0
  378. package/dist/esm/measures.native.js +5 -0
  379. package/dist/esm/measures.native.js.map +1 -0
  380. package/dist/esm/record/RecordBars.native.js.map +1 -1
  381. package/dist/esm/record/RecordGallery.native.js.map +1 -1
  382. package/dist/esm/record/RecordHero.native.js.map +1 -1
  383. package/dist/esm/record/RecordPage.native.js.map +1 -1
  384. package/dist/esm/record/RecordPager.native.js.map +1 -1
  385. package/dist/esm/record/RecordRows.native.js.map +1 -1
  386. package/dist/esm/record/recordData.native.js.map +1 -1
  387. package/dist/esm/record/recordSections.native.js.map +1 -1
  388. package/dist/esm/recordShape.mjs +74 -0
  389. package/dist/esm/recordShape.mjs.map +1 -0
  390. package/dist/esm/recordShape.native.js +83 -0
  391. package/dist/esm/recordShape.native.js.map +1 -0
  392. package/dist/esm/report/ReportGrid.mjs +428 -0
  393. package/dist/esm/report/ReportGrid.mjs.map +1 -0
  394. package/dist/esm/report/ReportGrid.native.js +471 -0
  395. package/dist/esm/report/ReportGrid.native.js.map +1 -0
  396. package/dist/esm/report/ReportViewToolbar.mjs +228 -0
  397. package/dist/esm/report/ReportViewToolbar.mjs.map +1 -0
  398. package/dist/esm/report/ReportViewToolbar.native.js +264 -0
  399. package/dist/esm/report/ReportViewToolbar.native.js.map +1 -0
  400. package/dist/esm/report/queryReport.mjs +404 -0
  401. package/dist/esm/report/queryReport.mjs.map +1 -0
  402. package/dist/esm/report/queryReport.native.js +545 -0
  403. package/dist/esm/report/queryReport.native.js.map +1 -0
  404. package/dist/esm/report/queryReportColumns.mjs +105 -0
  405. package/dist/esm/report/queryReportColumns.mjs.map +1 -0
  406. package/dist/esm/report/queryReportColumns.native.js +119 -0
  407. package/dist/esm/report/queryReportColumns.native.js.map +1 -0
  408. package/dist/esm/report/reportViewModel.mjs +343 -0
  409. package/dist/esm/report/reportViewModel.mjs.map +1 -0
  410. package/dist/esm/report/reportViewModel.native.js +611 -0
  411. package/dist/esm/report/reportViewModel.native.js.map +1 -0
  412. package/dist/esm/report/savedReports.mjs +112 -0
  413. package/dist/esm/report/savedReports.mjs.map +1 -0
  414. package/dist/esm/report/savedReports.native.js +141 -0
  415. package/dist/esm/report/savedReports.native.js.map +1 -0
  416. package/dist/esm/report/useFrappeReport.mjs +158 -0
  417. package/dist/esm/report/useFrappeReport.mjs.map +1 -0
  418. package/dist/esm/report/useFrappeReport.native.js +185 -0
  419. package/dist/esm/report/useFrappeReport.native.js.map +1 -0
  420. package/dist/esm/report/useQueryReport.mjs +176 -0
  421. package/dist/esm/report/useQueryReport.mjs.map +1 -0
  422. package/dist/esm/report/useQueryReport.native.js +205 -0
  423. package/dist/esm/report/useQueryReport.native.js.map +1 -0
  424. package/dist/esm/resolveControl.native.js.map +1 -1
  425. package/dist/esm/schemaForm/SchemaWizard.native.js.map +1 -1
  426. package/dist/esm/schemaForm/applyFieldOrder.native.js.map +1 -1
  427. package/dist/esm/schemaForm/index.native.js.map +1 -1
  428. package/dist/esm/shared/devWarn.native.js.map +1 -1
  429. package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
  430. package/dist/esm/syncError.native.js.map +1 -1
  431. package/dist/esm/useConnectionFilters.native.js.map +1 -1
  432. package/dist/esm/useFrappeAggregate.native.js.map +1 -1
  433. package/dist/esm/useFrappeFacets.native.js.map +1 -1
  434. package/dist/esm/useFrappeForm.mjs +533 -0
  435. package/dist/esm/useFrappeForm.mjs.map +1 -0
  436. package/dist/esm/useFrappeForm.native.js +686 -0
  437. package/dist/esm/useFrappeForm.native.js.map +1 -0
  438. package/dist/esm/useFrappePagination.native.js.map +1 -1
  439. package/dist/esm/useFrappeRows.native.js.map +1 -1
  440. package/dist/jsx/FileBrowser/index.mjs +20 -3
  441. package/dist/jsx/FileBrowser/index.mjs.map +1 -1
  442. package/dist/jsx/FileBrowser/index.native.js +20 -3
  443. package/dist/jsx/FileBrowser/index.native.js.map +1 -1
  444. package/dist/jsx/FrappeCalendar.mjs +4 -3
  445. package/dist/jsx/FrappeCalendar.mjs.map +1 -1
  446. package/dist/jsx/FrappeCalendar.native.js +3 -2
  447. package/dist/jsx/FrappeCalendar.native.js.map +1 -1
  448. package/dist/jsx/FrappeForm.mjs +151 -467
  449. package/dist/jsx/FrappeForm.mjs.map +1 -1
  450. package/dist/jsx/FrappeForm.native.js +152 -633
  451. package/dist/jsx/FrappeForm.native.js.map +1 -1
  452. package/dist/jsx/FrappeListView.mjs +6 -28
  453. package/dist/jsx/FrappeListView.mjs.map +1 -1
  454. package/dist/jsx/FrappeListView.native.js +11 -32
  455. package/dist/jsx/FrappeListView.native.js.map +1 -1
  456. package/dist/jsx/FrappeReportBuilder.mjs +526 -312
  457. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  458. package/dist/jsx/FrappeReportBuilder.native.js +658 -353
  459. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  460. package/dist/jsx/FrappeReportView.mjs +30 -229
  461. package/dist/jsx/FrappeReportView.mjs.map +1 -1
  462. package/dist/jsx/FrappeReportView.native.js +39 -283
  463. package/dist/jsx/FrappeReportView.native.js.map +1 -1
  464. package/dist/jsx/dependsOn.mjs +2 -2
  465. package/dist/jsx/dependsOn.mjs.map +1 -1
  466. package/dist/jsx/dependsOn.native.js +1 -2
  467. package/dist/jsx/dependsOn.native.js.map +1 -1
  468. package/dist/jsx/fields/shared/EditorPreviewPanes.mjs +2 -2
  469. package/dist/jsx/fields/shared/EditorPreviewPanes.mjs.map +1 -1
  470. package/dist/jsx/fields/shared/EditorPreviewPanes.native.js +2 -2
  471. package/dist/jsx/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  472. package/dist/jsx/formEngine/docPermissions.mjs +19 -1
  473. package/dist/jsx/formEngine/docPermissions.mjs.map +1 -1
  474. package/dist/jsx/formEngine/docPermissions.native.js +69 -0
  475. package/dist/jsx/formEngine/docPermissions.native.js.map +1 -1
  476. package/dist/jsx/formEngine/index.mjs +2 -2
  477. package/dist/jsx/formEngine/index.mjs.map +1 -1
  478. package/dist/jsx/formEngine/index.native.js +2 -0
  479. package/dist/jsx/formEngine/index.native.js.map +1 -1
  480. package/dist/jsx/index.js +16 -4
  481. package/dist/jsx/index.js.map +1 -1
  482. package/dist/jsx/index.mjs +16 -4
  483. package/dist/jsx/index.mjs.map +1 -1
  484. package/dist/jsx/index.native.js +67 -7
  485. package/dist/jsx/index.native.js.map +1 -1
  486. package/dist/jsx/liveErrors.mjs +8 -3
  487. package/dist/jsx/liveErrors.mjs.map +1 -1
  488. package/dist/jsx/liveErrors.native.js +8 -2
  489. package/dist/jsx/liveErrors.native.js.map +1 -1
  490. package/dist/jsx/measures.mjs +5 -0
  491. package/dist/jsx/measures.mjs.map +1 -0
  492. package/dist/jsx/measures.native.js +34 -0
  493. package/dist/jsx/measures.native.js.map +1 -0
  494. package/dist/jsx/recordShape.mjs +74 -0
  495. package/dist/jsx/recordShape.mjs.map +1 -0
  496. package/dist/jsx/recordShape.native.js +115 -0
  497. package/dist/jsx/recordShape.native.js.map +1 -0
  498. package/dist/jsx/report/ReportGrid.mjs +428 -0
  499. package/dist/jsx/report/ReportGrid.mjs.map +1 -0
  500. package/dist/jsx/report/ReportGrid.native.js +510 -0
  501. package/dist/jsx/report/ReportGrid.native.js.map +1 -0
  502. package/dist/jsx/report/ReportViewToolbar.mjs +228 -0
  503. package/dist/jsx/report/ReportViewToolbar.mjs.map +1 -0
  504. package/dist/jsx/report/ReportViewToolbar.native.js +303 -0
  505. package/dist/jsx/report/ReportViewToolbar.native.js.map +1 -0
  506. package/dist/jsx/report/queryReport.mjs +404 -0
  507. package/dist/jsx/report/queryReport.mjs.map +1 -0
  508. package/dist/jsx/report/queryReport.native.js +588 -0
  509. package/dist/jsx/report/queryReport.native.js.map +1 -0
  510. package/dist/jsx/report/queryReportColumns.mjs +105 -0
  511. package/dist/jsx/report/queryReportColumns.mjs.map +1 -0
  512. package/dist/jsx/report/queryReportColumns.native.js +159 -0
  513. package/dist/jsx/report/queryReportColumns.native.js.map +1 -0
  514. package/dist/jsx/report/reportViewModel.mjs +343 -0
  515. package/dist/jsx/report/reportViewModel.mjs.map +1 -0
  516. package/dist/jsx/report/reportViewModel.native.js +657 -0
  517. package/dist/jsx/report/reportViewModel.native.js.map +1 -0
  518. package/dist/jsx/report/savedReports.mjs +112 -0
  519. package/dist/jsx/report/savedReports.mjs.map +1 -0
  520. package/dist/jsx/report/savedReports.native.js +169 -0
  521. package/dist/jsx/report/savedReports.native.js.map +1 -0
  522. package/dist/jsx/report/useFrappeReport.mjs +158 -0
  523. package/dist/jsx/report/useFrappeReport.mjs.map +1 -0
  524. package/dist/jsx/report/useFrappeReport.native.js +214 -0
  525. package/dist/jsx/report/useFrappeReport.native.js.map +1 -0
  526. package/dist/jsx/report/useQueryReport.mjs +176 -0
  527. package/dist/jsx/report/useQueryReport.mjs.map +1 -0
  528. package/dist/jsx/report/useQueryReport.native.js +233 -0
  529. package/dist/jsx/report/useQueryReport.native.js.map +1 -0
  530. package/dist/jsx/useFrappeForm.mjs +533 -0
  531. package/dist/jsx/useFrappeForm.mjs.map +1 -0
  532. package/dist/jsx/useFrappeForm.native.js +714 -0
  533. package/dist/jsx/useFrappeForm.native.js.map +1 -0
  534. package/package.json +16 -16
  535. package/src/FileBrowser/FileBrowser.spec.tsx +21 -0
  536. package/src/FileBrowser/FileBrowser.stories.tsx +27 -0
  537. package/src/FileBrowser/index.tsx +25 -2
  538. package/src/FrappeCalendar.tsx +8 -2
  539. package/src/FrappeForm.stories.tsx +52 -0
  540. package/src/FrappeForm.tsx +176 -565
  541. package/src/FrappeListView.cards.stories.tsx +3 -6
  542. package/src/FrappeListView.tsx +15 -55
  543. package/src/FrappeReportBuilder.stories.tsx +34 -7
  544. package/src/FrappeReportBuilder.tsx +790 -380
  545. package/src/FrappeReportView.spec.tsx +10 -6
  546. package/src/FrappeReportView.stories.tsx +20 -1
  547. package/src/FrappeReportView.tsx +89 -415
  548. package/src/dependsOn.ts +4 -1
  549. package/src/fields/shared/EditorPreviewPanes.tsx +2 -2
  550. package/src/formEngine/docPermissions.spec.ts +36 -1
  551. package/src/formEngine/docPermissions.ts +34 -0
  552. package/src/formEngine/index.ts +8 -1
  553. package/src/frappeRemainder.designLaw.spec.ts +9 -1
  554. package/src/frappeRoutes.spec.tsx +9 -0
  555. package/src/frappeViews.designLaw.spec.ts +15 -2
  556. package/src/guestFallback.spec.tsx +236 -0
  557. package/src/index.ts +117 -16
  558. package/src/liveErrors.spec.ts +10 -0
  559. package/src/liveErrors.ts +16 -3
  560. package/src/measures.ts +11 -0
  561. package/src/recordShape.spec.ts +100 -0
  562. package/src/recordShape.ts +133 -0
  563. package/src/report/ReportGrid.spec.tsx +175 -0
  564. package/src/report/ReportGrid.tsx +530 -0
  565. package/src/report/ReportViewToolbar.spec.tsx +90 -0
  566. package/src/report/ReportViewToolbar.tsx +314 -0
  567. package/src/report/queryReport.spec.ts +483 -0
  568. package/src/report/queryReport.ts +722 -0
  569. package/src/report/queryReportColumns.tsx +123 -0
  570. package/src/report/reportViewModel.spec.ts +393 -0
  571. package/src/report/reportViewModel.ts +617 -0
  572. package/src/report/savedReports.ts +172 -0
  573. package/src/report/seam.spec.ts +216 -0
  574. package/src/report/useFrappeReport.ts +241 -0
  575. package/src/report/useQueryReport.spec.tsx +131 -0
  576. package/src/report/useQueryReport.ts +309 -0
  577. package/src/useFrappeForm.spec.tsx +209 -0
  578. package/src/useFrappeForm.ts +778 -0
  579. package/types/FileBrowser/index.d.ts.map +1 -1
  580. package/types/FrappeCalendar.d.ts.map +1 -1
  581. package/types/FrappeForm.d.ts +21 -1
  582. package/types/FrappeForm.d.ts.map +1 -1
  583. package/types/FrappeListView.d.ts.map +1 -1
  584. package/types/FrappeReportBuilder.d.ts +66 -16
  585. package/types/FrappeReportBuilder.d.ts.map +1 -1
  586. package/types/FrappeReportView.d.ts +9 -127
  587. package/types/FrappeReportView.d.ts.map +1 -1
  588. package/types/dependsOn.d.ts.map +1 -1
  589. package/types/formEngine/docPermissions.d.ts +14 -0
  590. package/types/formEngine/docPermissions.d.ts.map +1 -1
  591. package/types/formEngine/index.d.ts +1 -1
  592. package/types/formEngine/index.d.ts.map +1 -1
  593. package/types/index.d.ts +15 -3
  594. package/types/index.d.ts.map +1 -1
  595. package/types/liveErrors.d.ts +9 -1
  596. package/types/liveErrors.d.ts.map +1 -1
  597. package/types/measures.d.ts +3 -0
  598. package/types/measures.d.ts.map +1 -0
  599. package/types/recordShape.d.ts +45 -0
  600. package/types/recordShape.d.ts.map +1 -0
  601. package/types/report/ReportGrid.d.ts +20 -0
  602. package/types/report/ReportGrid.d.ts.map +1 -0
  603. package/types/report/ReportViewToolbar.d.ts +31 -0
  604. package/types/report/ReportViewToolbar.d.ts.map +1 -0
  605. package/types/report/queryReport.d.ts +181 -0
  606. package/types/report/queryReport.d.ts.map +1 -0
  607. package/types/report/queryReportColumns.d.ts +12 -0
  608. package/types/report/queryReportColumns.d.ts.map +1 -0
  609. package/types/report/reportViewModel.d.ts +146 -0
  610. package/types/report/reportViewModel.d.ts.map +1 -0
  611. package/types/report/savedReports.d.ts +27 -0
  612. package/types/report/savedReports.d.ts.map +1 -0
  613. package/types/report/useFrappeReport.d.ts +60 -0
  614. package/types/report/useFrappeReport.d.ts.map +1 -0
  615. package/types/report/useQueryReport.d.ts +37 -0
  616. package/types/report/useQueryReport.d.ts.map +1 -0
  617. package/types/useFrappeForm.d.ts +142 -0
  618. package/types/useFrappeForm.d.ts.map +1 -0
@@ -0,0 +1,722 @@
1
+ // The query/script report model: the one normalization of what
2
+ // frappe.desk.query_report.run and the Report doc send, shared by
3
+ // FrappeReportView and the desk's QueryReportScreen (MPO-15, GL-28).
4
+ // React-free; server messages decode through @multiplatform.one/frappe's one
5
+ // decoder, the same one HttpClient uses for every failed response.
6
+ //
7
+ // PROBED response shapes (bench v15 — reports "ToDo", "Permitted Documents
8
+ // For User", and the SQL query report "Backoffice QR Probe"):
9
+ // POST /api/method/frappe.desk.query_report.run {report_name, filters}
10
+ // → {message: {columns, result, message, chart, report_summary,
11
+ // add_total_row, skip_total_row, execution_time, status}}
12
+ // - columns: [{label, fieldname, fieldtype, width?, options?}] — width is
13
+ // a STRING ("90"), fieldtype may be "". v15 normalizes even old-style
14
+ // SQL alias columns ("Label:Fieldtype/Options:Width") into this dict
15
+ // shape server-side (get_column_as_dict); the string + positional-array
16
+ // row forms are still handled here (older benches, prepared payloads,
17
+ // the server-appended total row).
18
+ // - result: array of objects keyed by fieldname; values may embed HTML
19
+ // (e.g. desk anchor tags). The totals row is appended SERVER-side when
20
+ // add_total_row=1, so no client aggregation happens here.
21
+ // - errors: {exc_type, _server_messages} where _server_messages is a
22
+ // JSON-encoded array of JSON-encoded {message} — humanized below.
23
+
24
+ import { readServerMessages } from "@multiplatform.one/frappe";
25
+
26
+ export interface QueryReportColumn {
27
+ fieldname: string;
28
+ label: string;
29
+ /** Frappe fieldtype ("Link", "Date", "Currency", … or "" when untyped). */
30
+ fieldtype: string;
31
+ /** Link target doctype (fieldtype "Link"). */
32
+ options?: string;
33
+ /** Desk pixel width hint (server sends strings like "90"). */
34
+ width?: number;
35
+ /** Float/Currency decimal places, when the column declares them. */
36
+ precision?: number;
37
+ }
38
+
39
+ export type QueryReportRow = Record<string, unknown>;
40
+ export type QueryReportFilters = Record<string, unknown>;
41
+
42
+ /**
43
+ * One report filter's declaration — from the Report doc `filters` child
44
+ * table (Report Filter rows) or extracted from the desk-side script module
45
+ * (which spells mandatory as `reqd`; both normalize to `mandatory`).
46
+ */
47
+ export interface QueryReportFilterMeta {
48
+ fieldname: string;
49
+ label?: string;
50
+ fieldtype?: string;
51
+ options?: string;
52
+ /** Script modules declare numeric/boolean defaults; doc rows are strings. */
53
+ default?: string | number;
54
+ mandatory?: 0 | 1;
55
+ /** Desk wraps this filter's value in `%…%` before the run. */
56
+ wildcard_filter?: 0 | 1;
57
+ /** Applied (defaults included) but never rendered — desk parity. */
58
+ hidden?: 0 | 1;
59
+ /**
60
+ * Desk `read_only` — the control renders (so the value is honest) but
61
+ * cannot be edited. Locked filters must not open pickers (LC-21 family:
62
+ * a disabled control opens nothing).
63
+ */
64
+ read_only?: 0 | 1;
65
+ }
66
+
67
+ /** Report doc bits the screen cares about (loose — server owns the schema). */
68
+ export interface QueryReportMeta {
69
+ name: string;
70
+ report_name?: string;
71
+ ref_doctype?: string;
72
+ report_type?: string;
73
+ disabled?: 0 | 1;
74
+ prepared_report?: 0 | 1;
75
+ add_total_row?: 0 | 1;
76
+ filters?: QueryReportFilterMeta[];
77
+ [key: string]: unknown;
78
+ }
79
+
80
+ /** Static data for stories/tests — skips every bench RPC. */
81
+ export interface QueryReportFixture {
82
+ meta?: Partial<QueryReportMeta>;
83
+ /** Raw column shapes (dicts or "Label:Fieldtype/Options:Width" strings). */
84
+ columns: unknown[];
85
+ /** Raw rows (dicts or positional arrays). */
86
+ rows: unknown[];
87
+ message?: string;
88
+ /** Desk-side script module text (get_script response) for filter extraction. */
89
+ script?: string;
90
+ }
91
+
92
+ /**
93
+ * A report filter as a caller or the wire declares it (Report Filter rows,
94
+ * a `filterFields` prop, a fixture's `filters`): flags may be 0/1 or
95
+ * booleans, and a script module spells mandatory `reqd`.
96
+ * `normalizeFilterMeta` turns it into {@link QueryReportFilterMeta}.
97
+ */
98
+ export interface QueryReportFilterInput {
99
+ fieldname: string;
100
+ label?: string;
101
+ fieldtype?: string;
102
+ options?: string | string[];
103
+ default?: unknown;
104
+ mandatory?: number | boolean;
105
+ reqd?: number | boolean;
106
+ wildcard_filter?: number | boolean;
107
+ hidden?: number | boolean;
108
+ read_only?: number | boolean;
109
+ }
110
+
111
+ /** Raw `frappe.desk.query_report.run` response body (`message`). */
112
+ export interface QueryReportRunMessage {
113
+ columns?: unknown[];
114
+ result?: unknown[];
115
+ message?: string | string[] | null;
116
+ chart?: unknown;
117
+ report_summary?: unknown;
118
+ add_total_row?: number | boolean;
119
+ skip_total_row?: number | boolean;
120
+ execution_time?: number;
121
+ status?: string | null;
122
+ /**
123
+ * Fixture extension: filter declarations. The live endpoint does not send
124
+ * filters with `run`; fixtures may, so a fixture-backed view gets a filter
125
+ * bar without a second fixture surface.
126
+ */
127
+ filters?: QueryReportFilterInput[];
128
+ }
129
+
130
+ /** A normalized run: what a report table renders. */
131
+ export interface QueryReportPayload {
132
+ columns: QueryReportColumn[];
133
+ rows: QueryReportRow[];
134
+ /** Server-side report message (already user-facing). */
135
+ message?: string;
136
+ /** True when the last row is the server-computed total row. */
137
+ addTotalRow: boolean;
138
+ /** Fixture-provided filter declarations (see QueryReportRunMessage). */
139
+ filters?: QueryReportFilterInput[];
140
+ /** The untouched response, for chart / report_summary consumers. */
141
+ raw: QueryReportRunMessage;
142
+ }
143
+
144
+ /**
145
+ * The server's `frappe.scrub`: `txt.replace(" ", "_").replace("-", "_").lower()`.
146
+ * A label-only column gets its fieldname this way on the server
147
+ * (`get_column_as_dict`), and the rows are keyed by that fieldname, so the
148
+ * client has to produce the same string, parentheses and slashes included.
149
+ */
150
+ export function scrubFieldname(label: string): string {
151
+ return label.replace(/ /g, "_").replace(/-/g, "_").toLowerCase();
152
+ }
153
+
154
+ /** Best-effort HTML → text for report cell values and server messages. */
155
+ export function stripHtml(value: string): string {
156
+ if (!value.includes("<") && !value.includes("&")) return value;
157
+ return value
158
+ .replace(/<[^>]*>/g, "")
159
+ .replace(/&nbsp;/g, " ")
160
+ .replace(/&amp;/g, "&")
161
+ .replace(/&lt;/g, "<")
162
+ .replace(/&gt;/g, ">")
163
+ .replace(/&quot;/g, '"')
164
+ .replace(/&#39;/g, "'")
165
+ .replace(/\s+/g, " ")
166
+ .trim();
167
+ }
168
+
169
+ function parseWidth(raw: unknown): number | undefined {
170
+ if (typeof raw === "number") return raw > 0 ? raw : undefined;
171
+ if (typeof raw === "string" && raw) {
172
+ const parsed = Number.parseInt(raw, 10);
173
+ if (!Number.isNaN(parsed) && parsed > 0) return parsed;
174
+ }
175
+ return undefined;
176
+ }
177
+
178
+ function parsePrecision(raw: unknown): number | undefined {
179
+ const parsed = typeof raw === "string" && raw ? Number(raw) : raw;
180
+ return typeof parsed === "number" && Number.isInteger(parsed) && parsed >= 0 ? parsed : undefined;
181
+ }
182
+
183
+ /**
184
+ * Normalize run() columns: v15 sends dicts, older/custom reports may send
185
+ * "Label:Fieldtype/Options:Width" alias strings. Fieldnames are deduped so
186
+ * positional rows always land somewhere addressable.
187
+ */
188
+ export function normalizeQueryReportColumns(
189
+ raw: readonly unknown[] | undefined,
190
+ ): QueryReportColumn[] {
191
+ const used = new Set<string>();
192
+ const columns: QueryReportColumn[] = [];
193
+ (raw ?? []).forEach((entry, index) => {
194
+ let label = "";
195
+ let fieldname = "";
196
+ let fieldtype = "";
197
+ let options: string | undefined;
198
+ let width: number | undefined;
199
+ let precision: number | undefined;
200
+ if (typeof entry === "string") {
201
+ const [labelPart = "", typePart = "", widthPart = ""] = entry.split(":");
202
+ label = labelPart.trim();
203
+ const [typeBit = "", optionsBit = ""] = typePart.split("/");
204
+ fieldtype = typeBit.trim();
205
+ options = optionsBit.trim() || undefined;
206
+ width = parseWidth(widthPart.trim());
207
+ } else if (entry && typeof entry === "object") {
208
+ const column = entry as Record<string, unknown>;
209
+ label = typeof column.label === "string" ? column.label : "";
210
+ fieldname = typeof column.fieldname === "string" ? column.fieldname : "";
211
+ fieldtype = typeof column.fieldtype === "string" ? column.fieldtype : "";
212
+ options = typeof column.options === "string" && column.options ? column.options : undefined;
213
+ width = parseWidth(column.width);
214
+ precision = parsePrecision(column.precision);
215
+ } else {
216
+ return;
217
+ }
218
+ let id = fieldname || scrubFieldname(label) || `col_${index}`;
219
+ if (used.has(id)) id = `${id}_${index}`;
220
+ used.add(id);
221
+ columns.push({ fieldname: id, label: label || id, fieldtype, options, width, precision });
222
+ });
223
+ return columns;
224
+ }
225
+
226
+ /** Normalize run() rows: positional arrays are zipped onto column fieldnames. */
227
+ export function normalizeQueryReportRows(
228
+ raw: readonly unknown[] | undefined,
229
+ columns: readonly QueryReportColumn[],
230
+ ): QueryReportRow[] {
231
+ const rows: QueryReportRow[] = [];
232
+ for (const entry of raw ?? []) {
233
+ if (Array.isArray(entry)) {
234
+ const row: QueryReportRow = {};
235
+ columns.forEach((column, index) => {
236
+ row[column.fieldname] = entry[index];
237
+ });
238
+ rows.push(row);
239
+ } else if (entry && typeof entry === "object") {
240
+ rows.push(entry as QueryReportRow);
241
+ }
242
+ }
243
+ return rows;
244
+ }
245
+
246
+ /** Truthy check/flag coercion (accepts 1, "1", true — the wire variants). */
247
+ function coerceFlag(raw: unknown): 0 | 1 {
248
+ return raw === 1 || raw === "1" || raw === true ? 1 : 0;
249
+ }
250
+
251
+ /**
252
+ * One filter declaration record (a Report Filter doc row or a script-object
253
+ * extraction) → normalized meta. Script modules spell mandatory as `reqd`
254
+ * and may declare numeric/boolean defaults.
255
+ */
256
+ function coerceFilterMetaEntry(row: Record<string, unknown>): QueryReportFilterMeta | undefined {
257
+ const fieldname =
258
+ typeof row.fieldname === "string" && row.fieldname
259
+ ? row.fieldname
260
+ : typeof row.label === "string" && row.label
261
+ ? scrubFieldname(row.label)
262
+ : "";
263
+ if (!fieldname) return undefined;
264
+ let defaultValue: string | number | undefined;
265
+ if (typeof row.default === "string" && row.default !== "") defaultValue = row.default;
266
+ else if (typeof row.default === "number") defaultValue = row.default;
267
+ else if (typeof row.default === "boolean") defaultValue = row.default ? 1 : 0;
268
+ return {
269
+ fieldname,
270
+ label: typeof row.label === "string" ? row.label : undefined,
271
+ fieldtype: typeof row.fieldtype === "string" ? row.fieldtype : undefined,
272
+ options:
273
+ typeof row.options === "string"
274
+ ? row.options
275
+ : Array.isArray(row.options) && row.options.every((entry) => typeof entry === "string")
276
+ ? row.options.join("\n")
277
+ : undefined,
278
+ default: defaultValue,
279
+ mandatory: coerceFlag(row.mandatory) || coerceFlag(row.reqd) ? 1 : 0,
280
+ wildcard_filter: coerceFlag(row.wildcard_filter),
281
+ hidden: coerceFlag(row.hidden),
282
+ read_only: coerceFlag(row.read_only) || coerceFlag(row.readOnly) ? 1 : 0,
283
+ };
284
+ }
285
+
286
+ export function normalizeFilterMeta(raw: unknown): QueryReportFilterMeta[] {
287
+ if (!Array.isArray(raw)) return [];
288
+ const filters: QueryReportFilterMeta[] = [];
289
+ for (const entry of raw) {
290
+ if (!entry || typeof entry !== "object") continue;
291
+ const meta = coerceFilterMetaEntry(entry as Record<string, unknown>);
292
+ if (meta) filters.push(meta);
293
+ }
294
+ return filters;
295
+ }
296
+
297
+ export function isEmptyFilterValue(value: unknown): boolean {
298
+ return value === undefined || value === null || value === "";
299
+ }
300
+
301
+ /** Drop empty values so a cleared control never reaches the server. */
302
+ export function compactFilterValues(values: QueryReportFilters | undefined): QueryReportFilters {
303
+ const out: QueryReportFilters = {};
304
+ for (const [fieldname, value] of Object.entries(values ?? {})) {
305
+ if (!isEmptyFilterValue(value)) out[fieldname] = value;
306
+ }
307
+ return out;
308
+ }
309
+
310
+ /** A run response → the columns, rows and message a report table renders. */
311
+ export function normalizeQueryReportPayload(raw: QueryReportRunMessage): QueryReportPayload {
312
+ const columns = normalizeQueryReportColumns(raw.columns);
313
+ const rows = normalizeQueryReportRows(raw.result, columns);
314
+ const message = Array.isArray(raw.message)
315
+ ? raw.message.filter(Boolean).join(" ")
316
+ : (raw.message ?? undefined);
317
+ return {
318
+ columns,
319
+ rows,
320
+ message: message || undefined,
321
+ addTotalRow: Boolean(raw.add_total_row) && !raw.skip_total_row,
322
+ filters: raw.filters,
323
+ raw,
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Draft/applied values → the dict that round-trips through `?filters=` and
329
+ * `query_report.run`. Empty values drop; hidden filters keep their values
330
+ * so a clear-all on the visible bar does not strip seeded hidden defaults.
331
+ */
332
+ export function compactQueryReportFilters(
333
+ filterMeta: readonly QueryReportFilterMeta[],
334
+ values: QueryReportFilters,
335
+ ): QueryReportFilters {
336
+ const declared: QueryReportFilters = {};
337
+ for (const filter of filterMeta) declared[filter.fieldname] = values[filter.fieldname];
338
+ return compactFilterValues(declared);
339
+ }
340
+
341
+ /** Seedable default values ("" defaults are non-values, desk parity). */
342
+ export function defaultFilterValues(
343
+ filterMeta: readonly QueryReportFilterMeta[],
344
+ ): QueryReportFilters {
345
+ const defaults: QueryReportFilters = {};
346
+ for (const filter of filterMeta) {
347
+ if (filter.default !== undefined && filter.default !== "")
348
+ defaults[filter.fieldname] = filter.default;
349
+ }
350
+ return defaults;
351
+ }
352
+
353
+ /**
354
+ * Filter values → the `filters` dict for frappe.desk.query_report.run.
355
+ * Desk parity (query_report.js get_filter_values): falsy values are OMITTED
356
+ * (an unchecked Check or empty input sends nothing), `wildcard_filter`
357
+ * values wrap in `%…%` unless the user typed their own wildcard, and
358
+ * numeric fieldtypes send numbers (script reports do arithmetic on them).
359
+ */
360
+ export function buildRunFilters(
361
+ filterMeta: readonly QueryReportFilterMeta[],
362
+ filters: QueryReportFilters,
363
+ ): QueryReportFilters {
364
+ const metaByField = new Map(filterMeta.map((filter) => [filter.fieldname, filter]));
365
+ const out: QueryReportFilters = {};
366
+ for (const [fieldname, rawValue] of Object.entries(filters)) {
367
+ let value: unknown = rawValue === true ? 1 : rawValue;
368
+ if (isEmptyFilterValue(value) || value === false || value === 0) continue;
369
+ const meta = metaByField.get(fieldname);
370
+ if (meta?.wildcard_filter === 1 && typeof value === "string" && !value.includes("%"))
371
+ value = `%${value}%`;
372
+ if (
373
+ meta?.fieldtype !== undefined &&
374
+ NUMERIC_FILTER_FIELDTYPES.has(meta.fieldtype) &&
375
+ typeof value === "string" &&
376
+ value.trim() !== "" &&
377
+ Number.isFinite(Number(value))
378
+ )
379
+ value = Number(value);
380
+ out[fieldname] = value;
381
+ }
382
+ return out;
383
+ }
384
+
385
+ // ── Script-declared filters (desk-side report JS modules) ───────
386
+ //
387
+ // Standard reports declare filters in their desk JS module, reachable only
388
+ // as raw text via frappe.desk.query_report.get_script:
389
+ // frappe.query_reports["<name>"] = { filters: [{fieldname, label: __("…"),
390
+ // fieldtype, options, reqd, default, get_query() {…}}, …] }
391
+ // The declarative subset (string/number/boolean values, __() labels, string
392
+ // arrays) is extracted WITHOUT eval by a small string/comment-aware scanner;
393
+ // function-valued keys (get_query, on_change, formatters) are skipped.
394
+ // Entries that don't yield a renderable control count toward `declaredCount`
395
+ // so the surface can render an honest "defined in code" gap note.
396
+
397
+ export interface ScriptFilterExtraction {
398
+ /** True when the module declares a `filters` key (even an empty one). */
399
+ declared: boolean;
400
+ /** Top-level entries the script declares (parseable or not). */
401
+ declaredCount: number;
402
+ /** The renderable (declarative) subset, normalized. */
403
+ filters: QueryReportFilterMeta[];
404
+ }
405
+
406
+ const EMPTY_EXTRACTION: ScriptFilterExtraction = { declared: false, declaredCount: 0, filters: [] };
407
+
408
+ /** Filter fieldtypes the surface can render (desk-only ones are gaps). */
409
+ const RENDERABLE_FILTER_FIELDTYPES = new Set([
410
+ "Data",
411
+ "Small Text",
412
+ "Text",
413
+ "Int",
414
+ "Float",
415
+ "Currency",
416
+ "Percent",
417
+ "Date",
418
+ "Datetime",
419
+ "Time",
420
+ "Check",
421
+ "Select",
422
+ "Link",
423
+ ]);
424
+
425
+ const NUMERIC_FILTER_FIELDTYPES = new Set(["Int", "Float", "Currency", "Percent"]);
426
+
427
+ /** Index AFTER the string literal opening at `start` (escape-aware). */
428
+ function scanStringEnd(text: string, start: number): number {
429
+ const quote = text[start];
430
+ let index = start + 1;
431
+ while (index < text.length) {
432
+ const ch = text[index];
433
+ if (ch === "\\") {
434
+ index += 2;
435
+ continue;
436
+ }
437
+ if (ch === quote) return index + 1;
438
+ index += 1;
439
+ }
440
+ return index;
441
+ }
442
+
443
+ /** Index after a line or block comment opening at `start` (start+1 for a bare slash). */
444
+ function scanCommentEnd(text: string, start: number): number {
445
+ const next = text[start + 1];
446
+ if (next === "/") {
447
+ const newline = text.indexOf("\n", start);
448
+ return newline === -1 ? text.length : newline + 1;
449
+ }
450
+ if (next === "*") {
451
+ const end = text.indexOf("*/", start + 2);
452
+ return end === -1 ? text.length : end + 2;
453
+ }
454
+ return start + 1;
455
+ }
456
+
457
+ /** Matching close-bracket index for the opener at `open` (-1 when unbalanced). */
458
+ function matchBracket(text: string, open: number): number {
459
+ const openCh = text[open];
460
+ const closeCh = openCh === "[" ? "]" : openCh === "{" ? "}" : openCh === "(" ? ")" : "";
461
+ if (!closeCh) return -1;
462
+ let depth = 0;
463
+ let index = open;
464
+ while (index < text.length) {
465
+ const ch = text[index];
466
+ if (ch === "'" || ch === '"' || ch === "`") {
467
+ index = scanStringEnd(text, index);
468
+ continue;
469
+ }
470
+ if (ch === "/") {
471
+ index = scanCommentEnd(text, index);
472
+ continue;
473
+ }
474
+ if (ch === openCh) depth += 1;
475
+ else if (ch === closeCh) {
476
+ depth -= 1;
477
+ if (depth === 0) return index;
478
+ }
479
+ index += 1;
480
+ }
481
+ return -1;
482
+ }
483
+
484
+ /** Unescape the common sequences inside a scanned string literal body. */
485
+ function unescapeStringBody(body: string): string {
486
+ return body.replace(/\\(.)/g, (_, ch: string) =>
487
+ ch === "n" ? "\n" : ch === "t" ? "\t" : ch === "r" ? "\r" : ch,
488
+ );
489
+ }
490
+
491
+ /**
492
+ * Interpret one raw value slice from a script object literal. Returns
493
+ * undefined for anything non-declarative (functions, frappe.* expressions,
494
+ * template strings with interpolations, ternaries…).
495
+ */
496
+ function interpretScriptValue(raw: string): string | number | boolean | string[] | undefined {
497
+ const value = raw.trim();
498
+ if (!value) return undefined;
499
+ const first = value[0];
500
+ if (first === "'" || first === '"' || first === "`") {
501
+ const end = scanStringEnd(value, 0);
502
+ if (end !== value.length) return undefined;
503
+ const body = value.slice(1, -1);
504
+ if (first === "`" && body.includes("${")) return undefined;
505
+ return unescapeStringBody(body);
506
+ }
507
+ if (/^__\s*\(/.test(value)) {
508
+ // Translation call — the first string argument is the label.
509
+ const parenIndex = value.indexOf("(");
510
+ const rest = value.slice(parenIndex + 1).trim();
511
+ const quote = rest[0];
512
+ if (quote !== "'" && quote !== '"' && quote !== "`") return undefined;
513
+ const quoteIndex = value.indexOf(quote, parenIndex);
514
+ const end = scanStringEnd(value, quoteIndex);
515
+ return unescapeStringBody(value.slice(quoteIndex + 1, end - 1));
516
+ }
517
+ if (/^-?\d+(\.\d+)?$/.test(value)) return Number(value);
518
+ if (value === "true") return true;
519
+ if (value === "false") return false;
520
+ if (first === "[") {
521
+ const close = matchBracket(value, 0);
522
+ if (close !== value.length - 1) return undefined;
523
+ const entries: string[] = [];
524
+ let index = 1;
525
+ while (index < close) {
526
+ const ch = value[index];
527
+ if (ch === "'" || ch === '"' || ch === "`") {
528
+ const end = scanStringEnd(value, index);
529
+ const body = value.slice(index + 1, end - 1);
530
+ if (ch === "`" && body.includes("${")) return undefined;
531
+ entries.push(unescapeStringBody(body));
532
+ index = end;
533
+ continue;
534
+ }
535
+ if (ch === "/" && (value[index + 1] === "/" || value[index + 1] === "*")) {
536
+ index = scanCommentEnd(value, index);
537
+ continue;
538
+ }
539
+ if (ch === "," || ch === " " || ch === "\t" || ch === "\n" || ch === "\r") {
540
+ index += 1;
541
+ continue;
542
+ }
543
+ return undefined; // non-string entry (objects, expressions) — not declarative
544
+ }
545
+ return entries;
546
+ }
547
+ return undefined;
548
+ }
549
+
550
+ /** Parse one `{…}` object literal into declarative key/value pairs. */
551
+ function parseScriptObject(source: string): Record<string, unknown> {
552
+ const record: Record<string, unknown> = {};
553
+ let index = 1; // past the opening brace
554
+ const end = source.length - 1; // before the closing brace
555
+ while (index < end) {
556
+ const ch = source[index];
557
+ if (ch === "/" && (source[index + 1] === "/" || source[index + 1] === "*")) {
558
+ index = scanCommentEnd(source, index);
559
+ continue;
560
+ }
561
+ if (/\s|,/.test(ch)) {
562
+ index += 1;
563
+ continue;
564
+ }
565
+ // Key: identifier or quoted string.
566
+ let key = "";
567
+ if (ch === "'" || ch === '"') {
568
+ const keyEnd = scanStringEnd(source, index);
569
+ key = source.slice(index + 1, keyEnd - 1);
570
+ index = keyEnd;
571
+ } else {
572
+ const keyMatch = source.slice(index, index + 64).match(/^[A-Za-z_$][\w$]*/);
573
+ if (!keyMatch) break; // not an object key — bail out of this entry
574
+ key = keyMatch[0];
575
+ index += key.length;
576
+ }
577
+ while (index < end && /\s/.test(source[index])) index += 1;
578
+ if (source[index] !== ":") break; // shorthand/method — not declarative
579
+ index += 1;
580
+ // Value: scan to the next top-level comma, collecting comment-free text.
581
+ let valueRaw = "";
582
+ while (index < end) {
583
+ const valueCh = source[index];
584
+ if (valueCh === "'" || valueCh === '"' || valueCh === "`") {
585
+ const stringEnd = scanStringEnd(source, index);
586
+ valueRaw += source.slice(index, stringEnd);
587
+ index = stringEnd;
588
+ continue;
589
+ }
590
+ if (valueCh === "/" && (source[index + 1] === "/" || source[index + 1] === "*")) {
591
+ index = scanCommentEnd(source, index);
592
+ continue;
593
+ }
594
+ if (valueCh === "{" || valueCh === "[" || valueCh === "(") {
595
+ const close = matchBracket(source, index);
596
+ if (close === -1) return record; // unbalanced — stop parsing
597
+ valueRaw += source.slice(index, close + 1);
598
+ index = close + 1;
599
+ continue;
600
+ }
601
+ if (valueCh === ",") {
602
+ index += 1;
603
+ break;
604
+ }
605
+ valueRaw += valueCh;
606
+ index += 1;
607
+ }
608
+ const interpreted = interpretScriptValue(valueRaw);
609
+ if (interpreted !== undefined) record[key] = interpreted;
610
+ }
611
+ return record;
612
+ }
613
+
614
+ /**
615
+ * Extract the declarative filter subset from a desk report script module.
616
+ * Never throws; anything unparseable degrades to a smaller `filters` list
617
+ * (the `declaredCount` delta is the honest gap).
618
+ */
619
+ export function extractScriptFilters(script: string | undefined): ScriptFilterExtraction {
620
+ if (!script) return EMPTY_EXTRACTION;
621
+ const keyMatch = script.match(/\bfilters\s*:\s*\[/);
622
+ if (!keyMatch || keyMatch.index === undefined) return EMPTY_EXTRACTION;
623
+ const openBracket = keyMatch.index + keyMatch[0].length - 1;
624
+ const closeBracket = matchBracket(script, openBracket);
625
+ if (closeBracket === -1) return EMPTY_EXTRACTION;
626
+ const filters: QueryReportFilterMeta[] = [];
627
+ let declaredCount = 0;
628
+ let index = openBracket + 1;
629
+ while (index < closeBracket) {
630
+ const ch = script[index];
631
+ if (ch === "{") {
632
+ const close = matchBracket(script, index);
633
+ if (close === -1 || close > closeBracket) break;
634
+ declaredCount += 1;
635
+ const record = parseScriptObject(script.slice(index, close + 1));
636
+ const meta = coerceFilterMetaEntry(record);
637
+ const fieldtype = meta?.fieldtype ?? "Data";
638
+ const needsOptions = fieldtype === "Select" || fieldtype === "Link";
639
+ if (
640
+ meta &&
641
+ RENDERABLE_FILTER_FIELDTYPES.has(fieldtype) &&
642
+ (!needsOptions || (meta.options ?? "") !== "")
643
+ )
644
+ filters.push({ ...meta, fieldtype });
645
+ index = close + 1;
646
+ continue;
647
+ }
648
+ if (ch === "'" || ch === '"' || ch === "`") {
649
+ index = scanStringEnd(script, index);
650
+ continue;
651
+ }
652
+ if (ch === "/" && (script[index + 1] === "/" || script[index + 1] === "*")) {
653
+ index = scanCommentEnd(script, index);
654
+ continue;
655
+ }
656
+ index += 1;
657
+ }
658
+ return { declared: true, declaredCount, filters };
659
+ }
660
+
661
+ /** `_server_messages` as one line per message, block and `<br>` (MPO-473). */
662
+ function decodeServerMessages(raw: unknown): string | undefined {
663
+ if (typeof raw !== "string" || !raw.startsWith("[")) return undefined;
664
+ const lines = readServerMessages(raw);
665
+ return lines.length > 0 ? lines.join("\n") : undefined;
666
+ }
667
+
668
+ /**
669
+ * A failed report call → an Error whose message is the server's own sentence.
670
+ * The HTTP `status` and frappe `exc_type` ride along, so a caller can still
671
+ * tell a refused run (403 / PermissionError) from a broken one.
672
+ */
673
+ export function humanizeFrappeError(err: unknown): Error {
674
+ if (err instanceof Error) {
675
+ const source = err as Error & { data?: unknown; status?: unknown; exc_type?: unknown };
676
+ const data = source.data as Record<string, unknown> | undefined;
677
+ const decoded =
678
+ decodeServerMessages(data?._server_messages) ?? decodeServerMessages(err.message);
679
+ if (!decoded) return err;
680
+ const humanized = new Error(decoded) as Error & Record<string, unknown>;
681
+ if (source.status !== undefined) humanized.status = source.status;
682
+ const excType = source.exc_type ?? data?.exc_type;
683
+ if (excType !== undefined) humanized.exc_type = excType;
684
+ if (source.data !== undefined) humanized.data = source.data;
685
+ if (err.stack) humanized.stack = err.stack;
686
+ return humanized;
687
+ }
688
+ return new Error(String(err));
689
+ }
690
+
691
+ // ── FrappeReportView's names for the same model ────────────────
692
+ // FrappeReportView shipped these names before the model was one. They stay
693
+ // on the barrel as aliases so existing imports keep compiling; none of them
694
+ // is a second implementation.
695
+
696
+ export type FrappeReportColumn = QueryReportColumn;
697
+ export type FrappeReportRow = QueryReportRow;
698
+ export type FrappeReportValues = QueryReportFilters;
699
+ export type FrappeReportFilterDef = QueryReportFilterInput;
700
+ export type FrappeReportRunResponse = QueryReportRunMessage;
701
+ export type FrappeReportPayload = QueryReportPayload;
702
+
703
+ export const normalizeReportPayload = normalizeQueryReportPayload;
704
+
705
+ /** One column, dict or `"Label:Fieldtype/Options:Width"`, in its normalized shape. */
706
+ export function normalizeReportColumn(column: unknown): QueryReportColumn {
707
+ return (
708
+ normalizeQueryReportColumns([column])[0] ?? {
709
+ fieldname: "col_0",
710
+ label: "col_0",
711
+ fieldtype: "",
712
+ }
713
+ );
714
+ }
715
+
716
+ /** `normalizeQueryReportRows` with FrappeReportView's argument order. */
717
+ export function normalizeReportRows(
718
+ columns: readonly QueryReportColumn[],
719
+ result: readonly unknown[] | undefined,
720
+ ): QueryReportRow[] {
721
+ return normalizeQueryReportRows(result, columns);
722
+ }