@svadmin/ui 0.72.0 → 0.74.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 (276) hide show
  1. package/README.md +62 -22
  2. package/THIRD_PARTY_NOTICES.md +52 -0
  3. package/dist/app.css +8488 -6297
  4. package/dist/app.theme.css +8514 -6374
  5. package/dist/class-properties.generated.d.ts +1 -0
  6. package/dist/class-properties.generated.js +2 -0
  7. package/dist/classnames.d.ts +8 -0
  8. package/dist/classnames.js +26 -0
  9. package/dist/component-registry.d.ts +14977 -0
  10. package/dist/component-registry.js +216 -0
  11. package/dist/components/AboutSettings.svelte +7 -1
  12. package/dist/components/AboutSettings.svelte.d.ts +4 -1
  13. package/dist/components/ActivityFeed.svelte +9 -3
  14. package/dist/components/ActivityFeed.svelte.d.ts +3 -0
  15. package/dist/components/AdminApp.svelte +19 -10
  16. package/dist/components/AdminApp.svelte.d.ts +6 -0
  17. package/dist/components/ApiSettings.svelte +41 -5
  18. package/dist/components/ApprovalCenter.svelte +283 -0
  19. package/dist/components/ApprovalCenter.svelte.d.ts +10 -0
  20. package/dist/components/AuditLogViewer.svelte +3 -1
  21. package/dist/components/AutoForm.svelte +53 -9
  22. package/dist/components/AutoForm.svelte.d.ts +3 -0
  23. package/dist/components/AutoTable.svelte +846 -43
  24. package/dist/components/AutoTable.svelte.d.ts +22 -1
  25. package/dist/components/BoundRecordDetailDrawer.svelte +17 -2
  26. package/dist/components/BoundRecordDetailDrawer.svelte.d.ts +4 -0
  27. package/dist/components/Breadcrumbs.svelte +11 -1
  28. package/dist/components/CancelTaskButton.svelte +12 -42
  29. package/dist/components/ColorPicker.svelte +73 -0
  30. package/dist/components/ColorPicker.svelte.d.ts +15 -0
  31. package/dist/components/ComboboxField.svelte +143 -34
  32. package/dist/components/ComboboxField.svelte.d.ts +4 -2
  33. package/dist/components/CreatePage.svelte +4 -0
  34. package/dist/components/CreatePage.svelte.d.ts +2 -0
  35. package/dist/components/DashboardView.svelte +99 -0
  36. package/dist/components/DashboardView.svelte.d.ts +14 -0
  37. package/dist/components/DatePicker.svelte +10 -0
  38. package/dist/components/DatePicker.svelte.d.ts +6 -0
  39. package/dist/components/DateRangeInput.svelte +155 -0
  40. package/dist/components/DateRangeInput.svelte.d.ts +35 -0
  41. package/dist/components/DateRangePicker.svelte +10 -0
  42. package/dist/components/DateRangePicker.svelte.d.ts +6 -0
  43. package/dist/components/DateTimeInput.svelte +134 -0
  44. package/dist/components/DateTimeInput.svelte.d.ts +27 -0
  45. package/dist/components/DateTimePicker.svelte +10 -0
  46. package/dist/components/DateTimePicker.svelte.d.ts +6 -0
  47. package/dist/components/DevTools.svelte +36 -28
  48. package/dist/components/DevframePanel.svelte +123 -0
  49. package/dist/components/DevframePanel.svelte.d.ts +3 -0
  50. package/dist/components/EditPage.svelte +4 -0
  51. package/dist/components/EditPage.svelte.d.ts +2 -0
  52. package/dist/components/ErrorSummary.svelte +52 -0
  53. package/dist/components/ErrorSummary.svelte.d.ts +14 -0
  54. package/dist/components/FieldRenderer.svelte +172 -99
  55. package/dist/components/FileUpload.svelte +412 -0
  56. package/dist/components/FileUpload.svelte.d.ts +43 -0
  57. package/dist/components/FilterBuilder.svelte +244 -265
  58. package/dist/components/FilterBuilder.svelte.d.ts +3 -0
  59. package/dist/components/FilterCollectionInput.svelte +80 -0
  60. package/dist/components/FilterCollectionInput.svelte.d.ts +10 -0
  61. package/dist/components/GanttChart.svelte +66 -14
  62. package/dist/components/GanttChart.svelte.d.ts +6 -0
  63. package/dist/components/Header.svelte +18 -2
  64. package/dist/components/ImportWizard.svelte +509 -100
  65. package/dist/components/ImportWizard.svelte.d.ts +11 -0
  66. package/dist/components/JsonSchemaForm.svelte +322 -98
  67. package/dist/components/JsonSchemaForm.svelte.d.ts +18 -1
  68. package/dist/components/KanbanBoard.svelte +195 -40
  69. package/dist/components/KanbanBoard.svelte.d.ts +9 -2
  70. package/dist/components/Layout.svelte +4 -3
  71. package/dist/components/LazyAutoForm.svelte +28 -0
  72. package/dist/components/LazyAutoForm.svelte.d.ts +8 -0
  73. package/dist/components/LazyAutoTable.svelte +28 -0
  74. package/dist/components/LazyAutoTable.svelte.d.ts +8 -0
  75. package/dist/components/LazySettingsPage.svelte +28 -0
  76. package/dist/components/LazySettingsPage.svelte.d.ts +8 -0
  77. package/dist/components/LazyShowPage.svelte +28 -0
  78. package/dist/components/LazyShowPage.svelte.d.ts +8 -0
  79. package/dist/components/LazyTaskQueueDrawer.svelte.d.ts +1 -1
  80. package/dist/components/ListPage.svelte +9 -1
  81. package/dist/components/ListPage.svelte.d.ts +5 -0
  82. package/dist/components/LoginPage.svelte +2 -2
  83. package/dist/components/MoneyInput.svelte +25 -0
  84. package/dist/components/MoneyInput.svelte.d.ts +20 -0
  85. package/dist/components/MultiTabKeepAlive.svelte +11 -6
  86. package/dist/components/NotificationsSettings.svelte +69 -2
  87. package/dist/components/NotificationsSettings.svelte.d.ts +25 -1
  88. package/dist/components/NumberInput.svelte +25 -0
  89. package/dist/components/NumberInput.svelte.d.ts +19 -0
  90. package/dist/components/NumericInput.svelte +110 -0
  91. package/dist/components/NumericInput.svelte.d.ts +23 -0
  92. package/dist/components/PercentInput.svelte +25 -0
  93. package/dist/components/PercentInput.svelte.d.ts +20 -0
  94. package/dist/components/PermissionMatrix.svelte +20 -1
  95. package/dist/components/PivotExportButton.svelte +157 -0
  96. package/dist/components/PivotExportButton.svelte.d.ts +16 -0
  97. package/dist/components/PivotTable.svelte +229 -74
  98. package/dist/components/PivotTable.svelte.d.ts +19 -2
  99. package/dist/components/QuickEditDrawer.svelte +4 -1
  100. package/dist/components/QuickEditDrawer.svelte.d.ts +2 -0
  101. package/dist/components/RadioGroup.svelte +121 -0
  102. package/dist/components/RadioGroup.svelte.d.ts +43 -0
  103. package/dist/components/RangeSlider.svelte +127 -0
  104. package/dist/components/RangeSlider.svelte.d.ts +22 -0
  105. package/dist/components/Rate.svelte +121 -0
  106. package/dist/components/Rate.svelte.d.ts +16 -0
  107. package/dist/components/RecordDetailDrawer.svelte +6 -2
  108. package/dist/components/RecordDetailDrawer.svelte.d.ts +4 -0
  109. package/dist/components/RelationPicker.svelte +341 -0
  110. package/dist/components/RelationPicker.svelte.d.ts +26 -0
  111. package/dist/components/ResourceOperationsPage.svelte +25 -19
  112. package/dist/components/ResourceOperationsPage.svelte.d.ts +5 -1
  113. package/dist/components/RetryTaskButton.svelte +12 -42
  114. package/dist/components/SecuritySettings.svelte +29 -5
  115. package/dist/components/SegmentedControl.svelte +145 -0
  116. package/dist/components/SegmentedControl.svelte.d.ts +38 -0
  117. package/dist/components/SettingsPage.svelte +3 -1
  118. package/dist/components/SettingsPage.svelte.d.ts +1 -0
  119. package/dist/components/ShowInferencer.svelte +4 -2
  120. package/dist/components/ShowInferencer.svelte.d.ts +2 -0
  121. package/dist/components/ShowPage.svelte +25 -6
  122. package/dist/components/ShowPage.svelte.d.ts +5 -0
  123. package/dist/components/Sidebar.svelte +5 -5
  124. package/dist/components/Slider.svelte +100 -0
  125. package/dist/components/Slider.svelte.d.ts +19 -0
  126. package/dist/components/SpreadsheetView.svelte +1037 -124
  127. package/dist/components/SpreadsheetView.svelte.d.ts +19 -0
  128. package/dist/components/StepsForm.svelte +5 -5
  129. package/dist/components/SvarAutoTable.svelte +39 -0
  130. package/dist/components/SvarAutoTable.svelte.d.ts +13 -0
  131. package/dist/components/SvarDataGrid.svelte +362 -0
  132. package/dist/components/SvarDataGrid.svelte.d.ts +57 -0
  133. package/dist/components/SvarGridCell.svelte +10 -0
  134. package/dist/components/SvarGridCell.svelte.d.ts +7 -0
  135. package/dist/components/SvarResourceRead.svelte +50 -0
  136. package/dist/components/SvarResourceRead.svelte.d.ts +23 -0
  137. package/dist/components/SvarResourceTable.svelte +63 -0
  138. package/dist/components/SvarResourceTable.svelte.d.ts +42 -0
  139. package/dist/components/SvarResourceTableView.svelte +364 -0
  140. package/dist/components/SvarResourceTableView.svelte.d.ts +4 -0
  141. package/dist/components/TagsInput.svelte +178 -0
  142. package/dist/components/TagsInput.svelte.d.ts +17 -0
  143. package/dist/components/TaskQueueDrawer.svelte +72 -16
  144. package/dist/components/TimePicker.svelte +10 -0
  145. package/dist/components/TimePicker.svelte.d.ts +6 -0
  146. package/dist/components/TreeSelect.svelte +440 -46
  147. package/dist/components/TreeSelect.svelte.d.ts +6 -1
  148. package/dist/components/TreeTable.svelte +484 -82
  149. package/dist/components/TreeTable.svelte.d.ts +24 -1
  150. package/dist/components/TwoFactorAuthPage.svelte +85 -48
  151. package/dist/components/TwoFactorAuthPage.svelte.d.ts +12 -1
  152. package/dist/components/VirtualTable.svelte +116 -20
  153. package/dist/components/VirtualTable.svelte.d.ts +5 -0
  154. package/dist/components/account/CompanyProfilePage.svelte +74 -38
  155. package/dist/components/account/GetStartedPage.svelte +2 -1
  156. package/dist/components/account/ImportMembersPage.svelte +22 -167
  157. package/dist/components/account/ImportMembersPage.svelte.d.ts +4 -1
  158. package/dist/components/account/MemberDirectory.svelte +156 -0
  159. package/dist/components/account/MemberDirectory.svelte.d.ts +19 -0
  160. package/dist/components/account/MembersStarterPage.svelte +9 -55
  161. package/dist/components/account/MembersStarterPage.svelte.d.ts +5 -1
  162. package/dist/components/account/SecurityLogPage.svelte +4 -1
  163. package/dist/components/account/SettingsPlainPage.svelte +7 -38
  164. package/dist/components/account/SettingsPlainPage.svelte.d.ts +4 -1
  165. package/dist/components/account/SettingsSidebarPage.svelte +7 -20
  166. package/dist/components/account/TeamMembersPage.svelte +4 -20
  167. package/dist/components/account/TeamMembersPage.svelte.d.ts +5 -1
  168. package/dist/components/account/UserProfilePage.svelte +3 -25
  169. package/dist/components/account/UserProfilePage.svelte.d.ts +17 -2
  170. package/dist/components/auto-table-grid.d.ts +26 -0
  171. package/dist/components/auto-table-grid.js +1 -0
  172. package/dist/components/buttons/ExportButton.svelte +56 -12
  173. package/dist/components/buttons/ExportButton.svelte.d.ts +11 -0
  174. package/dist/components/content/ContentPageHeader.svelte +12 -9
  175. package/dist/components/content/ContentPageShell.svelte +6 -9
  176. package/dist/components/content/FileBrowser.svelte +35 -0
  177. package/dist/components/content/FileBrowser.svelte.d.ts +14 -0
  178. package/dist/components/content/MetricBlock.svelte +10 -13
  179. package/dist/components/content/NetworkTable.svelte +3 -3
  180. package/dist/components/content/NetworkTable.svelte.d.ts +1 -0
  181. package/dist/components/content/PageToolbar.svelte +6 -10
  182. package/dist/components/content/ReferenceNotice.svelte +5 -0
  183. package/dist/components/content/ReferenceNotice.svelte.d.ts +18 -0
  184. package/dist/components/content/SectionHeader.svelte +8 -13
  185. package/dist/components/content/SettingsFieldRow.svelte +9 -23
  186. package/dist/components/content/SettingsGroup.svelte +11 -27
  187. package/dist/components/content/StatusBadge.svelte +3 -8
  188. package/dist/components/content/WorkspaceLayout.svelte +8 -12
  189. package/dist/components/enterprise/filter-tree.d.ts +48 -0
  190. package/dist/components/enterprise/filter-tree.js +224 -0
  191. package/dist/components/enterprise/json-schema-form.d.ts +39 -0
  192. package/dist/components/enterprise/json-schema-form.js +195 -0
  193. package/dist/components/enterprise/recursive-schema-form.d.ts +30 -0
  194. package/dist/components/enterprise/recursive-schema-form.js +196 -0
  195. package/dist/components/enterprise/spreadsheet-formula.d.ts +12 -0
  196. package/dist/components/enterprise/spreadsheet-formula.js +245 -0
  197. package/dist/components/export-reference.d.ts +2 -0
  198. package/dist/components/export-reference.js +9 -0
  199. package/dist/components/fieldComponentMap.js +2 -0
  200. package/dist/components/fields/DateField.svelte +12 -12
  201. package/dist/components/fields/date-display.d.ts +6 -0
  202. package/dist/components/fields/date-display.js +24 -0
  203. package/dist/components/fields/date-field-value.d.ts +2 -0
  204. package/dist/components/fields/date-field-value.js +13 -0
  205. package/dist/components/json-schema-form-state.d.ts +37 -0
  206. package/dist/components/json-schema-form-state.js +168 -0
  207. package/dist/components/network/TeamCrewTablePage.svelte +6 -1
  208. package/dist/components/network/UserCardsNFTPage.svelte +2 -0
  209. package/dist/components/profile/PublicProfilePage.svelte +2 -0
  210. package/dist/components/record-detail.svelte.d.ts +3 -0
  211. package/dist/components/record-detail.svelte.js +10 -4
  212. package/dist/components/saved-list-views.d.ts +74 -1
  213. package/dist/components/saved-list-views.js +191 -3
  214. package/dist/components/svar-grid-cells.d.ts +14 -0
  215. package/dist/components/svar-grid-cells.js +2 -0
  216. package/dist/components/svar-grid-contract.d.ts +80 -0
  217. package/dist/components/svar-grid-contract.js +159 -0
  218. package/dist/components/svar-grid-interactions.d.ts +54 -0
  219. package/dist/components/svar-grid-interactions.js +174 -0
  220. package/dist/components/svar-grid-loading.d.ts +40 -0
  221. package/dist/components/svar-grid-loading.js +180 -0
  222. package/dist/components/svar-grid-operations.d.ts +37 -0
  223. package/dist/components/svar-grid-operations.js +186 -0
  224. package/dist/components/svar-grid-panes.d.ts +34 -0
  225. package/dist/components/svar-grid-panes.js +66 -0
  226. package/dist/components/svar-grid-resource-loading.d.ts +18 -0
  227. package/dist/components/svar-grid-resource-loading.js +68 -0
  228. package/dist/components/svar-grid-resource-session.svelte.d.ts +29 -0
  229. package/dist/components/svar-grid-resource-session.svelte.js +61 -0
  230. package/dist/components/table-contract.d.ts +12 -1
  231. package/dist/components/task-action.svelte.d.ts +13 -0
  232. package/dist/components/task-action.svelte.js +73 -0
  233. package/dist/components/ui/DesignSystemShowcase.svelte +164 -0
  234. package/dist/components/ui/DesignSystemShowcase.svelte.d.ts +3 -0
  235. package/dist/components/ui/badge/badge-variants.d.ts +3 -2
  236. package/dist/components/ui/badge/badge-variants.js +2 -1
  237. package/dist/components/ui/badge/badge.svelte +3 -0
  238. package/dist/components/ui/badge/badge.svelte.d.ts +1 -0
  239. package/dist/components/ui/button/button-variants.d.ts +5 -4
  240. package/dist/components/ui/button/button-variants.js +7 -2
  241. package/dist/components/ui/checkbox/checkbox.svelte +5 -1
  242. package/dist/components/ui/checkbox/checkbox.svelte.d.ts +5 -1
  243. package/dist/components/ui/input/input.svelte +8 -6
  244. package/dist/components/ui/input/input.svelte.d.ts +4 -1
  245. package/dist/components/ui/select/select.svelte +4 -1
  246. package/dist/components/ui/select/select.svelte.d.ts +2 -1
  247. package/dist/components/ui/textarea/textarea.svelte +2 -1
  248. package/dist/components.css +3110 -0
  249. package/dist/date-input-policy.d.ts +4 -0
  250. package/dist/date-input-policy.js +35 -0
  251. package/dist/design-contract.d.ts +13 -0
  252. package/dist/design-contract.js +11 -0
  253. package/dist/design-system-components.d.ts +100 -0
  254. package/dist/design-system-components.js +101 -0
  255. package/dist/design-system.d.ts +15 -0
  256. package/dist/design-system.js +7 -0
  257. package/dist/devtools-bridge.d.ts +80 -0
  258. package/dist/devtools-bridge.js +92 -0
  259. package/dist/index.d.ts +50 -1
  260. package/dist/index.js +32 -2
  261. package/dist/page-chrome.css +12 -49
  262. package/dist/recipes.d.ts +960 -0
  263. package/dist/recipes.js +264 -0
  264. package/dist/rendering/index.d.ts +87 -0
  265. package/dist/rendering/index.js +117 -0
  266. package/dist/styles/aliases.css +49 -0
  267. package/dist/styles/compatibility.epilogue.css +384 -0
  268. package/dist/styles/compatibility.prelude.css +5513 -0
  269. package/dist/styles/conditional-states.css +28 -0
  270. package/dist/styles/conditional-utilities.css +22 -0
  271. package/dist/tree-table-model.d.ts +24 -0
  272. package/dist/tree-table-model.js +111 -0
  273. package/dist/utils.d.ts +1 -1
  274. package/dist/utils.js +1 -1
  275. package/package.json +40 -10
  276. package/styles-compatibility.json +12 -0
