@svgrid/enterprise 2.5.2 → 2.6.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 (620) hide show
  1. package/dist/SvAlertRuleEditor.svelte.d.ts +13 -0
  2. package/dist/SvAlertsManager.svelte.d.ts +14 -0
  3. package/dist/SvAlertsPanel.svelte.d.ts +9 -0
  4. package/dist/SvAuthGate.svelte.d.ts +22 -0
  5. package/dist/SvBoard.svelte.d.ts +35 -0
  6. package/dist/SvExportMenu.svelte.d.ts +61 -0
  7. package/dist/SvExpressionEditor.svelte.d.ts +12 -0
  8. package/dist/SvFileInput.svelte.d.ts +20 -0
  9. package/dist/SvGridAlerts.svelte.d.ts +77 -0
  10. package/dist/SvGridBoard.svelte.d.ts +30 -0
  11. package/dist/SvGridEditPanel.svelte.d.ts +73 -0
  12. package/dist/SvGridMasterDetail.svelte.d.ts +49 -0
  13. package/dist/SvGridScheduler.svelte.d.ts +30 -0
  14. package/dist/SvImportDialog.svelte.d.ts +88 -0
  15. package/dist/SvLookupInput.svelte.d.ts +21 -0
  16. package/dist/SvPivotDesigner.svelte.d.ts +176 -0
  17. package/dist/SvRecordDetail.svelte.d.ts +58 -0
  18. package/dist/SvSchedule.svelte.d.ts +29 -0
  19. package/dist/SvSchemaChart.svelte.d.ts +61 -0
  20. package/dist/SvSchemaDashboard.svelte.d.ts +46 -0
  21. package/dist/alerts/alert-engine-attach.d.ts +79 -0
  22. package/dist/alerts/alert-engine-attach.js +106 -0
  23. package/dist/alerts/alert-engine.d.ts +42 -0
  24. package/dist/alerts/alert-engine.js +196 -0
  25. package/dist/alerts/alert-formats.d.ts +26 -0
  26. package/dist/alerts/alert-formats.js +58 -0
  27. package/dist/alerts/alert-observer.d.ts +54 -0
  28. package/dist/alerts/alert-observer.js +156 -0
  29. package/dist/alerts/alert-scheduler.d.ts +30 -0
  30. package/dist/alerts/alert-scheduler.js +54 -0
  31. package/dist/alerts/alert-storage.d.ts +31 -0
  32. package/dist/alerts/alert-storage.js +92 -0
  33. package/dist/alerts/alert-store.svelte.d.ts +24 -0
  34. package/dist/alerts/alert-store.svelte.js +69 -0
  35. package/dist/alerts/alert-types.d.ts +86 -0
  36. package/dist/alerts/alert-types.js +1 -0
  37. package/dist/alerts.d.ts +2 -0
  38. package/{src/alerts.ts → dist/alerts.js} +9 -9
  39. package/dist/board.d.ts +7 -0
  40. package/{src/board.ts → dist/board.js} +13 -14
  41. package/dist/cdn/svgrid-enterprise.svelte-external.js +2987 -2981
  42. package/dist/designer/assets/{index-CM5xvaOy.js → index-BF0UH638.js} +3 -3
  43. package/dist/designer/assets/{src-D-ET9Mmo.js → src-BPJruwB9.js} +184 -184
  44. package/dist/designer/index.html +2 -2
  45. package/dist/edit-panel.d.ts +105 -0
  46. package/dist/edit-panel.js +350 -0
  47. package/dist/export-conditional.d.ts +31 -0
  48. package/dist/export-conditional.js +65 -0
  49. package/dist/export-ooxml.d.ts +93 -0
  50. package/dist/export-ooxml.js +385 -0
  51. package/dist/export-pdf.d.ts +107 -0
  52. package/dist/export-pdf.js +144 -0
  53. package/dist/export-print.d.ts +55 -0
  54. package/dist/export-print.js +91 -0
  55. package/{src/export-serialize.ts → dist/export-serialize.d.ts} +11 -24
  56. package/dist/export-serialize.js +11 -0
  57. package/dist/export-xls.d.ts +26 -0
  58. package/dist/export-xls.js +157 -0
  59. package/dist/export.d.ts +323 -0
  60. package/dist/export.js +1021 -0
  61. package/dist/expressions/evaluate.d.ts +17 -0
  62. package/dist/expressions/evaluate.js +214 -0
  63. package/dist/expressions/expression-columns.d.ts +61 -0
  64. package/dist/expressions/expression-columns.js +72 -0
  65. package/dist/expressions/expression-types.d.ts +125 -0
  66. package/dist/expressions/expression-types.js +1 -0
  67. package/dist/expressions/parse.d.ts +25 -0
  68. package/dist/expressions/parse.js +537 -0
  69. package/dist/import.d.ts +232 -0
  70. package/dist/import.js +846 -0
  71. package/dist/index.d.ts +66 -0
  72. package/dist/index.js +91 -0
  73. package/dist/install.d.ts +70 -0
  74. package/dist/install.js +61 -0
  75. package/dist/license-core.d.ts +37 -0
  76. package/dist/license-core.js +81 -0
  77. package/dist/license.d.ts +30 -0
  78. package/dist/license.js +139 -0
  79. package/dist/master-detail.d.ts +23 -0
  80. package/dist/master-detail.js +35 -0
  81. package/dist/node/studio.js +1 -1
  82. package/dist/pivot-chart.d.ts +28 -0
  83. package/dist/pivot-chart.js +71 -0
  84. package/dist/pivot-designer.d.ts +69 -0
  85. package/dist/pivot-designer.js +38 -0
  86. package/dist/pivot-enable.d.ts +6 -0
  87. package/{src/pivot-enable.ts → dist/pivot-enable.js} +13 -18
  88. package/dist/pivot.d.ts +111 -0
  89. package/dist/pivot.js +353 -0
  90. package/dist/print.d.ts +33 -0
  91. package/dist/print.js +61 -0
  92. package/dist/revoked.d.ts +1 -0
  93. package/{src/revoked.ts → dist/revoked.js} +5 -6
  94. package/dist/scheduler-assignments.d.ts +64 -0
  95. package/dist/scheduler-assignments.js +92 -0
  96. package/dist/scheduler-axis.d.ts +81 -0
  97. package/dist/scheduler-axis.js +180 -0
  98. package/{src/scheduler-booking.ts → dist/scheduler-booking.d.ts} +10 -43
  99. package/dist/scheduler-booking.js +50 -0
  100. package/dist/scheduler-config.d.ts +177 -0
  101. package/dist/scheduler-config.js +1 -0
  102. package/dist/scheduler-dependencies.d.ts +89 -0
  103. package/dist/scheduler-dependencies.js +179 -0
  104. package/dist/scheduler-freebusy.d.ts +19 -0
  105. package/{src/scheduler-freebusy.ts → dist/scheduler-freebusy.js} +9 -19
  106. package/{src/scheduler-heatmap.ts → dist/scheduler-heatmap.d.ts} +12 -35
  107. package/dist/scheduler-heatmap.js +41 -0
  108. package/dist/scheduler-resource-tree.d.ts +48 -0
  109. package/dist/scheduler-resource-tree.js +78 -0
  110. package/dist/scheduler-slots.d.ts +37 -0
  111. package/dist/scheduler-slots.js +80 -0
  112. package/dist/scheduler-summary.d.ts +41 -0
  113. package/dist/scheduler-summary.js +54 -0
  114. package/dist/scheduler.d.ts +7 -0
  115. package/{src/scheduler.ts → dist/scheduler.js} +13 -14
  116. package/dist/scheduling.d.ts +132 -0
  117. package/dist/scheduling.js +228 -0
  118. package/dist/schema-designer.d.ts +42 -0
  119. package/dist/schema-designer.js +117 -0
  120. package/dist/schema.d.ts +369 -0
  121. package/dist/schema.js +216 -0
  122. package/dist/smart-shim.d.ts +62 -0
  123. package/dist/smart-shim.js +34 -0
  124. package/dist/sources/aggregate.d.ts +43 -0
  125. package/dist/sources/aggregate.js +60 -0
  126. package/dist/sources/auth-supabase.d.ts +69 -0
  127. package/dist/sources/auth-supabase.js +39 -0
  128. package/dist/sources/dashboard.d.ts +65 -0
  129. package/dist/sources/dashboard.js +95 -0
  130. package/dist/sources/field-inference.d.ts +23 -0
  131. package/dist/sources/field-inference.js +52 -0
  132. package/dist/sources/filters.d.ts +35 -0
  133. package/dist/sources/filters.js +52 -0
  134. package/dist/sources/index.d.ts +18 -0
  135. package/dist/sources/index.js +18 -0
  136. package/dist/sources/introspect-supabase.d.ts +30 -0
  137. package/dist/sources/introspect-supabase.js +134 -0
  138. package/dist/sources/realtime-supabase.d.ts +37 -0
  139. package/dist/sources/realtime-supabase.js +52 -0
  140. package/dist/sources/relation-lookup.d.ts +50 -0
  141. package/dist/sources/relation-lookup.js +77 -0
  142. package/dist/sources/rest-adapters.d.ts +48 -0
  143. package/dist/sources/rest-adapters.js +85 -0
  144. package/dist/sources/rest.d.ts +38 -0
  145. package/dist/sources/rest.js +86 -0
  146. package/dist/sources/schema-from-columns.d.ts +37 -0
  147. package/dist/sources/schema-from-columns.js +48 -0
  148. package/dist/sources/supabase.d.ts +33 -0
  149. package/dist/sources/supabase.js +74 -0
  150. package/dist/sources/with-entity-rules.d.ts +25 -0
  151. package/dist/sources/with-entity-rules.js +47 -0
  152. package/dist/sources/with-relation-labels.d.ts +26 -0
  153. package/dist/sources/with-relation-labels.js +38 -0
  154. package/dist/staged-editing.d.ts +85 -0
  155. package/dist/staged-editing.js +0 -0
  156. package/dist/studio/bug-report.d.ts +61 -0
  157. package/dist/studio/bug-report.js +126 -0
  158. package/dist/studio/cli.d.ts +56 -0
  159. package/dist/studio/cli.js +70 -0
  160. package/dist/studio/copilot-core.d.ts +22 -0
  161. package/{src/studio/copilot-core.ts → dist/studio/copilot-core.js} +34 -38
  162. package/dist/studio/csv.d.ts +36 -0
  163. package/dist/studio/csv.js +173 -0
  164. package/dist/studio/db-connect-string.d.ts +45 -0
  165. package/dist/studio/db-connect-string.js +113 -0
  166. package/dist/studio/deploy-cli.d.ts +35 -0
  167. package/dist/studio/deploy-cli.js +81 -0
  168. package/dist/studio/emit-project.d.ts +77 -0
  169. package/dist/studio/emit-project.js +5389 -0
  170. package/dist/studio/emit-schema.d.ts +110 -0
  171. package/dist/studio/emit-schema.js +1128 -0
  172. package/dist/studio/index.d.ts +35 -0
  173. package/dist/studio/index.js +38 -0
  174. package/dist/studio/init-flow.d.ts +58 -0
  175. package/dist/studio/init-flow.js +451 -0
  176. package/dist/studio/introspect-db.d.ts +47 -0
  177. package/dist/studio/introspect-db.js +255 -0
  178. package/dist/studio/introspect-openapi.d.ts +19 -0
  179. package/dist/studio/introspect-openapi.js +244 -0
  180. package/dist/studio/introspect-prisma.d.ts +25 -0
  181. package/dist/studio/introspect-prisma.js +164 -0
  182. package/dist/studio/introspect.d.ts +35 -0
  183. package/dist/studio/introspect.js +306 -0
  184. package/dist/studio/project.d.ts +1327 -0
  185. package/dist/studio/project.js +1798 -0
  186. package/dist/studio/sample-data.d.ts +19 -0
  187. package/dist/studio/sample-data.js +207 -0
  188. package/dist/studio/samples/ats.d.ts +2 -0
  189. package/dist/studio/samples/ats.js +194 -0
  190. package/dist/studio/samples/clinic.d.ts +2 -0
  191. package/dist/studio/samples/clinic.js +171 -0
  192. package/dist/studio/samples/crm.d.ts +2 -0
  193. package/dist/studio/samples/crm.js +280 -0
  194. package/dist/studio/samples/datasets.d.ts +38 -0
  195. package/dist/studio/samples/datasets.js +296 -0
  196. package/dist/studio/samples/ecommerce.d.ts +2 -0
  197. package/dist/studio/samples/ecommerce.js +178 -0
  198. package/dist/studio/samples/events.d.ts +2 -0
  199. package/dist/studio/samples/events.js +192 -0
  200. package/dist/studio/samples/fleet.d.ts +2 -0
  201. package/dist/studio/samples/fleet.js +203 -0
  202. package/dist/studio/samples/gym.d.ts +2 -0
  203. package/dist/studio/samples/gym.js +205 -0
  204. package/dist/studio/samples/hr.d.ts +2 -0
  205. package/dist/studio/samples/hr.js +186 -0
  206. package/dist/studio/samples/index.d.ts +13 -0
  207. package/dist/studio/samples/index.js +44 -0
  208. package/dist/studio/samples/insurance.d.ts +2 -0
  209. package/dist/studio/samples/insurance.js +220 -0
  210. package/dist/studio/samples/inventory.d.ts +2 -0
  211. package/dist/studio/samples/inventory.js +204 -0
  212. package/dist/studio/samples/invoicing.d.ts +2 -0
  213. package/dist/studio/samples/invoicing.js +154 -0
  214. package/dist/studio/samples/library.d.ts +2 -0
  215. package/dist/studio/samples/library.js +171 -0
  216. package/dist/studio/samples/live-data.d.ts +5 -0
  217. package/dist/studio/samples/live-data.js +261 -0
  218. package/dist/studio/samples/projects.d.ts +2 -0
  219. package/dist/studio/samples/projects.js +203 -0
  220. package/dist/studio/samples/realestate.d.ts +2 -0
  221. package/dist/studio/samples/realestate.js +187 -0
  222. package/dist/studio/samples/restaurant.d.ts +2 -0
  223. package/dist/studio/samples/restaurant.js +180 -0
  224. package/dist/studio/samples/school.d.ts +2 -0
  225. package/dist/studio/samples/school.js +188 -0
  226. package/dist/studio/samples/shared.d.ts +142 -0
  227. package/dist/studio/samples/shared.js +164 -0
  228. package/dist/studio/samples/starter.d.ts +4 -0
  229. package/dist/studio/samples/starter.js +237 -0
  230. package/dist/studio/samples/subscriptions.d.ts +2 -0
  231. package/dist/studio/samples/subscriptions.js +175 -0
  232. package/dist/studio/samples/support.d.ts +2 -0
  233. package/dist/studio/samples/support.js +209 -0
  234. package/dist/studio/scaffold-app.d.ts +22 -0
  235. package/{src/studio/scaffold-app.ts → dist/studio/scaffold-app.js} +45 -63
  236. package/dist/studio/scaffold.d.ts +63 -0
  237. package/dist/studio/scaffold.js +346 -0
  238. package/dist/studio/screen-suites.d.ts +193 -0
  239. package/dist/studio/screen-suites.js +297 -0
  240. package/dist/studio/themes.d.ts +34 -0
  241. package/dist/studio/themes.js +41 -0
  242. package/dist/studio/ui-components.d.ts +89 -0
  243. package/dist/studio/ui-components.generated.d.ts +29 -0
  244. package/dist/studio/ui-components.generated.js +7139 -0
  245. package/dist/studio/ui-components.js +673 -0
  246. package/dist/studio/user-error.d.ts +23 -0
  247. package/{src/studio/user-error.ts → dist/studio/user-error.js} +10 -13
  248. package/dist/studio/verify.d.ts +34 -0
  249. package/dist/studio/verify.js +47 -0
  250. package/dist/sveltekit/in-memory.d.ts +14 -0
  251. package/dist/sveltekit/in-memory.js +113 -0
  252. package/dist/sveltekit/index.d.ts +6 -0
  253. package/dist/sveltekit/index.js +5 -0
  254. package/dist/sveltekit/query-plan.d.ts +44 -0
  255. package/dist/sveltekit/query-plan.js +76 -0
  256. package/dist/sveltekit/sql-source.d.ts +47 -0
  257. package/dist/sveltekit/sql-source.js +106 -0
  258. package/dist/sveltekit/sql.d.ts +48 -0
  259. package/dist/sveltekit/sql.js +73 -0
  260. package/dist/sveltekit/transport.d.ts +209 -0
  261. package/dist/sveltekit/transport.js +219 -0
  262. package/{src/sveltekit/types.ts → dist/sveltekit/types.d.ts} +8 -11
  263. package/dist/sveltekit/types.js +1 -0
  264. package/dist/upgrade-prompt.d.ts +16 -0
  265. package/dist/upgrade-prompt.js +141 -0
  266. package/dist/version.d.ts +13 -0
  267. package/{src/version.ts → dist/version.js} +1 -1
  268. package/dist/watermark.d.ts +2 -0
  269. package/dist/watermark.js +146 -0
  270. package/package.json +26 -24
  271. package/src/SvBoard.dom.test.ts +0 -67
  272. package/src/SvGridAlerts.dom.test.ts +0 -113
  273. package/src/SvGridEditPanel.dom.test.ts +0 -320
  274. package/src/SvRecordDetail.dom.test.ts +0 -137
  275. package/src/SvSchedule.dom.test.ts +0 -57
  276. package/src/ai-export-pdf.dom.test.ts +0 -77
  277. package/src/ai-export-xlsx.dom.test.ts +0 -90
  278. package/src/ai-export.dom.test.ts +0 -114
  279. package/src/alerts/alert-engine-attach.ts +0 -165
  280. package/src/alerts/alert-engine.test.ts +0 -135
  281. package/src/alerts/alert-engine.ts +0 -260
  282. package/src/alerts/alert-formats.test.ts +0 -87
  283. package/src/alerts/alert-formats.ts +0 -77
  284. package/src/alerts/alert-observer.test.ts +0 -189
  285. package/src/alerts/alert-observer.ts +0 -208
  286. package/src/alerts/alert-scheduler.ts +0 -96
  287. package/src/alerts/alert-storage.test.ts +0 -54
  288. package/src/alerts/alert-storage.ts +0 -116
  289. package/src/alerts/alert-store.svelte.ts +0 -80
  290. package/src/alerts/alert-types.ts +0 -94
  291. package/src/board.dom.test.ts +0 -941
  292. package/src/edit-panel.test.ts +0 -322
  293. package/src/edit-panel.ts +0 -379
  294. package/src/export-conditional.test.ts +0 -60
  295. package/src/export-conditional.ts +0 -94
  296. package/src/export-ooxml.test.ts +0 -152
  297. package/src/export-ooxml.ts +0 -489
  298. package/src/export-pdf.test.ts +0 -138
  299. package/src/export-pdf.ts +0 -245
  300. package/src/export-print.test.ts +0 -66
  301. package/src/export-print.ts +0 -132
  302. package/src/export-serialize.test.ts +0 -56
  303. package/src/export-xls.ts +0 -199
  304. package/src/export-xlsx-roundtrip.test.ts +0 -120
  305. package/src/export-xlsx.test.ts +0 -150
  306. package/src/export.test.ts +0 -349
  307. package/src/export.ts +0 -1464
  308. package/src/expressions/evaluate.test.ts +0 -111
  309. package/src/expressions/evaluate.ts +0 -237
  310. package/src/expressions/expression-columns.ts +0 -133
  311. package/src/expressions/expression-types.ts +0 -84
  312. package/src/expressions/parse.test.ts +0 -106
  313. package/src/expressions/parse.ts +0 -610
  314. package/src/import-automap.test.ts +0 -131
  315. package/src/import-hardening.test.ts +0 -158
  316. package/src/import.test.ts +0 -415
  317. package/src/import.ts +0 -1044
  318. package/src/index.ts +0 -569
  319. package/src/install.ts +0 -154
  320. package/src/license-core.test.ts +0 -23
  321. package/src/license-core.ts +0 -107
  322. package/src/license-expiry.test.ts +0 -127
  323. package/src/license.ts +0 -137
  324. package/src/master-detail.test.ts +0 -61
  325. package/src/master-detail.ts +0 -42
  326. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -178
  327. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-ZrPsKxob.js +0 -3875
  328. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-ZrPsKxob.js.map +0 -1
  329. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-ACqvWGE2.js +0 -21
  330. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-ACqvWGE2.js.map +0 -1
  331. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-D3w5jt92.js +0 -1938
  332. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-D3w5jt92.js.map +0 -1
  333. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-CC2V3H0y.js +0 -205
  334. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-CC2V3H0y.js.map +0 -1
  335. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-BXP37tAa.js +0 -18
  336. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-BXP37tAa.js.map +0 -1
  337. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-DwubnU5b.js +0 -264
  338. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-DwubnU5b.js.map +0 -1
  339. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-hD7f6PUz.js +0 -697
  340. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-hD7f6PUz.js.map +0 -1
  341. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -134
  342. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -1
  343. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -55
  344. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -1
  345. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -2
  346. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -46843
  347. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -1
  348. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -237
  349. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -1
  350. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -2
  351. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -4
  352. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -1
  353. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -7
  354. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -4
  355. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -1
  356. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -5
  357. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -1
  358. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -5
  359. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -1
  360. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -5
  361. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -1
  362. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -6
  363. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -83
  364. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -1
  365. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -559
  366. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -1
  367. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -24
  368. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -1
  369. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -122
  370. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -1
  371. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -2
  372. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -89
  373. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -1
  374. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -241
  375. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -1
  376. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DBx1SCN6.js +0 -4938
  377. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DBx1SCN6.js.map +0 -1
  378. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-gjfpSTFS.js +0 -495
  379. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-gjfpSTFS.js.map +0 -1
  380. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-DKoOKg8S.js +0 -190
  381. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-DKoOKg8S.js.map +0 -1
  382. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-C0MiR7eR.js +0 -8
  383. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-C0MiR7eR.js.map +0 -1
  384. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-B6Y7P0Q-.js +0 -138
  385. package/src/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-B6Y7P0Q-.js.map +0 -1
  386. package/src/pivot-chart.test.ts +0 -86
  387. package/src/pivot-chart.ts +0 -112
  388. package/src/pivot-designer.ts +0 -101
  389. package/src/pivot.test.ts +0 -335
  390. package/src/pivot.ts +0 -578
  391. package/src/print.ts +0 -107
  392. package/src/scheduler-assignments.test.ts +0 -97
  393. package/src/scheduler-assignments.ts +0 -134
  394. package/src/scheduler-axis.test.ts +0 -108
  395. package/src/scheduler-axis.ts +0 -238
  396. package/src/scheduler-booking.test.ts +0 -57
  397. package/src/scheduler-config.ts +0 -179
  398. package/src/scheduler-dependencies.test.ts +0 -155
  399. package/src/scheduler-dependencies.ts +0 -223
  400. package/src/scheduler-freebusy.test.ts +0 -41
  401. package/src/scheduler-heatmap.test.ts +0 -39
  402. package/src/scheduler-resource-tree.test.ts +0 -84
  403. package/src/scheduler-resource-tree.ts +0 -107
  404. package/src/scheduler-slots.test.ts +0 -53
  405. package/src/scheduler-slots.ts +0 -94
  406. package/src/scheduler-summary.test.ts +0 -47
  407. package/src/scheduler-summary.ts +0 -81
  408. package/src/scheduling.test.ts +0 -194
  409. package/src/scheduling.ts +0 -293
  410. package/src/schema-designer.test.ts +0 -121
  411. package/src/schema-designer.ts +0 -142
  412. package/src/schema.test.ts +0 -268
  413. package/src/schema.ts +0 -562
  414. package/src/smart-shim.ts +0 -107
  415. package/src/sources/aggregate.test.ts +0 -79
  416. package/src/sources/aggregate.ts +0 -102
  417. package/src/sources/auth-supabase.test.ts +0 -80
  418. package/src/sources/auth-supabase.ts +0 -87
  419. package/src/sources/dashboard.kpi.test.ts +0 -50
  420. package/src/sources/dashboard.test.ts +0 -61
  421. package/src/sources/dashboard.ts +0 -136
  422. package/src/sources/field-inference.test.ts +0 -60
  423. package/src/sources/field-inference.ts +0 -63
  424. package/src/sources/filters.test.ts +0 -58
  425. package/src/sources/filters.ts +0 -70
  426. package/src/sources/index.ts +0 -67
  427. package/src/sources/introspect-supabase.test.ts +0 -112
  428. package/src/sources/introspect-supabase.ts +0 -139
  429. package/src/sources/realtime-supabase.test.ts +0 -93
  430. package/src/sources/realtime-supabase.ts +0 -99
  431. package/src/sources/relation-lookup.test.ts +0 -99
  432. package/src/sources/relation-lookup.ts +0 -128
  433. package/src/sources/rest-adapters.test.ts +0 -95
  434. package/src/sources/rest-adapters.ts +0 -120
  435. package/src/sources/rest.test.ts +0 -104
  436. package/src/sources/rest.ts +0 -129
  437. package/src/sources/schema-from-columns.test.ts +0 -106
  438. package/src/sources/schema-from-columns.ts +0 -88
  439. package/src/sources/supabase.test.ts +0 -110
  440. package/src/sources/supabase.ts +0 -99
  441. package/src/sources/with-entity-rules.test.ts +0 -104
  442. package/src/sources/with-entity-rules.ts +0 -78
  443. package/src/sources/with-relation-labels.test.ts +0 -75
  444. package/src/sources/with-relation-labels.ts +0 -73
  445. package/src/staged-editing.ts +0 -0
  446. package/src/studio/bug-report.test.ts +0 -101
  447. package/src/studio/bug-report.ts +0 -165
  448. package/src/studio/cli.test.ts +0 -187
  449. package/src/studio/cli.ts +0 -117
  450. package/src/studio/copilot-core.test.ts +0 -45
  451. package/src/studio/csv.test.ts +0 -90
  452. package/src/studio/csv.ts +0 -165
  453. package/src/studio/db-connect-string.test.ts +0 -94
  454. package/src/studio/db-connect-string.ts +0 -128
  455. package/src/studio/deploy-cli.test.ts +0 -56
  456. package/src/studio/deploy-cli.ts +0 -100
  457. package/src/studio/emit-project.test.ts +0 -3324
  458. package/src/studio/emit-project.ts +0 -5377
  459. package/src/studio/emit-schema.test.ts +0 -111
  460. package/src/studio/emit-schema.ts +0 -1181
  461. package/src/studio/index.ts +0 -380
  462. package/src/studio/init-flow.test.ts +0 -514
  463. package/src/studio/init-flow.ts +0 -556
  464. package/src/studio/introspect-db.test.ts +0 -186
  465. package/src/studio/introspect-db.ts +0 -312
  466. package/src/studio/introspect-openapi.test.ts +0 -84
  467. package/src/studio/introspect-openapi.ts +0 -252
  468. package/src/studio/introspect-prisma.test.ts +0 -99
  469. package/src/studio/introspect-prisma.ts +0 -175
  470. package/src/studio/introspect.test.ts +0 -172
  471. package/src/studio/introspect.ts +0 -310
  472. package/src/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -1
  473. package/src/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -3
  474. package/src/studio/pipeline.test.ts +0 -42
  475. package/src/studio/project-robust.test.ts +0 -157
  476. package/src/studio/project.test.ts +0 -929
  477. package/src/studio/project.ts +0 -2394
  478. package/src/studio/sample-data.test.ts +0 -58
  479. package/src/studio/sample-data.ts +0 -203
  480. package/src/studio/samples/ats.ts +0 -202
  481. package/src/studio/samples/clinic.ts +0 -179
  482. package/src/studio/samples/crm.ts +0 -291
  483. package/src/studio/samples/datasets.test.ts +0 -84
  484. package/src/studio/samples/datasets.ts +0 -340
  485. package/src/studio/samples/ecommerce.ts +0 -187
  486. package/src/studio/samples/events.ts +0 -201
  487. package/src/studio/samples/fleet.ts +0 -213
  488. package/src/studio/samples/gym.ts +0 -215
  489. package/src/studio/samples/hr.ts +0 -195
  490. package/src/studio/samples/index.ts +0 -55
  491. package/src/studio/samples/insurance.ts +0 -229
  492. package/src/studio/samples/inventory.ts +0 -213
  493. package/src/studio/samples/invoicing.ts +0 -162
  494. package/src/studio/samples/library.ts +0 -180
  495. package/src/studio/samples/live-data.test.ts +0 -99
  496. package/src/studio/samples/live-data.ts +0 -306
  497. package/src/studio/samples/projects.ts +0 -212
  498. package/src/studio/samples/realestate.ts +0 -196
  499. package/src/studio/samples/restaurant.ts +0 -189
  500. package/src/studio/samples/samples.test.ts +0 -304
  501. package/src/studio/samples/school.ts +0 -197
  502. package/src/studio/samples/seed-floor.test.ts +0 -25
  503. package/src/studio/samples/shared.ts +0 -237
  504. package/src/studio/samples/starter.ts +0 -251
  505. package/src/studio/samples/subscriptions.ts +0 -183
  506. package/src/studio/samples/support.ts +0 -216
  507. package/src/studio/scaffold-app.test.ts +0 -91
  508. package/src/studio/scaffold.test.ts +0 -192
  509. package/src/studio/scaffold.ts +0 -390
  510. package/src/studio/screen-suites.test.ts +0 -269
  511. package/src/studio/screen-suites.ts +0 -448
  512. package/src/studio/themes.ts +0 -62
  513. package/src/studio/ui-components-surface.test.ts +0 -185
  514. package/src/studio/ui-components.generated.ts +0 -7154
  515. package/src/studio/ui-components.ts +0 -742
  516. package/src/studio/verify.test.ts +0 -47
  517. package/src/studio/verify.ts +0 -79
  518. package/src/sveltekit/in-memory.test.ts +0 -104
  519. package/src/sveltekit/in-memory.ts +0 -129
  520. package/src/sveltekit/index.ts +0 -24
  521. package/src/sveltekit/query-plan.test.ts +0 -109
  522. package/src/sveltekit/query-plan.ts +0 -125
  523. package/src/sveltekit/sql-source.test.ts +0 -198
  524. package/src/sveltekit/sql-source.ts +0 -171
  525. package/src/sveltekit/sql.test.ts +0 -80
  526. package/src/sveltekit/sql.ts +0 -131
  527. package/src/sveltekit/transport-scope.test.ts +0 -125
  528. package/src/sveltekit/transport.test.ts +0 -201
  529. package/src/sveltekit/transport.ts +0 -373
  530. package/src/upgrade-prompt.test.ts +0 -71
  531. package/src/upgrade-prompt.ts +0 -162
  532. package/src/version.test.ts +0 -17
  533. package/src/watermark.test.ts +0 -97
  534. package/src/watermark.ts +0 -156
  535. /package/{src → dist}/SvAlertRuleEditor.svelte +0 -0
  536. /package/{src → dist}/SvAlertsManager.svelte +0 -0
  537. /package/{src → dist}/SvAlertsPanel.svelte +0 -0
  538. /package/{src → dist}/SvAuthGate.svelte +0 -0
  539. /package/{src → dist}/SvBoard.svelte +0 -0
  540. /package/{src → dist}/SvExportMenu.svelte +0 -0
  541. /package/{src → dist}/SvExpressionEditor.svelte +0 -0
  542. /package/{src → dist}/SvFileInput.svelte +0 -0
  543. /package/{src → dist}/SvGridAlerts.svelte +0 -0
  544. /package/{src → dist}/SvGridBoard.svelte +0 -0
  545. /package/{src → dist}/SvGridEditPanel.svelte +0 -0
  546. /package/{src → dist}/SvGridMasterDetail.svelte +0 -0
  547. /package/{src → dist}/SvGridScheduler.svelte +0 -0
  548. /package/{src → dist}/SvImportDialog.svelte +0 -0
  549. /package/{src → dist}/SvLookupInput.svelte +0 -0
  550. /package/{src → dist}/SvPivotDesigner.svelte +0 -0
  551. /package/{src → dist}/SvRecordDetail.svelte +0 -0
  552. /package/{src → dist}/SvSchedule.svelte +0 -0
  553. /package/{src → dist}/SvSchemaChart.svelte +0 -0
  554. /package/{src → dist}/SvSchemaDashboard.svelte +0 -0
  555. /package/{src → dist}/pdfmake-shims.d.ts +0 -0
  556. /package/{src → dist}/smart.export.d.ts +0 -0
  557. /package/{src → dist}/smart.export.js +0 -0
  558. /package/{src → dist}/studio/HANDLERS-DESIGN.md +0 -0
  559. /package/{src → dist/studio}/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/_svelte_metadata.json +0 -0
  560. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/_metadata.json +0 -0
  561. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js +0 -0
  562. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/attachments-BOv1rBKp.js.map +0 -0
  563. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js +0 -0
  564. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/constants-B9vgIdCd.js.map +0 -0
  565. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js +0 -0
  566. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/dev-T1qbW_qD.js.map +0 -0
  567. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js +0 -0
  568. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/events-Bo11SfVK.js.map +0 -0
  569. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js +0 -0
  570. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/flags-X7D4vfrZ.js.map +0 -0
  571. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js +0 -0
  572. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/hydration-oyUje5i1.js.map +0 -0
  573. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js +0 -0
  574. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/legacy-client-DeSQgSFm.js.map +0 -0
  575. /package/{src → dist/studio}/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/package.json +0 -0
  576. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js +0 -0
  577. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte.js.map +0 -0
  578. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js +0 -0
  579. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_animate.js.map +0 -0
  580. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_attachments.js +0 -0
  581. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js +0 -0
  582. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_compiler.js.map +0 -0
  583. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js +0 -0
  584. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_easing.js.map +0 -0
  585. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_events.js +0 -0
  586. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js +0 -0
  587. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal.js.map +0 -0
  588. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_client.js +0 -0
  589. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js +0 -0
  590. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_disclose-version.js.map +0 -0
  591. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js +0 -0
  592. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_async.js.map +0 -0
  593. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js +0 -0
  594. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_legacy.js.map +0 -0
  595. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js +0 -0
  596. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_flags_tracing.js.map +0 -0
  597. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_internal_server.js +0 -0
  598. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js +0 -0
  599. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_legacy.js.map +0 -0
  600. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js +0 -0
  601. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_motion.js.map +0 -0
  602. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js +0 -0
  603. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity.js.map +0 -0
  604. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js +0 -0
  605. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_reactivity_window.js.map +0 -0
  606. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_server.js +0 -0
  607. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js +0 -0
  608. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_store.js.map +0 -0
  609. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js +0 -0
  610. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/svelte_transition.js.map +0 -0
  611. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js +0 -0
  612. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-BbWyXNk1.js.map +0 -0
  613. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js +0 -0
  614. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/utils-DI_fC7vt.js.map +0 -0
  615. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js +0 -0
  616. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/validate-Dyr3lQv9.js.map +0 -0
  617. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js +0 -0
  618. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/version-_9FHH-LF.js.map +0 -0
  619. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js +0 -0
  620. /package/{src → dist}/studio/node_modules/.vite/vitest/be65d27ae088a0e03fd8e1331d90b01649464cb6/deps___vitest__/warnings-CUbSPnyP.js.map +0 -0
package/src/import.ts DELETED
@@ -1,1044 +0,0 @@
1
- /**
2
- * Pro Import feature
3
- * ------------------
4
- *
5
- * Read Excel (.xlsx), CSV, TSV, or JSON in the browser and produce a typed
6
- * preview of the parsed rows, including per-cell validation errors. The
7
- * caller decides whether to commit the parsed rows into the grid via
8
- * `api.addRows(...)`, or to render an editing modal so the user can fix
9
- * issues first.
10
- *
11
- * Two flavours of usage:
12
- *
13
- * 1. Read + preview, then commit explicitly:
14
- *
15
- * const result = await api.importData({ file, format: 'auto' })
16
- * // result.headers, result.rows, result.errors
17
- * if (result.errors.length === 0) api.addRows(result.rows, 'bottom')
18
- *
19
- * 2. Read and commit in one go (no preview UX):
20
- *
21
- * await api.importData({ file, format: 'auto', commit: true })
22
- *
23
- * Both go through the same polite license soft-gate as `exportData` and
24
- * `print`, so unlicensed evaluation works but emits a one-time nudge.
25
- */
26
-
27
- import type { RowData, SvGridApi, TableFeatures } from '@svgrid/grid'
28
- import { assertEnterpriseLicensed } from './license'
29
-
30
- // ---------------------------------------------------------------------------
31
- // Public types
32
- // ---------------------------------------------------------------------------
33
-
34
- export type ImportFormat = 'xlsx' | 'csv' | 'tsv' | 'json' | 'auto'
35
-
36
- export type ImportColumnMap = Record<string, string>
37
-
38
- /**
39
- * Declared data type per target field. When `columnTypes` is set on
40
- * `ImportOptions`, the parser tries to coerce each non-empty cell into
41
- * the declared shape and emits an `ImportRowError` when it can't -
42
- * stricter than the ad-hoc "looks like a number" fallback.
43
- */
44
- export type ImportFieldType =
45
- | 'string'
46
- | 'number'
47
- | 'integer'
48
- | 'boolean'
49
- | 'date' // returns ISO yyyy-mm-dd
50
- | 'datetime' // returns ISO yyyy-mm-ddThh:mm:ss
51
- | 'json' // parses the cell as JSON (object / array / primitive)
52
-
53
- export type ImportColumnTypes = Record<string, ImportFieldType>
54
-
55
- /**
56
- * The slice of a grid column the auto-mapper needs: its target `field`,
57
- * a human `header` to match source headers against, and the `format`
58
- * config to infer a column type from. Shaped to accept the output of
59
- * `api.getColumns()` directly.
60
- */
61
- export type ImportGridColumn = {
62
- field?: string
63
- header?: string
64
- format?: { type?: string } | null
65
- }
66
-
67
- /** Progress ticks emitted during a large import so a UI can show a bar. */
68
- export type ImportProgress = {
69
- /** Which stage is running. */
70
- phase: 'parse' | 'map'
71
- /** 0..1 completion of the current phase. */
72
- ratio: number
73
- /** Rows processed so far in this phase. */
74
- done: number
75
- /** Total rows this phase will process (0 when unknown, e.g. mid-parse). */
76
- total: number
77
- }
78
-
79
- export type ImportRowError = {
80
- /** 0-based row index in the SOURCE file (excluding the header). */
81
- rowIndex: number
82
- /** Target field name (the grid's column field), or '*' for whole-row errors. */
83
- field: string
84
- message: string
85
- }
86
-
87
- export type ImportValidator<TData> = (
88
- row: TData,
89
- rowIndex: number,
90
- ) => Array<{ field: string; message: string }>
91
-
92
- export type ImportOptions<TData> = {
93
- /** The file to read. A `File`/`Blob` works for xlsx; a string is treated as
94
- * inline CSV/TSV/JSON text. */
95
- file: File | Blob | string
96
- /** When 'auto', the format is sniffed from `file.name`'s extension (Files
97
- * only), otherwise the function inspects the first characters of the
98
- * text payload. */
99
- format?: ImportFormat
100
- /**
101
- * Map source-header -> target-field. Missing entries fall back to the
102
- * source header verbatim (lowercased + trimmed). Pass `null` for a
103
- * source header you want to drop on the floor.
104
- */
105
- columnMap?: ImportColumnMap
106
- /**
107
- * Declared data types per target field. When set, the importer uses
108
- * strict per-type coercion (`'2024-03-15'` -> ISO date; `'$1,234'`
109
- * -> 1234 for `number` fields) and emits an `ImportRowError` whenever
110
- * a value can't be coerced. Fields not listed fall back to the
111
- * built-in best-effort coercion (currency / number / date sniffing
112
- * by value shape).
113
- */
114
- columnTypes?: ImportColumnTypes
115
- /** Per-row validator. Returned errors land in `result.errors`. */
116
- validator?: ImportValidator<TData>
117
- /**
118
- * When true, source headers are fuzzy-matched to the grid's own columns
119
- * (by header label or field name) to build the `columnMap` automatically,
120
- * and `columnTypes` are inferred from each matched column's `format`
121
- * (currency / number / percent -> number, date -> date, datetime ->
122
- * datetime). Anything you pass explicitly in `columnMap` / `columnTypes`
123
- * wins over the guess. This is what powers "drop a file and it lines up
124
- * with my grid" in `SvImportDialog`.
125
- */
126
- autoMap?: boolean
127
- /** When true, the parsed rows are appended to the grid via
128
- * `api.addRows(...)` automatically. Defaults to false (preview mode). */
129
- commit?: boolean
130
- /** Where to insert when `commit` is true. Defaults to 'bottom'. */
131
- commitAt?: 'top' | 'bottom' | number
132
- /**
133
- * Drop duplicate rows by this key field, keeping the LAST occurrence
134
- * (upsert-style, so a later row in the file wins). Runs after mapping,
135
- * so pass the TARGET field name. Rows with a null/undefined key are kept.
136
- */
137
- dedupeBy?: keyof TData | (string & {})
138
- // --- Enterprise guard-rails ----------------------------------------------
139
- /** Reject the import if the source has more than this many data rows.
140
- * Guards against a runaway upload locking up the tab. */
141
- maxRows?: number
142
- /**
143
- * What to do when the source exceeds `maxRows`. `'reject'` (default)
144
- * throws so no data is silently lost; `'truncate'` keeps the first
145
- * `maxRows` rows and sets `result.truncated` so you can warn the user.
146
- * Only affects `maxRows` - `maxBytes` always rejects (a partial binary /
147
- * CSV can't be truncated safely).
148
- */
149
- overLimit?: 'reject' | 'truncate'
150
- /** Reject a File/Blob larger than this many bytes before it is read. */
151
- maxBytes?: number
152
- /** Stop collecting validation errors past this many (keeps memory bounded
153
- * on a pathological file). `result.errorsTruncated` flags when it hit. */
154
- maxErrors?: number
155
- /** Text encoding for CSV/TSV/JSON read from a File/Blob. Default 'utf-8'.
156
- * Set e.g. 'windows-1252' / 'latin1' for legacy Excel CSV exports. */
157
- encoding?: string
158
- /** Abort a long parse/map (wire to an AbortController). Throws an
159
- * AbortError, matching the export API. */
160
- signal?: AbortSignal
161
- /** Progress callback for large files (parse + map phases). */
162
- onProgress?: (progress: ImportProgress) => void
163
- }
164
-
165
- export type ImportResult<TData> = {
166
- /** Source headers as found in the file, in their original order. */
167
- headers: string[]
168
- /** Parsed + mapped rows. Order matches the source. */
169
- rows: TData[]
170
- /** All validation errors (zero-length if the file passed clean). */
171
- errors: ImportRowError[]
172
- /** Rows skipped because they were entirely blank. */
173
- skipped: number
174
- /** Total source rows the parser saw (including blanks and bad rows). */
175
- total: number
176
- /** Detected format (resolved from 'auto'). */
177
- format: Exclude<ImportFormat, 'auto'>
178
- /** True when `maxErrors` capped the error list (there were more). */
179
- errorsTruncated?: boolean
180
- /** Rows dropped by `dedupeBy` (0 when not deduping). */
181
- deduped?: number
182
- /** True when `maxRows` + `overLimit:'truncate'` dropped trailing rows.
183
- * `total` still reports the original source row count. */
184
- truncated?: boolean
185
- }
186
-
187
- // ---------------------------------------------------------------------------
188
- // Lazy peer dependency: jszip (xlsx only)
189
- // ---------------------------------------------------------------------------
190
-
191
- let jszipPromise: Promise<unknown> | null = null
192
- async function getJSZip(): Promise<any> {
193
- if (typeof window === 'undefined') {
194
- throw new Error('@svgrid/enterprise: importData requires a browser environment')
195
- }
196
- const g = globalThis as unknown as { JSZip?: unknown }
197
- if (g.JSZip) return g.JSZip
198
- if (!jszipPromise) {
199
- jszipPromise = (async () => {
200
- let mod: unknown
201
- try {
202
- // Optional peer, loaded on demand (keeps consumer type-checks clean when absent).
203
- // @ts-ignore - "jszip" is an optional peerDependency
204
- mod = await import('jszip')
205
- } catch {
206
- throw new Error(
207
- '@svgrid/enterprise: xlsx import requires the "jszip" peer dependency. ' +
208
- 'Install it with: pnpm add jszip',
209
- )
210
- }
211
- const J = (mod as { default?: unknown }).default ?? mod
212
- g.JSZip = J
213
- return J
214
- })()
215
- }
216
- return jszipPromise
217
- }
218
-
219
- // ---------------------------------------------------------------------------
220
- // Format sniffing
221
- // ---------------------------------------------------------------------------
222
-
223
- function sniffFormat(
224
- file: File | Blob | string,
225
- declared: ImportFormat,
226
- ): Exclude<ImportFormat, 'auto'> {
227
- if (declared !== 'auto') return declared
228
- // File: trust the extension.
229
- if (file instanceof File && file.name) {
230
- const ext = file.name.toLowerCase().split('.').pop() ?? ''
231
- if (ext === 'xlsx') return 'xlsx'
232
- if (ext === 'csv') return 'csv'
233
- if (ext === 'tsv' || ext === 'tab') return 'tsv'
234
- if (ext === 'json') return 'json'
235
- }
236
- // String: sniff the first non-whitespace char.
237
- if (typeof file === 'string') {
238
- const trimmed = file.trimStart()
239
- if (trimmed.startsWith('[') || trimmed.startsWith('{')) return 'json'
240
- // Tab-rich heads are tsv; otherwise default to csv.
241
- const firstLine = trimmed.slice(0, 200).split(/\r?\n/)[0] ?? ''
242
- if ((firstLine.match(/\t/g)?.length ?? 0) >= 1) return 'tsv'
243
- return 'csv'
244
- }
245
- // Blob without a filename / extension: assume xlsx (the most common case
246
- // the importer is asked to handle).
247
- return 'xlsx'
248
- }
249
-
250
- // ---------------------------------------------------------------------------
251
- // CSV / TSV parser
252
- // ---------------------------------------------------------------------------
253
-
254
- /**
255
- * RFC 4180-flavour CSV / TSV parser. Handles:
256
- * - quoted fields with embedded commas / tabs / newlines
257
- * - escaped quotes ("") inside quoted fields
258
- * - both \r\n and \n line endings
259
- *
260
- * Doesn't aim to be the world's fastest parser - it walks the string
261
- * character-by-character. For files in the 10-100k row range this is
262
- * fine; for million-row imports, do the import server-side.
263
- */
264
- function parseDelimited(text: string, sep: ',' | '\t'): string[][] {
265
- const rows: string[][] = []
266
- let row: string[] = []
267
- let field = ''
268
- let i = 0
269
- let inQuotes = false
270
- // Strip a UTF-8 BOM if present so the first header isn't named "ID".
271
- if (text.charCodeAt(0) === 0xfeff) i = 1
272
- while (i < text.length) {
273
- const c = text[i]!
274
- if (inQuotes) {
275
- if (c === '"') {
276
- if (text[i + 1] === '"') { field += '"'; i += 2; continue }
277
- inQuotes = false
278
- i += 1
279
- continue
280
- }
281
- field += c
282
- i += 1
283
- continue
284
- }
285
- if (c === '"') { inQuotes = true; i += 1; continue }
286
- if (c === sep) { row.push(field); field = ''; i += 1; continue }
287
- if (c === '\r') {
288
- if (text[i + 1] === '\n') i += 1
289
- row.push(field); rows.push(row); row = []; field = ''; i += 1; continue
290
- }
291
- if (c === '\n') {
292
- row.push(field); rows.push(row); row = []; field = ''; i += 1; continue
293
- }
294
- field += c
295
- i += 1
296
- }
297
- // Flush the trailing field / row (no trailing newline).
298
- if (field.length > 0 || row.length > 0) {
299
- row.push(field)
300
- rows.push(row)
301
- }
302
- return rows
303
- }
304
-
305
- // ---------------------------------------------------------------------------
306
- // XLSX parser (minimal)
307
- // ---------------------------------------------------------------------------
308
-
309
- /**
310
- * Minimal SpreadsheetML reader. Supports the .xlsx shape Excel and Google
311
- * Sheets produce by default: one default sheet, optional shared-strings
312
- * table, inline strings, numbers, and dates expressed as serial numbers.
313
- *
314
- * The grid does NOT try to be a fully-featured Excel reader. Formulas
315
- * are read as their cached value when present. Multi-sheet imports
316
- * require the caller to pre-extract the desired sheet (or for a future
317
- * release).
318
- */
319
- async function parseXlsx(file: File | Blob): Promise<string[][]> {
320
- const J = await getJSZip()
321
- const buf = await (file as Blob).arrayBuffer()
322
- const zip = await J.loadAsync(buf)
323
-
324
- // Read sharedStrings.xml if it exists.
325
- let sharedStrings: string[] = []
326
- const ssEntry = zip.file('xl/sharedStrings.xml')
327
- if (ssEntry) {
328
- const ssText = await ssEntry.async('string')
329
- sharedStrings = parseSharedStrings(ssText)
330
- }
331
-
332
- // Read the FIRST sheet. Workbook.xml -> rels mapping is involved; for the
333
- // 99% case the first sheet lives at xl/worksheets/sheet1.xml.
334
- const sheetEntry =
335
- zip.file('xl/worksheets/sheet1.xml') ??
336
- zip.file('xl/worksheets/sheet 1.xml')
337
- if (!sheetEntry) {
338
- throw new Error(
339
- '@svgrid/enterprise: could not locate sheet1.xml in the .xlsx archive',
340
- )
341
- }
342
- const sheetText = await sheetEntry.async('string')
343
- return parseSheetXml(sheetText, sharedStrings)
344
- }
345
-
346
- /** Pull every `<t>...</t>` out of sharedStrings.xml in document order. */
347
- function parseSharedStrings(xml: string): string[] {
348
- const out: string[] = []
349
- // A shared-string item may be a plain <si><t>X</t></si> or a rich-text
350
- // <si><r><t>X</t></r><r><t>Y</t></r></si>. Concatenate every <t> inside
351
- // each <si>.
352
- const itemRe = /<si\b[^>]*>([\s\S]*?)<\/si>/g
353
- const tRe = /<t\b[^>]*>([\s\S]*?)<\/t>/g
354
- let m: RegExpExecArray | null
355
- while ((m = itemRe.exec(xml)) !== null) {
356
- let combined = ''
357
- let n: RegExpExecArray | null
358
- tRe.lastIndex = 0
359
- while ((n = tRe.exec(m[1] ?? '')) !== null) {
360
- combined += decodeXmlEntities(n[1] ?? '')
361
- }
362
- out.push(combined)
363
- }
364
- return out
365
- }
366
-
367
- function decodeXmlEntities(s: string): string {
368
- return s
369
- .replace(/&amp;/g, '&')
370
- .replace(/&lt;/g, '<')
371
- .replace(/&gt;/g, '>')
372
- .replace(/&quot;/g, '"')
373
- .replace(/&apos;/g, "'")
374
- .replace(/&#10;/g, '\n')
375
- .replace(/&#9;/g, '\t')
376
- }
377
-
378
- /**
379
- * Convert a sheet's XML body into a dense `string[][]`. Holes in the
380
- * cell stream (e.g. row jumps from col B to col E) are filled with
381
- * empty strings so the result is rectangular.
382
- */
383
- function parseSheetXml(xml: string, sharedStrings: string[]): string[][] {
384
- const rows: string[][] = []
385
- const rowRe = /<row\b[^>]*>([\s\S]*?)<\/row>/g
386
- const cellRe = /<c\b([^>]*)>([\s\S]*?)<\/c>/g
387
- const inlineStrRe = /<is>\s*([\s\S]*?)\s*<\/is>/
388
- const tRe = /<t\b[^>]*>([\s\S]*?)<\/t>/g
389
- const vRe = /<v>([\s\S]*?)<\/v>/
390
- let rowMatch: RegExpExecArray | null
391
- while ((rowMatch = rowRe.exec(xml)) !== null) {
392
- const rowBody = rowMatch[1] ?? ''
393
- const cells: string[] = []
394
- let cellMatch: RegExpExecArray | null
395
- cellRe.lastIndex = 0
396
- while ((cellMatch = cellRe.exec(rowBody)) !== null) {
397
- const attrs = cellMatch[1] ?? ''
398
- const body = cellMatch[2] ?? ''
399
- const ref = /r="([A-Z]+)\d+"/.exec(attrs)?.[1] ?? ''
400
- const colIndex = colRefToIndex(ref)
401
- const type = /t="([^"]+)"/.exec(attrs)?.[1] ?? 'n'
402
- // Pad holes with empty strings so column alignment survives.
403
- while (cells.length < colIndex) cells.push('')
404
- let value = ''
405
- if (type === 's') {
406
- const idx = Number(vRe.exec(body)?.[1] ?? '-1')
407
- value = sharedStrings[idx] ?? ''
408
- } else if (type === 'inlineStr' || type === 'str') {
409
- const inlineBody = inlineStrRe.exec(body)?.[1] ?? body
410
- let parts = ''
411
- let n: RegExpExecArray | null
412
- tRe.lastIndex = 0
413
- while ((n = tRe.exec(inlineBody)) !== null) parts += decodeXmlEntities(n[1] ?? '')
414
- value = parts || decodeXmlEntities(vRe.exec(body)?.[1] ?? '')
415
- } else if (type === 'b') {
416
- value = vRe.exec(body)?.[1] === '1' ? 'true' : 'false'
417
- } else {
418
- // Numeric or date - we surface as the raw number string. The
419
- // caller's column type then handles parsing.
420
- value = decodeXmlEntities(vRe.exec(body)?.[1] ?? '')
421
- }
422
- cells.push(value)
423
- }
424
- rows.push(cells)
425
- }
426
- return rows
427
- }
428
-
429
- /** Excel column reference ("A", "B", ..., "AA", ...) to a zero-based index. */
430
- function colRefToIndex(ref: string): number {
431
- if (!ref) return 0
432
- let n = 0
433
- for (let i = 0; i < ref.length; i += 1) {
434
- n = n * 26 + (ref.charCodeAt(i) - 64)
435
- }
436
- return Math.max(0, n - 1)
437
- }
438
-
439
- // ---------------------------------------------------------------------------
440
- // Coerce raw string values into typed JS values based on a sample of other
441
- // values in the same column. We don't ask the consumer for a schema - it
442
- // would defeat the "drop a file in and go" UX - but we DO want
443
- // "$1,234.56" to become 1234.56 and "true" to become true.
444
- // ---------------------------------------------------------------------------
445
-
446
- function inferAndCoerce(value: string): unknown {
447
- if (value === '') return ''
448
- const trimmed = value.trim()
449
- if (trimmed === '') return ''
450
- // Boolean
451
- if (trimmed === 'true' || trimmed === 'TRUE') return true
452
- if (trimmed === 'false' || trimmed === 'FALSE') return false
453
- // Currency / number with grouping. Strip $, commas, whitespace.
454
- if (/^[-+]?\$?\s?[\d,]+(?:\.\d+)?$/.test(trimmed)) {
455
- const n = parseFloat(trimmed.replace(/[$,\s]/g, ''))
456
- if (!Number.isNaN(n)) return n
457
- }
458
- // Bare integer / float
459
- if (/^[-+]?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(trimmed)) {
460
- const n = parseFloat(trimmed)
461
- if (!Number.isNaN(n)) return n
462
- }
463
- // ISO date (yyyy-mm-dd, optionally with time) -> keep as ISO string. We
464
- // don't return a Date because most grid columns prefer strings on the
465
- // wire (sort + filter + format paths are already date-aware).
466
- if (/^\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:?\d{2})?)?$/.test(trimmed)) {
467
- return trimmed
468
- }
469
- return trimmed
470
- }
471
-
472
- // ---------------------------------------------------------------------------
473
- // Map source rows -> typed records.
474
- // ---------------------------------------------------------------------------
475
-
476
- /**
477
- * Field names we refuse to write, because assigning them from untrusted file
478
- * headers would let a malicious upload walk the prototype chain (prototype
479
- * pollution). Applies to the default snake_case fallback AND anything a
480
- * columnMap points at.
481
- */
482
- const UNSAFE_FIELDS = new Set(['__proto__', 'prototype', 'constructor'])
483
-
484
- /** Resolve each source header to a target field (or null = drop the column),
485
- * honouring the columnMap and refusing blank + pollution-prone names. */
486
- function computeFields(
487
- headers: string[],
488
- columnMap: ImportColumnMap | undefined,
489
- ): Array<string | null> {
490
- return headers.map((h) => {
491
- let field: string | null
492
- if (columnMap && Object.prototype.hasOwnProperty.call(columnMap, h)) {
493
- field = columnMap[h] ?? null
494
- } else {
495
- field = h.toLowerCase().replace(/\s+/g, '_').replace(/[^a-z0-9_]/g, '')
496
- }
497
- if (field == null || field === '' || UNSAFE_FIELDS.has(field)) return null
498
- return field
499
- })
500
- }
501
-
502
- /** Build one typed record from a row of cells. Pure; no side effects on the
503
- * shared error list (returns its own). */
504
- function buildRecord(
505
- cells: string[],
506
- headerCount: number,
507
- fields: Array<string | null>,
508
- columnTypes: ImportColumnTypes | undefined,
509
- outRowIndex: number,
510
- ): { rec: Record<string, unknown>; errors: ImportRowError[] } {
511
- const rec: Record<string, unknown> = {}
512
- const errors: ImportRowError[] = []
513
- for (let i = 0; i < headerCount; i += 1) {
514
- const field = fields[i]
515
- if (field == null) continue
516
- const raw = cells[i] ?? ''
517
- const declaredType = columnTypes?.[field]
518
- if (declaredType) {
519
- const result = coerceTyped(raw, declaredType)
520
- if (result.ok) {
521
- rec[field] = result.value
522
- } else {
523
- errors.push({ rowIndex: outRowIndex, field, message: result.message })
524
- // Park the raw string so downstream code still sees SOMETHING.
525
- rec[field] = raw
526
- }
527
- } else {
528
- rec[field] = inferAndCoerce(raw)
529
- }
530
- }
531
- return { rec, errors }
532
- }
533
-
534
- /** Push `source` errors into `target`, stopping at `maxErrors`. Returns true
535
- * when it had to truncate. */
536
- function collectErrors(
537
- target: ImportRowError[],
538
- source: ImportRowError[],
539
- maxErrors: number | undefined,
540
- ): boolean {
541
- for (const e of source) {
542
- if (maxErrors != null && target.length >= maxErrors) return true
543
- target.push(e)
544
- }
545
- return false
546
- }
547
-
548
- /** Drop duplicate rows by `key`, keeping the last occurrence in place. */
549
- function dedupeRows<TData>(rows: TData[], key: string): { rows: TData[]; deduped: number } {
550
- const idx = new Map<unknown, number>()
551
- const out: TData[] = []
552
- for (const r of rows) {
553
- const k = (r as Record<string, unknown>)?.[key]
554
- if (k == null) { out.push(r); continue }
555
- const at = idx.get(k)
556
- if (at !== undefined) out[at] = r
557
- else { idx.set(k, out.length); out.push(r) }
558
- }
559
- return { rows: out, deduped: rows.length - out.length }
560
- }
561
-
562
- function isBlankRow(cells: string[]): boolean {
563
- return cells.every((c) => c === undefined || c.trim() === '')
564
- }
565
-
566
- function abortError(): Error {
567
- const e = new Error('@svgrid/enterprise: import cancelled')
568
- e.name = 'AbortError'
569
- return e
570
- }
571
-
572
- /** Yield to the event loop so a long map doesn't block paint / input. */
573
- function nextTick(): Promise<void> {
574
- return new Promise((resolve) => setTimeout(resolve, 0))
575
- }
576
-
577
- function buildRecords<TData>(
578
- matrix: string[][],
579
- columnMap: ImportColumnMap | undefined,
580
- columnTypes: ImportColumnTypes | undefined,
581
- maxErrors?: number,
582
- ): { headers: string[]; rows: TData[]; skipped: number; errors: ImportRowError[]; errorsTruncated: boolean } {
583
- if (matrix.length === 0) return { headers: [], rows: [], skipped: 0, errors: [], errorsTruncated: false }
584
- const headers = (matrix[0] ?? []).map((h) => h.trim())
585
- const fields = computeFields(headers, columnMap)
586
- const dataRows = matrix.slice(1)
587
- const out: TData[] = []
588
- const errors: ImportRowError[] = []
589
- let skipped = 0
590
- let errorsTruncated = false
591
- // Skipped (blank) rows don't count toward the output row index used
592
- // in errors, so the indices match what the consumer's preview UI shows.
593
- let outRowIndex = 0
594
- for (const cells of dataRows) {
595
- if (isBlankRow(cells)) { skipped += 1; continue }
596
- const { rec, errors: rowErrs } = buildRecord(cells, headers.length, fields, columnTypes, outRowIndex)
597
- if (rowErrs.length && collectErrors(errors, rowErrs, maxErrors)) errorsTruncated = true
598
- out.push(rec as unknown as TData)
599
- outRowIndex += 1
600
- }
601
- return { headers, rows: out, skipped, errors, errorsTruncated }
602
- }
603
-
604
- /**
605
- * Strict per-type coercion used when the consumer declares
606
- * `columnTypes`. Returns either `{ ok: true, value }` or
607
- * `{ ok: false, message }` describing why the value couldn't be
608
- * shaped into the declared type.
609
- *
610
- * Empty values for required types (number, date) error rather than
611
- * silently coerce to 0 / null - the consumer can drop the row in
612
- * their validator if blanks should be tolerated.
613
- */
614
- function coerceTyped(raw: string, type: ImportFieldType):
615
- | { ok: true; value: unknown }
616
- | { ok: false; message: string }
617
- {
618
- const trimmed = raw.trim()
619
- // Empty cells map to `null` for most types and the empty string for
620
- // `string` - this is the only case where typed import returns a
621
- // null. Validator step is the right place to insist on "required".
622
- if (trimmed === '') {
623
- if (type === 'string') return { ok: true, value: '' }
624
- return { ok: true, value: null }
625
- }
626
-
627
- switch (type) {
628
- case 'string':
629
- return { ok: true, value: trimmed }
630
-
631
- case 'boolean': {
632
- const low = trimmed.toLowerCase()
633
- if (low === 'true' || low === '1' || low === 'yes' || low === 'y') return { ok: true, value: true }
634
- if (low === 'false' || low === '0' || low === 'no' || low === 'n') return { ok: true, value: false }
635
- return { ok: false, message: `not a boolean: ${trimmed}` }
636
- }
637
-
638
- case 'number': {
639
- const stripped = trimmed.replace(/[$,\s]/g, '')
640
- const n = Number(stripped)
641
- if (!Number.isFinite(n)) return { ok: false, message: `not a number: ${trimmed}` }
642
- return { ok: true, value: n }
643
- }
644
-
645
- case 'integer': {
646
- const stripped = trimmed.replace(/[$,\s]/g, '')
647
- const n = Number(stripped)
648
- if (!Number.isFinite(n) || !Number.isInteger(n)) {
649
- return { ok: false, message: `not an integer: ${trimmed}` }
650
- }
651
- return { ok: true, value: n }
652
- }
653
-
654
- case 'date': {
655
- // Accept ISO dates and a handful of common day-first / month-first
656
- // shapes. Returns ISO yyyy-mm-dd.
657
- const iso = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})/)
658
- if (iso) return { ok: true, value: `${iso[1]}-${iso[2]}-${iso[3]}` }
659
- // mm/dd/yyyy or dd/mm/yyyy - we don't try to disambiguate; the
660
- // demo can declare the locale via its own validator if it cares.
661
- const slash = trimmed.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{4})/)
662
- if (slash) {
663
- const [, a, b, y] = slash
664
- // Default to mm/dd/yyyy because it's the dominant locale where
665
- // Excel exports without an explicit ISO format. Consumers
666
- // wanting EU-style can pre-normalise the file.
667
- return { ok: true, value: `${y}-${a!.padStart(2, '0')}-${b!.padStart(2, '0')}` }
668
- }
669
- const parsed = Date.parse(trimmed)
670
- if (!Number.isNaN(parsed)) {
671
- return { ok: true, value: new Date(parsed).toISOString().slice(0, 10) }
672
- }
673
- return { ok: false, message: `not a date: ${trimmed}` }
674
- }
675
-
676
- case 'datetime': {
677
- // Accept anything Date.parse handles.
678
- const parsed = Date.parse(trimmed)
679
- if (Number.isNaN(parsed)) return { ok: false, message: `not a datetime: ${trimmed}` }
680
- return { ok: true, value: new Date(parsed).toISOString().slice(0, 19) }
681
- }
682
-
683
- case 'json': {
684
- try {
685
- return { ok: true, value: JSON.parse(trimmed) }
686
- } catch {
687
- return { ok: false, message: `not valid JSON: ${trimmed.slice(0, 30)}...` }
688
- }
689
- }
690
- }
691
- }
692
-
693
- // ---------------------------------------------------------------------------
694
- // Parse-once + map, so a UI (SvImportDialog) can read a file ONCE and then
695
- // re-map / re-validate as the user tweaks the column mapping without paying
696
- // the parse (or unzip, for xlsx) cost on every keystroke.
697
- // ---------------------------------------------------------------------------
698
-
699
- /**
700
- * Read a file (or inline text) into a raw `string[][]` matrix - header row
701
- * first - without any mapping, coercion, or validation. The cheap half of
702
- * `importData`: parse the bytes once, then feed the matrix to
703
- * `mapImportMatrix` as many times as the mapping UI needs.
704
- */
705
- export async function readImportMatrix(
706
- file: File | Blob | string,
707
- format: ImportFormat = 'auto',
708
- opts: { maxBytes?: number; encoding?: string; signal?: AbortSignal } = {},
709
- ): Promise<{ format: Exclude<ImportFormat, 'auto'>; matrix: string[][] }> {
710
- if (opts.signal?.aborted) throw abortError()
711
- // Guard the byte size BEFORE reading, so an oversized upload never lands
712
- // in memory.
713
- if (opts.maxBytes != null && file instanceof Blob && file.size > opts.maxBytes) {
714
- throw new Error(
715
- `@svgrid/enterprise: file is ${file.size.toLocaleString()} bytes, ` +
716
- `over the ${opts.maxBytes.toLocaleString()}-byte import limit.`,
717
- )
718
- }
719
- const fmt = sniffFormat(file, format)
720
- let matrix: string[][]
721
- if (fmt === 'xlsx') {
722
- if (typeof file === 'string') {
723
- throw new Error(
724
- '@svgrid/enterprise: xlsx import expects a File or Blob, not a string. ' +
725
- 'Use format: "csv" or "tsv" for inline text.',
726
- )
727
- }
728
- matrix = await parseXlsx(file)
729
- } else if (fmt === 'json') {
730
- const text = typeof file === 'string' ? file : await readText(file, opts.encoding)
731
- matrix = jsonToMatrix(text)
732
- } else {
733
- const sep = fmt === 'tsv' ? '\t' : ','
734
- const text = typeof file === 'string' ? file : await readText(file, opts.encoding)
735
- matrix = parseDelimited(text, sep)
736
- }
737
- if (opts.signal?.aborted) throw abortError()
738
- return { format: fmt, matrix }
739
- }
740
-
741
- type MapMatrixOptions<TData> = {
742
- columnMap?: ImportColumnMap
743
- columnTypes?: ImportColumnTypes
744
- validator?: ImportValidator<TData>
745
- maxErrors?: number
746
- dedupeBy?: keyof TData | (string & {})
747
- }
748
-
749
- type MapMatrixResult<TData> = {
750
- headers: string[]
751
- rows: TData[]
752
- errors: ImportRowError[]
753
- skipped: number
754
- total: number
755
- errorsTruncated: boolean
756
- deduped: number
757
- }
758
-
759
- /** Run the validator over built rows, capping + flagging truncation. */
760
- function applyValidator<TData>(
761
- rows: TData[],
762
- errors: ImportRowError[],
763
- validator: ImportValidator<TData> | undefined,
764
- maxErrors: number | undefined,
765
- startIndex = 0,
766
- ): boolean {
767
- if (!validator) return false
768
- let truncated = false
769
- for (let i = startIndex; i < rows.length; i += 1) {
770
- const errs = validator(rows[i]!, i)
771
- if (errs.length) {
772
- const mapped = errs.map((e) => ({ rowIndex: i, field: e.field, message: e.message }))
773
- if (collectErrors(errors, mapped, maxErrors)) { truncated = true; break }
774
- }
775
- }
776
- return truncated
777
- }
778
-
779
- /**
780
- * Apply a column map + declared types + validator to an already-parsed
781
- * matrix. The pure, synchronous half of `importData` - no I/O, no license
782
- * gate - so a preview UI can call it on every mapping change. For very large
783
- * files prefer `mapImportMatrixAsync`, which yields to keep the UI live.
784
- */
785
- export function mapImportMatrix<TData extends RowData>(
786
- matrix: string[][],
787
- opts: MapMatrixOptions<TData> = {},
788
- ): MapMatrixResult<TData> {
789
- const built = buildRecords<TData>(matrix, opts.columnMap, opts.columnTypes, opts.maxErrors)
790
- const errors = built.errors
791
- // Type-coercion errors come first; the validator runs on the rows we
792
- // managed to build, so its errors share the same `rowIndex` basis.
793
- let errorsTruncated = built.errorsTruncated
794
- if (applyValidator(built.rows, errors, opts.validator, opts.maxErrors)) errorsTruncated = true
795
- let rows = built.rows
796
- let deduped = 0
797
- if (opts.dedupeBy) {
798
- const r = dedupeRows(rows, opts.dedupeBy as string)
799
- rows = r.rows
800
- deduped = r.deduped
801
- }
802
- return {
803
- headers: built.headers,
804
- rows,
805
- errors,
806
- skipped: built.skipped,
807
- total: matrix.length > 0 ? matrix.length - 1 : 0,
808
- errorsTruncated,
809
- deduped,
810
- }
811
- }
812
-
813
- /**
814
- * Non-blocking sibling of `mapImportMatrix`: yields to the event loop every
815
- * few thousand rows and reports progress, so mapping a 100k-row file never
816
- * freezes the tab. Honors an AbortSignal. Used by `importData` and the
817
- * SvImportDialog preview.
818
- */
819
- export async function mapImportMatrixAsync<TData extends RowData>(
820
- matrix: string[][],
821
- opts: MapMatrixOptions<TData> & {
822
- signal?: AbortSignal
823
- onProgress?: (progress: ImportProgress) => void
824
- /** Rows per chunk before yielding. Default 5000. */
825
- chunkSize?: number
826
- } = {},
827
- ): Promise<MapMatrixResult<TData>> {
828
- const headers = (matrix[0] ?? []).map((h) => h.trim())
829
- const fields = computeFields(headers, opts.columnMap)
830
- const dataRows = matrix.slice(1)
831
- const total = dataRows.length
832
- const chunk = Math.max(1, opts.chunkSize ?? 5000)
833
- const rows: TData[] = []
834
- const errors: ImportRowError[] = []
835
- let skipped = 0
836
- let outRowIndex = 0
837
- let errorsTruncated = false
838
-
839
- for (let i = 0; i < total; i += 1) {
840
- if (opts.signal?.aborted) throw abortError()
841
- const cells = dataRows[i]!
842
- if (isBlankRow(cells)) { skipped += 1 } else {
843
- const { rec, errors: rowErrs } = buildRecord(cells, headers.length, fields, opts.columnTypes, outRowIndex)
844
- if (rowErrs.length && collectErrors(errors, rowErrs, opts.maxErrors)) errorsTruncated = true
845
- rows.push(rec as unknown as TData)
846
- outRowIndex += 1
847
- }
848
- if ((i + 1) % chunk === 0) {
849
- opts.onProgress?.({ phase: 'map', ratio: total ? (i + 1) / total : 1, done: i + 1, total })
850
- await nextTick()
851
- }
852
- }
853
-
854
- if (applyValidator(rows, errors, opts.validator, opts.maxErrors)) errorsTruncated = true
855
-
856
- let finalRows = rows
857
- let deduped = 0
858
- if (opts.dedupeBy) {
859
- const r = dedupeRows(rows, opts.dedupeBy as string)
860
- finalRows = r.rows
861
- deduped = r.deduped
862
- }
863
- opts.onProgress?.({ phase: 'map', ratio: 1, done: total, total })
864
- return {
865
- headers,
866
- rows: finalRows,
867
- errors,
868
- skipped,
869
- total: matrix.length > 0 ? matrix.length - 1 : 0,
870
- errorsTruncated,
871
- deduped,
872
- }
873
- }
874
-
875
- /** Fold a header / field down to letters + digits so "Unit Price", "unit_price"
876
- * and "UnitPrice" all collapse to the same key. */
877
- function normalizeHeader(s: string): string {
878
- return s.toLowerCase().replace(/[^a-z0-9]/g, '')
879
- }
880
-
881
- /**
882
- * Fuzzy-match each source header to one of the grid's columns (by header
883
- * label first, then field name) and return a `source header -> target
884
- * field` map. Headers with no confident match are left OUT of the map, so
885
- * `buildRecords` falls back to its snake_case default for them.
886
- */
887
- export function autoMapColumns(
888
- headers: string[],
889
- columns: ReadonlyArray<ImportGridColumn>,
890
- ): ImportColumnMap {
891
- const byKey = new Map<string, string>()
892
- for (const c of columns) {
893
- const field = c.field ?? c.header
894
- if (!field) continue
895
- // Field name is the strongest signal, so register header first then let
896
- // the field key overwrite on a collision.
897
- if (c.header) byKey.set(normalizeHeader(c.header), field)
898
- if (c.field) byKey.set(normalizeHeader(c.field), c.field)
899
- }
900
- const map: ImportColumnMap = {}
901
- for (const h of headers) {
902
- const hit = byKey.get(normalizeHeader(h))
903
- if (hit) map[h] = hit
904
- }
905
- return map
906
- }
907
-
908
- /**
909
- * Infer strict import types from each grid column's `format`, so a currency
910
- * / number / percent column parses "$1,234" -> 1234 and a date column parses
911
- * "2026-03-04" -> an ISO date. Columns with no informative format are left
912
- * out (best-effort coercion applies).
913
- */
914
- export function inferImportColumnTypes(
915
- columns: ReadonlyArray<ImportGridColumn>,
916
- ): ImportColumnTypes {
917
- const types: ImportColumnTypes = {}
918
- for (const c of columns) {
919
- if (!c.field) continue
920
- const t = c.format?.type
921
- if (t === 'number' || t === 'currency' || t === 'percent') types[c.field] = 'number'
922
- else if (t === 'date') types[c.field] = 'date'
923
- else if (t === 'datetime') types[c.field] = 'datetime'
924
- }
925
- return types
926
- }
927
-
928
- // ---------------------------------------------------------------------------
929
- // Public entry point
930
- // ---------------------------------------------------------------------------
931
-
932
- /**
933
- * Read a file (or inline text), parse, optionally validate + commit. The
934
- * sister function of `exportGrid`.
935
- */
936
- export async function importData<
937
- TFeatures extends TableFeatures,
938
- TData extends RowData,
939
- >(
940
- api: SvGridApi<TFeatures, TData>,
941
- opts: ImportOptions<TData>,
942
- ): Promise<ImportResult<TData>> {
943
- assertEnterpriseLicensed('Import')
944
- const { format, matrix } = await readImportMatrix(opts.file, opts.format ?? 'auto', {
945
- maxBytes: opts.maxBytes,
946
- encoding: opts.encoding,
947
- signal: opts.signal,
948
- })
949
-
950
- // Enforce the row cap before we do the O(rows) mapping work: either reject
951
- // outright, or truncate to the first maxRows and flag it.
952
- const dataCount = matrix.length > 0 ? matrix.length - 1 : 0
953
- let workMatrix = matrix
954
- let truncated = false
955
- if (opts.maxRows != null && dataCount > opts.maxRows) {
956
- if (opts.overLimit === 'truncate') {
957
- workMatrix = matrix.slice(0, opts.maxRows + 1) // header + first maxRows
958
- truncated = true
959
- } else {
960
- throw new Error(
961
- `@svgrid/enterprise: import has ${dataCount.toLocaleString()} rows, ` +
962
- `over the maxRows limit of ${opts.maxRows.toLocaleString()}.`,
963
- )
964
- }
965
- }
966
-
967
- // Grid-aware auto-mapping: derive the columnMap + columnTypes from the
968
- // grid's own columns, but let anything the caller passed win.
969
- let columnMap = opts.columnMap
970
- let columnTypes = opts.columnTypes
971
- if (opts.autoMap) {
972
- const gridCols = api.getColumns() as ReadonlyArray<ImportGridColumn>
973
- const headers = (workMatrix[0] ?? []).map((h) => h.trim())
974
- columnMap = { ...autoMapColumns(headers, gridCols), ...(opts.columnMap ?? {}) }
975
- columnTypes = { ...inferImportColumnTypes(gridCols), ...(opts.columnTypes ?? {}) }
976
- }
977
-
978
- const { headers, rows, errors, skipped, errorsTruncated, deduped } =
979
- await mapImportMatrixAsync<TData>(workMatrix, {
980
- columnMap,
981
- columnTypes,
982
- validator: opts.validator,
983
- maxErrors: opts.maxErrors,
984
- dedupeBy: opts.dedupeBy,
985
- signal: opts.signal,
986
- onProgress: opts.onProgress,
987
- })
988
-
989
- if (opts.commit && errors.length === 0 && rows.length > 0) {
990
- api.addRows(rows, opts.commitAt ?? 'bottom')
991
- }
992
-
993
- // `total` reports the ORIGINAL source row count even when truncated, so the
994
- // caller can say "imported X of Y".
995
- return { headers, rows, errors, skipped, total: dataCount, format, errorsTruncated, deduped, truncated }
996
- }
997
-
998
- // ---------------------------------------------------------------------------
999
- // Helpers
1000
- // ---------------------------------------------------------------------------
1001
-
1002
- async function readText(blob: Blob, encoding?: string): Promise<string> {
1003
- // The default UTF-8 path is fastest; a declared non-UTF-8 encoding (legacy
1004
- // Windows-1252 CSVs, etc.) routes through TextDecoder.
1005
- if (encoding && encoding.toLowerCase() !== 'utf-8' && encoding.toLowerCase() !== 'utf8') {
1006
- const buf = await blob.arrayBuffer()
1007
- return new TextDecoder(encoding).decode(buf)
1008
- }
1009
- return blob.text()
1010
- }
1011
-
1012
- /** Convert JSON text containing an array of objects into a `string[][]`
1013
- * matrix shaped like CSV: header row, then one row per record. */
1014
- function jsonToMatrix(text: string): string[][] {
1015
- const parsed = JSON.parse(text)
1016
- if (!Array.isArray(parsed)) {
1017
- throw new Error('@svgrid/enterprise: JSON import expects a top-level array')
1018
- }
1019
- if (parsed.length === 0) return []
1020
- // Collect the union of keys across the first ~50 records so we don't
1021
- // miss a column present only on later rows.
1022
- const headers: string[] = []
1023
- const seen = new Set<string>()
1024
- const sample = parsed.slice(0, 50) as Record<string, unknown>[]
1025
- for (const r of sample) {
1026
- if (r && typeof r === 'object') {
1027
- for (const k of Object.keys(r)) {
1028
- if (!seen.has(k)) { seen.add(k); headers.push(k) }
1029
- }
1030
- }
1031
- }
1032
- const rows: string[][] = [headers.slice()]
1033
- for (const r of parsed as Array<Record<string, unknown>>) {
1034
- const row: string[] = []
1035
- for (const h of headers) {
1036
- const v = r?.[h]
1037
- if (v == null) row.push('')
1038
- else if (typeof v === 'object') row.push(JSON.stringify(v))
1039
- else row.push(String(v))
1040
- }
1041
- rows.push(row)
1042
- }
1043
- return rows
1044
- }