@@ -0,0 +1,180 @@
1
+ import { snapshotPlainData, decodeBaseRecord } from '@svadmin/core/schema';
2
+ import { projectSvarRows } from './svar-grid-contract.js';
3
+ import { svarRecordIndex, svarRecordKey } from './svar-grid-operations.js';
4
+ export class SvarLoadCancelled extends Error {
5
+ constructor() { super('Grid request was superseded'); this.name = 'SvarLoadCancelled'; }
6
+ }
7
+ /** 单个网格的有界缓存:同键请求去重,AbortSignal 加请求所有者双重隔离。 */
8
+ export function createSvarLoadCache(copy, maxReady = 32, maxPending = 8) {
9
+ const entries = new Map();
10
+ let disposed = false;
11
+ function clear() {
12
+ const pending = [...entries.values()];
13
+ entries.clear();
14
+ for (const entry of pending)
15
+ if (entry.kind === 'pending')
16
+ entry.controller.abort();
17
+ }
18
+ function trim() {
19
+ let count = [...entries.values()].filter(entry => entry.kind === 'ready').length;
20
+ for (const [key, entry] of entries) {
21
+ if (count <= maxReady)
22
+ break;
23
+ if (entry.kind === 'ready') {
24
+ entries.delete(key);
25
+ count--;
26
+ }
27
+ }
28
+ }
29
+ function request(key, load) {
30
+ if (disposed)
31
+ return Promise.reject(new SvarLoadCancelled());
32
+ const existing = entries.get(key);
33
+ if (existing?.kind === 'pending')
34
+ return existing.promise.then(copy);
35
+ if (existing?.kind === 'ready') {
36
+ entries.delete(key);
37
+ entries.set(key, existing);
38
+ return Promise.resolve(copy(existing.value));
39
+ }
40
+ if ([...entries.values()].filter(entry => entry.kind === 'pending').length >= maxPending) {
41
+ return Promise.reject(new Error('Too many simultaneous grid requests'));
42
+ }
43
+ const owner = {};
44
+ const controller = new AbortController();
45
+ const current = () => !disposed && !controller.signal.aborted && entries.get(key)?.owner === owner;
46
+ const promise = Promise.resolve().then(() => {
47
+ if (!current())
48
+ throw new SvarLoadCancelled();
49
+ return load(controller.signal);
50
+ }).then(value => {
51
+ if (!current())
52
+ throw new SvarLoadCancelled();
53
+ const cached = copy(value);
54
+ if (!current())
55
+ throw new SvarLoadCancelled();
56
+ entries.set(key, { kind: 'ready', owner, value: cached });
57
+ trim();
58
+ return copy(cached);
59
+ }).catch((failure) => {
60
+ const active = current();
61
+ if (entries.get(key)?.owner === owner)
62
+ entries.delete(key);
63
+ if (!active)
64
+ throw new SvarLoadCancelled();
65
+ throw failure;
66
+ });
67
+ entries.set(key, { kind: 'pending', owner, controller, promise });
68
+ return promise;
69
+ }
70
+ return {
71
+ request, clear,
72
+ invalidate(key) {
73
+ const entry = entries.get(key);
74
+ entries.delete(key);
75
+ if (entry?.kind === 'pending')
76
+ entry.controller.abort();
77
+ },
78
+ abortPendingExcept(key) {
79
+ for (const [id, entry] of entries) {
80
+ if (id !== key && entry.kind === 'pending') {
81
+ entries.delete(id);
82
+ entry.controller.abort();
83
+ }
84
+ }
85
+ },
86
+ dispose() { disposed = true; clear(); },
87
+ };
88
+ }
89
+ export function snapshotSvarRecords(items, primaryKey = 'id', childrenKey) {
90
+ const cloned = snapshotPlainData(items);
91
+ if (!Array.isArray(cloned) || cloned.length > 100_000)
92
+ throw new Error('Invalid grid records');
93
+ const records = cloned.map(value => decodeBaseRecord(value));
94
+ if (svarRecordIndex(records, primaryKey, childrenKey).size > 100_000)
95
+ throw new Error('Too many grid records');
96
+ return records;
97
+ }
98
+ export function checkedSvarRange(event, total) {
99
+ if (!Number.isSafeInteger(total) || total < 0 || total > 10_000_000)
100
+ throw new Error('Invalid total row count');
101
+ const row = event && typeof event === 'object' ? Object.getOwnPropertyDescriptor(event, 'row')?.value : undefined;
102
+ const start = row && typeof row === 'object' ? Object.getOwnPropertyDescriptor(row, 'start')?.value : undefined;
103
+ const end = row && typeof row === 'object' ? Object.getOwnPropertyDescriptor(row, 'end')?.value : undefined;
104
+ if (typeof start !== 'number' || typeof end !== 'number' || !Number.isSafeInteger(start) || !Number.isSafeInteger(end)
105
+ || start < 0 || end < start || end - start > 2048)
106
+ throw new Error('Invalid grid window');
107
+ return { start: Math.min(start, total), end: Math.min(end, total) };
108
+ }
109
+ export function snapshotSvarWindow(page, range, primaryKey = 'id') {
110
+ const total = page && typeof page === 'object' ? Object.getOwnPropertyDescriptor(page, 'total')?.value : undefined;
111
+ const data = page && typeof page === 'object' ? Object.getOwnPropertyDescriptor(page, 'data')?.value : undefined;
112
+ if (typeof total !== 'number' || !Number.isSafeInteger(total) || total < 0 || total > 10_000_000 || !Array.isArray(data)
113
+ || data.length !== Math.max(0, Math.min(range.end, total) - range.start))
114
+ throw new Error('Invalid window response');
115
+ return { data: snapshotSvarRecords(data, primaryKey), total };
116
+ }
117
+ export function svarRowId(record, primaryKey) {
118
+ const id = Object.getOwnPropertyDescriptor(record, primaryKey)?.value;
119
+ if (typeof id !== 'string' && typeof id !== 'number')
120
+ throw new Error('Invalid record ID');
121
+ svarRecordKey(id);
122
+ return id;
123
+ }
124
+ /** 合并已加载分支但不修改 Provider 记录;最后全树验证,拒绝跨分支重复 ID。 */
125
+ export function mergeSvarBranches(items, branches, primaryKey, childrenKey) {
126
+ if (['__proto__', 'prototype', 'constructor'].includes(childrenKey) || !childrenKey)
127
+ throw new Error('Invalid children field');
128
+ const copied = snapshotSvarRecords(items, primaryKey, childrenKey);
129
+ let count = 0;
130
+ const ancestors = new Set();
131
+ function visit(records, depth) {
132
+ if (depth > 64)
133
+ throw new Error('Grid tree is too deep');
134
+ return records.map(record => {
135
+ if (++count > 100_000)
136
+ throw new Error('Too many grid records');
137
+ const key = svarRecordKey(svarRowId(record, primaryKey));
138
+ if (ancestors.has(key))
139
+ throw new Error('Cyclic grid branch');
140
+ const extra = branches.get(key);
141
+ const native = record[childrenKey];
142
+ const children = extra === undefined ? (Array.isArray(native) ? native.map(decodeBaseRecord) : undefined)
143
+ : snapshotSvarRecords(extra, primaryKey, childrenKey);
144
+ if (children === undefined)
145
+ return record;
146
+ ancestors.add(key);
147
+ const next = { ...record, [childrenKey]: visit(children, depth + 1) };
148
+ ancestors.delete(key);
149
+ return next;
150
+ });
151
+ }
152
+ const combined = visit(copied, 0);
153
+ svarRecordIndex(combined, primaryKey, childrenKey);
154
+ return combined;
155
+ }
156
+ /** 占位子节点永远不能被选中或编辑;真正展开前由适配器拦截并加载。 */
157
+ export function projectSvarLazyRows(records, columns, primaryKey, childrenKey, hasChildrenKey, loaded, opened) {
158
+ if (!hasChildrenKey || ['__proto__', 'prototype', 'constructor'].includes(hasChildrenKey))
159
+ throw new Error('Invalid branch marker field');
160
+ const index = svarRecordIndex(records, primaryKey, childrenKey);
161
+ const rows = projectSvarRows(records, columns, primaryKey, childrenKey);
162
+ function visit(items) {
163
+ for (const row of items) {
164
+ if (row.data?.length) {
165
+ row.open = opened.has(row.id);
166
+ visit(row.data);
167
+ }
168
+ else {
169
+ const record = index.get(row.id);
170
+ const marker = record ? Object.getOwnPropertyDescriptor(record, hasChildrenKey)?.value : undefined;
171
+ if (marker === true && !loaded.has(row.id)) {
172
+ row.data = [{ id: `pending:${row.id}` }];
173
+ row.open = false;
174
+ }
175
+ }
176
+ }
177
+ }
178
+ visit(rows);
179
+ return rows;
180
+ }
@@ -0,0 +1,37 @@
1
+ import type { SvarColumn, SvarRow } from './svar-grid-contract.js';
2
+ export type SvarRecordId = string | number;
3
+ export interface SvarBatchResult {
4
+ readonly succeeded: SvarRecordId[];
5
+ readonly failed: {
6
+ id: SvarRecordId;
7
+ message: string;
8
+ uncertain: boolean;
9
+ }[];
10
+ readonly skipped: SvarRecordId[];
11
+ readonly cancelled: boolean;
12
+ }
13
+ export declare function svarRecordKey(id: SvarRecordId): string;
14
+ /** 不解析引擎字符串推测业务 ID,必须从当前已授权记录建立映射。 */
15
+ export declare function svarRecordIndex(items: readonly Record<string, unknown>[], primaryKey?: string, childrenKey?: string): Map<string, Record<string, unknown>>;
16
+ export declare function checkedSvarSelection(ids: readonly SvarRecordId[], max?: number): SvarRecordId[];
17
+ /** 整批预检后逐条重新授权;部分成功不是事务回滚,会话变更后停止派发。 */
18
+ export declare function runSvarBatch(options: {
19
+ ids: readonly SvarRecordId[];
20
+ current: () => boolean;
21
+ authorize: (id: SvarRecordId) => Promise<boolean>;
22
+ write: (id: SvarRecordId) => Promise<unknown>;
23
+ }): Promise<SvarBatchResult>;
24
+ /** 导出只接受显式投影后的标量值;不调用对象的 toString/toJSON。 */
25
+ export declare function svarCsv(rows: readonly SvarRow[], columns: readonly SvarColumn[]): string;
26
+ export interface SvarExportSnapshot {
27
+ readonly ids: readonly SvarRecordId[];
28
+ readonly csv: string;
29
+ }
30
+ /** 在首次 await 之前冻结完整导出内容与所有后代 ID,避免检查与导出对象不一致。 */
31
+ export declare function prepareSvarExport(items: readonly Record<string, unknown>[], columns: readonly SvarColumn[], primaryKey?: string, childrenKey?: string): SvarExportSnapshot;
32
+ /** 只授权已经冻结的快照;禁止只检查树根,或在权限等待结束后读取新数据。 */
33
+ export declare function authorizeSvarExport(snapshot: SvarExportSnapshot, options: {
34
+ current: () => boolean;
35
+ authorize: (action: 'list' | 'export', id: SvarRecordId | undefined) => Promise<boolean>;
36
+ }): Promise<string>;
37
+ export declare function downloadSvarCsv(content: string, resourceName: string): void;
@@ -0,0 +1,186 @@
1
+ import { checkedSvarColumns, projectSvarRows, svarColumnId } from './svar-grid-contract.js';
2
+ export function svarRecordKey(id) {
3
+ if ((typeof id !== 'string' || id.length === 0) && (typeof id !== 'number' || !Number.isFinite(id))) {
4
+ throw new Error('Invalid record ID');
5
+ }
6
+ return `${typeof id === 'number' ? 'n' : 's'}:${id}`;
7
+ }
8
+ /** 不解析引擎字符串推测业务 ID,必须从当前已授权记录建立映射。 */
9
+ export function svarRecordIndex(items, primaryKey = 'id', childrenKey) {
10
+ const index = new Map();
11
+ const ancestors = new Set();
12
+ function visit(records, depth) {
13
+ if (!Array.isArray(records) || depth > 64)
14
+ throw new Error('Invalid grid tree');
15
+ for (const record of records) {
16
+ if (!record || typeof record !== 'object' || Array.isArray(record) || ancestors.has(record))
17
+ throw new Error('Invalid grid tree');
18
+ const descriptor = Object.getOwnPropertyDescriptor(record, primaryKey);
19
+ const id = descriptor && 'value' in descriptor ? descriptor.value : undefined;
20
+ if (typeof id !== 'string' && typeof id !== 'number')
21
+ throw new Error('Invalid record ID');
22
+ const key = svarRecordKey(id);
23
+ if (index.has(key))
24
+ throw new Error('Duplicate record ID');
25
+ index.set(key, record);
26
+ if (childrenKey) {
27
+ const childDescriptor = Object.getOwnPropertyDescriptor(record, childrenKey);
28
+ if (childDescriptor && !('value' in childDescriptor))
29
+ throw new Error('Accessors are not allowed');
30
+ const children = childDescriptor?.value;
31
+ if (children !== undefined && !Array.isArray(children))
32
+ throw new Error('Invalid child records');
33
+ if (Array.isArray(children)) {
34
+ ancestors.add(record);
35
+ visit(children, depth + 1);
36
+ ancestors.delete(record);
37
+ }
38
+ }
39
+ }
40
+ }
41
+ visit(items, 0);
42
+ return index;
43
+ }
44
+ export function checkedSvarSelection(ids, max = 100) {
45
+ if (!Array.isArray(ids) || ids.length > max)
46
+ throw new Error(`Select at most ${max} records`);
47
+ const seen = new Set();
48
+ return ids.filter(id => {
49
+ const key = svarRecordKey(id);
50
+ if (seen.has(key))
51
+ return false;
52
+ seen.add(key);
53
+ return true;
54
+ });
55
+ }
56
+ /** 整批预检后逐条重新授权;部分成功不是事务回滚,会话变更后停止派发。 */
57
+ export async function runSvarBatch(options) {
58
+ const ids = checkedSvarSelection(options.ids);
59
+ const succeeded = [];
60
+ const failed = [];
61
+ let cancelled = false;
62
+ for (const id of ids) {
63
+ if (!options.current())
64
+ return { succeeded, failed, skipped: ids, cancelled: true };
65
+ const allowed = await options.authorize(id).catch(() => false);
66
+ if (!options.current())
67
+ return { succeeded, failed, skipped: ids, cancelled: true };
68
+ if (!allowed)
69
+ return { succeeded, failed: [{ id, message: 'Access denied', uncertain: false }], skipped: ids.filter(value => !Object.is(value, id)), cancelled: false };
70
+ }
71
+ for (const id of ids) {
72
+ if (!options.current()) {
73
+ cancelled = true;
74
+ break;
75
+ }
76
+ const allowed = await options.authorize(id).catch(() => false);
77
+ if (!options.current()) {
78
+ cancelled = true;
79
+ break;
80
+ }
81
+ if (!allowed) {
82
+ failed.push({ id, message: 'Access denied', uncertain: false });
83
+ continue;
84
+ }
85
+ try {
86
+ await options.write(id);
87
+ succeeded.push(id);
88
+ }
89
+ catch (error) {
90
+ const details = error && typeof error === 'object' ? Object.getOwnPropertyDescriptor(error, 'details')?.value : undefined;
91
+ const known = details && typeof details === 'object' ? Object.getOwnPropertyDescriptor(details, 'writeMayHaveSucceeded')?.value : undefined;
92
+ failed.push({ id, message: 'Operation failed; refresh before retrying', uncertain: known !== false });
93
+ }
94
+ if (!options.current()) {
95
+ cancelled = true;
96
+ break;
97
+ }
98
+ }
99
+ const attempted = new Set([...succeeded, ...failed.map(item => item.id)].map(svarRecordKey));
100
+ return { succeeded, failed, skipped: ids.filter(id => !attempted.has(svarRecordKey(id))), cancelled };
101
+ }
102
+ function hasFormulaPrefix(text) {
103
+ if (text.startsWith('\t') || text.startsWith('\r') || text.startsWith('\n'))
104
+ return true;
105
+ let offset = 0;
106
+ while (offset < text.length) {
107
+ const character = text[offset] ?? '';
108
+ if (text.charCodeAt(offset) <= 31 || /\s/u.test(character))
109
+ offset++;
110
+ else
111
+ break;
112
+ }
113
+ const first = text[offset];
114
+ return first !== undefined && '=+@-'.includes(first);
115
+ }
116
+ /** 导出只接受显式投影后的标量值;不调用对象的 toString/toJSON。 */
117
+ export function svarCsv(rows, columns) {
118
+ const cell = (value) => {
119
+ let text = typeof value === 'string' ? value
120
+ : typeof value === 'number' && Number.isFinite(value) ? String(value)
121
+ : typeof value === 'boolean' ? String(value) : '';
122
+ if (typeof value === 'string' && hasFormulaPrefix(text))
123
+ text = `'${text}`;
124
+ return `"${text.replaceAll('"', '""')}"`;
125
+ };
126
+ const lines = [columns.map(column => cell(column.label)).join(',')];
127
+ let count = 0;
128
+ const ancestors = new Set();
129
+ function visit(records, depth) {
130
+ if (depth > 64)
131
+ throw new Error('Export tree is too deep');
132
+ for (const row of records) {
133
+ if (++count > 100_000 || ancestors.has(row))
134
+ throw new Error('Invalid or oversized export');
135
+ lines.push(columns.map(column => cell(row[svarColumnId(column.key)])).join(','));
136
+ if (row.data) {
137
+ ancestors.add(row);
138
+ visit(row.data, depth + 1);
139
+ ancestors.delete(row);
140
+ }
141
+ }
142
+ }
143
+ visit(rows, 0);
144
+ return `\uFEFF${lines.join('\r\n')}\r\n`;
145
+ }
146
+ /** 在首次 await 之前冻结完整导出内容与所有后代 ID,避免检查与导出对象不一致。 */
147
+ export function prepareSvarExport(items, columns, primaryKey = 'id', childrenKey) {
148
+ const checked = checkedSvarColumns(columns);
149
+ const index = svarRecordIndex(items, primaryKey, childrenKey);
150
+ const ids = [];
151
+ for (const record of index.values()) {
152
+ const id = Object.getOwnPropertyDescriptor(record, primaryKey)?.value;
153
+ if (typeof id !== 'string' && typeof id !== 'number')
154
+ throw new Error('Invalid record ID');
155
+ ids.push(id);
156
+ }
157
+ const csv = svarCsv(projectSvarRows(items, checked, primaryKey, childrenKey), checked);
158
+ return Object.freeze({ ids: Object.freeze(ids), csv });
159
+ }
160
+ /** 只授权已经冻结的快照;禁止只检查树根,或在权限等待结束后读取新数据。 */
161
+ export async function authorizeSvarExport(snapshot, options) {
162
+ async function check(action, id) {
163
+ if (!options.current())
164
+ throw new Error('Export scope changed');
165
+ const allowed = await options.authorize(action, id);
166
+ if (!options.current() || !allowed)
167
+ throw new Error('Export access denied');
168
+ }
169
+ await check('list');
170
+ await check('export');
171
+ for (const id of snapshot.ids)
172
+ await check('export', id);
173
+ if (!options.current())
174
+ throw new Error('Export scope changed');
175
+ return snapshot.csv;
176
+ }
177
+ export function downloadSvarCsv(content, resourceName) {
178
+ const url = URL.createObjectURL(new Blob([content], { type: 'text/csv;charset=utf-8' }));
179
+ const anchor = document.createElement('a');
180
+ anchor.href = url;
181
+ anchor.download = `${resourceName.replace(/[^a-zA-Z0-9_-]/gu, '_').slice(0, 80) || 'records'}.csv`;
182
+ document.body.append(anchor);
183
+ anchor.click();
184
+ anchor.remove();
185
+ setTimeout(() => URL.revokeObjectURL(url), 1000);
186
+ }
@@ -0,0 +1,34 @@
1
+ import type { Component } from 'svelte';
2
+ import type { SvarInteractiveApi, SvarInteractiveEngineProps } from './svar-grid-interactions.js';
3
+ export interface SvarManagedApi extends SvarInteractiveApi {
4
+ exec(action: string, params?: Record<string, unknown>): Promise<unknown>;
5
+ getState(): {
6
+ selectedRows?: unknown;
7
+ scrollTop?: number;
8
+ flatData?: Record<string, unknown>[];
9
+ focusCell?: {
10
+ row?: string | number;
11
+ column?: string | number;
12
+ };
13
+ };
14
+ }
15
+ export interface SvarManagedEngineProps extends Omit<SvarInteractiveEngineProps, 'init' | 'columns'> {
16
+ columns: (SvarInteractiveEngineProps['columns'][number] & {
17
+ hidden?: boolean;
18
+ cell?: Component<{
19
+ row: unknown;
20
+ column: unknown;
21
+ }>;
22
+ })[];
23
+ dynamic?: {
24
+ rowCount?: number;
25
+ };
26
+ init?: (api: SvarManagedApi) => void;
27
+ }
28
+ /** 两个公开 Grid 实例组成固定右侧面板,不读取或改写上游 Community 功能开关。 */
29
+ export declare function createSvarPanePair(current: () => boolean): {
30
+ attach: (side: 0 | 1, api: SvarManagedApi) => void;
31
+ focus: (side: 0 | 1, row: string | number, column: string) => void;
32
+ get: (side: 0 | 1) => SvarManagedApi | undefined;
33
+ dispose(): void;
34
+ };
@@ -0,0 +1,66 @@
1
+ function own(event, key) {
2
+ return event && typeof event === 'object' ? Object.getOwnPropertyDescriptor(event, key)?.value : undefined;
3
+ }
4
+ function mirroredEvent(action, event) {
5
+ if (action === 'scroll-to') {
6
+ const top = own(event, 'top');
7
+ return typeof top === 'number' && Number.isFinite(top) && top >= 0 ? { top } : undefined;
8
+ }
9
+ if (action === 'open-row' || action === 'close-row') {
10
+ const id = own(event, 'id');
11
+ return typeof id === 'string' ? { id, nested: own(event, 'nested') === true } : undefined;
12
+ }
13
+ const key = own(event, 'key');
14
+ if (typeof key !== 'string')
15
+ return undefined;
16
+ if (action === 'sort-rows') {
17
+ // 上游首次排序可能省略 order,其公开语义为升序。
18
+ const order = own(event, 'order') ?? 'asc';
19
+ if (order !== 'asc' && order !== 'desc')
20
+ return undefined;
21
+ return { key, order, add: own(event, 'add') === true };
22
+ }
23
+ const value = own(event, 'value');
24
+ return typeof value === 'string' || value == null ? { key, value: value ?? '' } : undefined;
25
+ }
26
+ /** 两个公开 Grid 实例组成固定右侧面板,不读取或改写上游 Community 功能开关。 */
27
+ export function createSvarPanePair(current) {
28
+ const panes = new Map();
29
+ let disposed = false;
30
+ let synchronizing = 0;
31
+ function attach(side, api) {
32
+ panes.set(side, api);
33
+ for (const action of ['scroll-to', 'sort-rows', 'filter-rows', 'open-row', 'close-row']) {
34
+ api.on(action, event => {
35
+ const peer = panes.get(side === 0 ? 1 : 0);
36
+ if (disposed || synchronizing || panes.get(side) !== api || !peer || !current())
37
+ return;
38
+ const next = mirroredEvent(action, event);
39
+ if (!next)
40
+ return;
41
+ if (action === 'scroll-to' && peer.getState().scrollTop === next['top'])
42
+ return;
43
+ synchronizing++;
44
+ try {
45
+ void Promise.resolve(peer.exec(action, next)).catch(() => { }).finally(() => { synchronizing--; });
46
+ }
47
+ catch {
48
+ synchronizing--;
49
+ }
50
+ });
51
+ }
52
+ if (side === 1) {
53
+ const top = panes.get(0)?.getState().scrollTop;
54
+ if (typeof top === 'number' && top > 0)
55
+ void api.exec('scroll-to', { top }).catch(() => { });
56
+ }
57
+ }
58
+ function focus(side, row, column) {
59
+ if (disposed || !current())
60
+ return;
61
+ const api = panes.get(side);
62
+ if (api)
63
+ void api.exec('focus-cell', { row, column, eventSource: 'svadmin-pinned-navigation' }).catch(() => { });
64
+ }
65
+ return { attach, focus, get: (side) => panes.get(side), dispose() { disposed = true; panes.clear(); } };
66
+ }
@@ -0,0 +1,18 @@
1
+ import { type SvarRange, type SvarWindowPage } from './svar-grid-loading.js';
2
+ export interface SvarLazyTree {
3
+ /** Resource field containing the parent record ID. */
4
+ readonly parentField: string;
5
+ readonly rootValue?: string | number | null;
6
+ readonly hasChildrenKey?: string;
7
+ /** A branch is rejected rather than silently truncated above this bound. Default: 10,000. */
8
+ readonly maxChildren?: number;
9
+ }
10
+ export type SvarResourcePageReader = (pagination: {
11
+ current: number;
12
+ pageSize: number;
13
+ }) => Promise<SvarWindowPage>;
14
+ /** Translate a zero-based exclusive grid window to the existing one-based Provider pagination. */
15
+ export declare function loadSvarResourceWindow(range: SvarRange, pageSize: number, read: SvarResourcePageReader, signal: AbortSignal, primaryKey?: string): Promise<SvarWindowPage>;
16
+ /** Load all children in bounded pages. Partial branches must never masquerade as complete trees. */
17
+ export declare function loadSvarResourceChildren(pageSize: number, maxChildren: number, read: SvarResourcePageReader, signal: AbortSignal, primaryKey?: string, childrenKey?: string): Promise<readonly Record<string, unknown>[]>;
18
+ export declare function appendSvarResourcePage(rows: readonly Record<string, unknown>[], page: SvarWindowPage, expectedTotal: number, primaryKey?: string): readonly Record<string, unknown>[];
@@ -0,0 +1,68 @@
1
+ import { snapshotSvarRecords, snapshotSvarWindow, SvarLoadCancelled } from './svar-grid-loading.js';
2
+ function checkSignal(signal) {
3
+ if (signal.aborted)
4
+ throw new SvarLoadCancelled();
5
+ }
6
+ function checkPageSize(pageSize) {
7
+ if (!Number.isSafeInteger(pageSize) || pageSize < 1 || pageSize > 1000)
8
+ throw new Error('Invalid resource page size');
9
+ }
10
+ function checkPage(page, start, size, primaryKey) {
11
+ return snapshotSvarWindow(page, { start, end: start + size }, primaryKey);
12
+ }
13
+ /** Translate a zero-based exclusive grid window to the existing one-based Provider pagination. */
14
+ export async function loadSvarResourceWindow(range, pageSize, read, signal, primaryKey = 'id') {
15
+ checkPageSize(pageSize);
16
+ checkSignal(signal);
17
+ if (!Number.isSafeInteger(range.start) || !Number.isSafeInteger(range.end) || range.start < 0
18
+ || range.end < range.start || range.end > 10_000_000 || range.end - range.start > 2048)
19
+ throw new Error('Invalid resource window');
20
+ const first = Math.floor(range.start / pageSize);
21
+ const last = Math.max(first, Math.ceil(range.end / pageSize) - 1);
22
+ let total;
23
+ const rows = [];
24
+ for (let pageIndex = first; pageIndex <= last; pageIndex++) {
25
+ checkSignal(signal);
26
+ const page = checkPage(await read({ current: pageIndex + 1, pageSize }), pageIndex * pageSize, pageSize, primaryKey);
27
+ checkSignal(signal);
28
+ if (total !== undefined && total !== page.total)
29
+ throw new Error('Resource changed during window loading; refresh');
30
+ total = page.total;
31
+ rows.push(...page.data);
32
+ if ((pageIndex + 1) * pageSize >= total)
33
+ break;
34
+ }
35
+ const data = rows.slice(range.start - first * pageSize, range.end - first * pageSize);
36
+ return snapshotSvarWindow({ data, total: total ?? 0 }, range, primaryKey);
37
+ }
38
+ /** Load all children in bounded pages. Partial branches must never masquerade as complete trees. */
39
+ export async function loadSvarResourceChildren(pageSize, maxChildren, read, signal, primaryKey = 'id', childrenKey = 'children') {
40
+ checkPageSize(pageSize);
41
+ checkSignal(signal);
42
+ if (!Number.isSafeInteger(maxChildren) || maxChildren < 1 || maxChildren > 100_000)
43
+ throw new Error('Invalid child limit');
44
+ let total;
45
+ const rows = [];
46
+ for (let pageIndex = 0;; pageIndex++) {
47
+ checkSignal(signal);
48
+ const page = checkPage(await read({ current: pageIndex + 1, pageSize }), pageIndex * pageSize, pageSize, primaryKey);
49
+ checkSignal(signal);
50
+ if (page.total > maxChildren)
51
+ throw new Error('Branch exceeds the configured child limit');
52
+ if (total !== undefined && total !== page.total)
53
+ throw new Error('Branch changed during loading; retry');
54
+ total = page.total;
55
+ rows.push(...page.data);
56
+ if (rows.length >= total)
57
+ return snapshotSvarRecords(rows, primaryKey, childrenKey);
58
+ }
59
+ }
60
+ export function appendSvarResourcePage(rows, page, expectedTotal, primaryKey = 'id') {
61
+ if (!Number.isSafeInteger(expectedTotal) || expectedTotal < 0 || expectedTotal > 10_000_000)
62
+ throw new Error('Invalid expected total');
63
+ if (page.total !== expectedTotal)
64
+ throw new Error('Resource changed during infinite loading; refresh');
65
+ if (rows.length + page.data.length > expectedTotal || (!page.data.length && rows.length < expectedTotal))
66
+ throw new Error('Invalid next resource page');
67
+ return snapshotSvarRecords([...rows, ...page.data], primaryKey);
68
+ }
@@ -0,0 +1,29 @@
1
+ import { SvelteMap } from 'svelte/reactivity';
2
+ import type { Filter, Sort } from '@svadmin/core';
3
+ import type { SvarResourceReadRequest } from './SvarResourceRead.svelte';
4
+ import { type SvarWindowPage } from './svar-grid-loading.js';
5
+ import type { SvarRecordId } from './svar-grid-operations.js';
6
+ /** Query workers remain descendants of the host AdminContext and QueryClientProvider. */
7
+ export declare function createSvarResourceReads<Scope extends object>(options: {
8
+ scope: () => Scope;
9
+ current: (scope: Scope) => boolean;
10
+ authorize: (scope: Scope, parentId?: SvarRecordId) => Promise<boolean>;
11
+ resourceName: () => string;
12
+ dataScopeKey: () => string | number;
13
+ primaryKey: () => string;
14
+ childrenKey: () => string | undefined;
15
+ }): {
16
+ requests: SvelteMap<number, SvarResourceReadRequest>;
17
+ read: (input: {
18
+ scope: Scope;
19
+ signal: AbortSignal;
20
+ pagination: {
21
+ current: number;
22
+ pageSize: number;
23
+ };
24
+ filters: Filter[];
25
+ sorters: Sort[];
26
+ parentId?: SvarRecordId;
27
+ }) => Promise<SvarWindowPage>;
28
+ cancelAll: () => void;
29
+ };