@datarecce/ui 0.1.30 → 0.1.32

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 (622) hide show
  1. package/dist/{state-lPCQsWy5.js → RecceCheckContext-BOGmP80K.js} +4367 -5089
  2. package/dist/RecceCheckContext-BOGmP80K.js.map +1 -0
  3. package/dist/{state-B9yzhuKs.mjs → RecceCheckContext-CwUCo6AW.mjs} +4273 -4541
  4. package/dist/RecceCheckContext-CwUCo6AW.mjs.map +1 -0
  5. package/dist/{state-DOUPNifc.css → RecceCheckContext-DPnWB_aU.css} +57 -57
  6. package/dist/RecceCheckContext-DPnWB_aU.css.map +1 -0
  7. package/dist/{state-IA7HWYOs.css → RecceCheckContext-DyxOeUsX.css} +57 -57
  8. package/dist/RecceCheckContext-DyxOeUsX.css.map +1 -0
  9. package/dist/api.d.mts +1 -1
  10. package/dist/api.d.ts +1 -1
  11. package/dist/api.js +65 -26
  12. package/dist/api.js.map +1 -0
  13. package/dist/api.mjs +44 -5
  14. package/dist/api.mjs.map +1 -0
  15. package/dist/{components-DCOI1YlQ.mjs → components-DQUwJlNQ.mjs} +20 -21
  16. package/dist/{components-DCOI1YlQ.mjs.map → components-DQUwJlNQ.mjs.map} +1 -1
  17. package/dist/{components-B-YxuuPz.js → components-uVp0e4cH.js} +231 -241
  18. package/dist/{components-B-YxuuPz.js.map → components-uVp0e4cH.js.map} +1 -1
  19. package/dist/components.d.mts +1 -1
  20. package/dist/components.d.ts +1 -1
  21. package/dist/components.js +38 -38
  22. package/dist/components.mjs +5 -5
  23. package/dist/{urls-B1Ymdoz-.mjs → const-CaIm1Z8g.mjs} +2 -6
  24. package/dist/const-CaIm1Z8g.mjs.map +1 -0
  25. package/dist/{urls-C4eAc82S.js → const-CvdZO0FN.js} +1 -11
  26. package/dist/const-CvdZO0FN.js.map +1 -0
  27. package/dist/global-styles.css +84 -0
  28. package/dist/global-styles.css.map +1 -0
  29. package/dist/global-styles.js +1 -0
  30. package/dist/global-styles.mjs +1 -0
  31. package/dist/{hooks-DjBNmTdh.mjs → hooks-C6Kma5ld.mjs} +2 -3
  32. package/dist/{hooks-DjBNmTdh.mjs.map → hooks-C6Kma5ld.mjs.map} +1 -1
  33. package/dist/hooks-CfZ4UBBF.js +40 -0
  34. package/dist/{hooks-B9hsc1oD.js.map → hooks-CfZ4UBBF.js.map} +1 -1
  35. package/dist/hooks.d.mts +1 -1
  36. package/dist/hooks.d.ts +1 -1
  37. package/dist/hooks.js +26 -26
  38. package/dist/hooks.mjs +4 -4
  39. package/dist/{html2canvas-pro.esm-WJxOmKlq.js → html2canvas-pro.esm-CsuSOHXp.js} +1 -1
  40. package/dist/{html2canvas-pro.esm-WJxOmKlq.js.map → html2canvas-pro.esm-CsuSOHXp.js.map} +1 -1
  41. package/dist/{html2canvas-pro.esm-BInzOtWO.mjs → html2canvas-pro.esm-E7kpobrC.mjs} +1 -1
  42. package/dist/{html2canvas-pro.esm-BInzOtWO.mjs.map → html2canvas-pro.esm-E7kpobrC.mjs.map} +1 -1
  43. package/dist/{index-BNUP2V_N.d.ts → index-B9lSPJTi.d.ts} +184 -2
  44. package/dist/index-B9lSPJTi.d.ts.map +1 -0
  45. package/dist/{index-DOPZuhD8.d.mts → index-DsCU2oGL.d.mts} +259 -77
  46. package/dist/index-DsCU2oGL.d.mts.map +1 -0
  47. package/dist/index.d.mts +2 -2
  48. package/dist/index.d.ts +2 -2
  49. package/dist/index.js +92 -84
  50. package/dist/index.js.map +1 -1
  51. package/dist/index.mjs +12 -10
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/{mui-theme-B2wm_cvZ.js → mui-theme-iBHkjXJq.js} +2 -2
  54. package/dist/{mui-theme-B2wm_cvZ.js.map → mui-theme-iBHkjXJq.js.map} +1 -1
  55. package/dist/state-CTITyT0R.js +795 -0
  56. package/dist/state-CTITyT0R.js.map +1 -0
  57. package/dist/state-Sc2b4jri.mjs +382 -0
  58. package/dist/state-Sc2b4jri.mjs.map +1 -0
  59. package/dist/styles.css +5 -0
  60. package/dist/theme.d.mts +2 -185
  61. package/dist/theme.d.ts +2 -185
  62. package/dist/theme.js +1 -1
  63. package/dist/{tooltipMessage-DosF13kZ.js → tooltipMessage-BC5W7H3X.js} +1 -1
  64. package/dist/{tooltipMessage-DosF13kZ.js.map → tooltipMessage-BC5W7H3X.js.map} +1 -1
  65. package/dist/{tooltipMessage-B--I3p1V.mjs → tooltipMessage-B_xMIKWL.mjs} +1 -1
  66. package/dist/{tooltipMessage-B--I3p1V.mjs.map → tooltipMessage-B_xMIKWL.mjs.map} +1 -1
  67. package/dist/types.d.mts +1 -1
  68. package/dist/types.d.ts +1 -1
  69. package/dist/types.js +5 -4
  70. package/dist/types.mjs +3 -2
  71. package/dist/urls-BQW5wjg-.js +13 -0
  72. package/dist/urls-BQW5wjg-.js.map +1 -0
  73. package/dist/urls-DT7FVEcS.mjs +7 -0
  74. package/dist/urls-DT7FVEcS.mjs.map +1 -0
  75. package/dist/version-B9s8yne-.js +300 -0
  76. package/dist/version-B9s8yne-.js.map +1 -0
  77. package/dist/version-DP1kU_7v.mjs +162 -0
  78. package/dist/version-DP1kU_7v.mjs.map +1 -0
  79. package/package.json +5 -3
  80. package/recce-source/.editorconfig +26 -0
  81. package/recce-source/.flake8 +37 -0
  82. package/recce-source/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
  83. package/recce-source/.github/ISSUE_TEMPLATE/custom.md +10 -0
  84. package/recce-source/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
  85. package/recce-source/.github/PULL_REQUEST_TEMPLATE.md +21 -0
  86. package/recce-source/.github/copilot-instructions.md +331 -0
  87. package/recce-source/.github/instructions/backend-instructions.md +541 -0
  88. package/recce-source/.github/instructions/frontend-instructions.md +317 -0
  89. package/recce-source/.github/workflows/build-statics.yaml +72 -0
  90. package/recce-source/.github/workflows/bump.yaml +48 -0
  91. package/recce-source/.github/workflows/integration-tests-cloud.yaml +92 -0
  92. package/recce-source/.github/workflows/integration-tests-sqlmesh.yaml +33 -0
  93. package/recce-source/.github/workflows/integration-tests.yaml +52 -0
  94. package/recce-source/.github/workflows/nightly.yaml +246 -0
  95. package/recce-source/.github/workflows/release.yaml +196 -0
  96. package/recce-source/.github/workflows/tests-js.yaml +58 -0
  97. package/recce-source/.github/workflows/tests-python.yaml +128 -0
  98. package/recce-source/.pre-commit-config.yaml +26 -0
  99. package/recce-source/CLAUDE.md +483 -0
  100. package/recce-source/CODE_OF_CONDUCT.md +128 -0
  101. package/recce-source/CONTRIBUTING.md +107 -0
  102. package/recce-source/LICENSE +201 -0
  103. package/recce-source/Makefile +126 -0
  104. package/recce-source/README.md +182 -0
  105. package/recce-source/RECCE_CLOUD.md +81 -0
  106. package/recce-source/SECURITY.md +25 -0
  107. package/recce-source/docs/PACKAGING.md +340 -0
  108. package/recce-source/docs/README.md +1 -0
  109. package/recce-source/integration_tests/dbt/dbt_project.yml +26 -0
  110. package/recce-source/integration_tests/dbt/models/customers.sql +69 -0
  111. package/recce-source/integration_tests/dbt/models/docs.md +14 -0
  112. package/recce-source/integration_tests/dbt/models/orders.sql +56 -0
  113. package/recce-source/integration_tests/dbt/models/schema.yml +82 -0
  114. package/recce-source/integration_tests/dbt/models/staging/schema.yml +31 -0
  115. package/recce-source/integration_tests/dbt/models/staging/stg_customers.sql +22 -0
  116. package/recce-source/integration_tests/dbt/models/staging/stg_orders.sql +23 -0
  117. package/recce-source/integration_tests/dbt/models/staging/stg_payments.sql +25 -0
  118. package/recce-source/integration_tests/dbt/packages.yml +7 -0
  119. package/recce-source/integration_tests/dbt/profiles.yml +8 -0
  120. package/recce-source/integration_tests/dbt/seeds/raw_customers.csv +101 -0
  121. package/recce-source/integration_tests/dbt/seeds/raw_orders.csv +100 -0
  122. package/recce-source/integration_tests/dbt/seeds/raw_payments.csv +114 -0
  123. package/recce-source/integration_tests/dbt/seeds/raw_statuses.csv +5 -0
  124. package/recce-source/integration_tests/dbt/smoke_test.sh +72 -0
  125. package/recce-source/integration_tests/dbt/smoke_test_cloud.sh +71 -0
  126. package/recce-source/integration_tests/sqlmesh/__init__.py +0 -0
  127. package/recce-source/integration_tests/sqlmesh/audits/assert_item_price_above_zero.sql +9 -0
  128. package/recce-source/integration_tests/sqlmesh/audits/items.sql +7 -0
  129. package/recce-source/integration_tests/sqlmesh/audits/order_items.sql +7 -0
  130. package/recce-source/integration_tests/sqlmesh/config.py +171 -0
  131. package/recce-source/integration_tests/sqlmesh/helper.py +20 -0
  132. package/recce-source/integration_tests/sqlmesh/hooks/__init__.py +0 -0
  133. package/recce-source/integration_tests/sqlmesh/macros/__init__.py +0 -0
  134. package/recce-source/integration_tests/sqlmesh/macros/macros.py +8 -0
  135. package/recce-source/integration_tests/sqlmesh/macros/macros.sql +8 -0
  136. package/recce-source/integration_tests/sqlmesh/macros/utils.py +11 -0
  137. package/recce-source/integration_tests/sqlmesh/metrics/metrics.sql +25 -0
  138. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_by_day.sql +41 -0
  139. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_lifetime.sql +60 -0
  140. package/recce-source/integration_tests/sqlmesh/models/customers.sql +32 -0
  141. package/recce-source/integration_tests/sqlmesh/models/items.py +95 -0
  142. package/recce-source/integration_tests/sqlmesh/models/marketing.sql +15 -0
  143. package/recce-source/integration_tests/sqlmesh/models/order_items.py +95 -0
  144. package/recce-source/integration_tests/sqlmesh/models/orders.py +70 -0
  145. package/recce-source/integration_tests/sqlmesh/models/raw_marketing.py +62 -0
  146. package/recce-source/integration_tests/sqlmesh/models/top_waiters.sql +23 -0
  147. package/recce-source/integration_tests/sqlmesh/models/waiter_as_customer_by_day.sql +29 -0
  148. package/recce-source/integration_tests/sqlmesh/models/waiter_names.sql +10 -0
  149. package/recce-source/integration_tests/sqlmesh/models/waiter_revenue_by_day.sql +29 -0
  150. package/recce-source/integration_tests/sqlmesh/models/waiters.py +62 -0
  151. package/recce-source/integration_tests/sqlmesh/prep_env.sh +16 -0
  152. package/recce-source/integration_tests/sqlmesh/schema.yaml +5 -0
  153. package/recce-source/integration_tests/sqlmesh/seeds/waiter_names.csv +11 -0
  154. package/recce-source/integration_tests/sqlmesh/test_server.sh +29 -0
  155. package/recce-source/integration_tests/sqlmesh/tests/test_customer_revenue_by_day.yaml +63 -0
  156. package/recce-source/integration_tests/sqlmesh/tests/test_order_items.yaml +72 -0
  157. package/recce-source/js/.editorconfig +27 -0
  158. package/recce-source/js/.env.development +5 -0
  159. package/recce-source/js/.husky/pre-commit +29 -0
  160. package/recce-source/js/.nvmrc +1 -0
  161. package/recce-source/js/README.md +39 -0
  162. package/recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx +65 -0
  163. package/recce-source/js/app/(mainComponents)/NavBar.tsx +228 -0
  164. package/recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx +107 -0
  165. package/recce-source/js/app/(mainComponents)/TopBar.tsx +252 -0
  166. package/recce-source/js/app/@lineage/default.tsx +20 -0
  167. package/recce-source/js/app/@lineage/page.tsx +14 -0
  168. package/recce-source/js/app/MainLayout.tsx +170 -0
  169. package/recce-source/js/app/Providers.tsx +49 -0
  170. package/recce-source/js/app/checks/page.tsx +296 -0
  171. package/recce-source/js/app/error.tsx +93 -0
  172. package/recce-source/js/app/favicon.ico +0 -0
  173. package/recce-source/js/app/global-error.tsx +115 -0
  174. package/recce-source/js/app/global.css +82 -0
  175. package/recce-source/js/app/layout.tsx +48 -0
  176. package/recce-source/js/app/lineage/page.tsx +15 -0
  177. package/recce-source/js/app/page.tsx +12 -0
  178. package/recce-source/js/app/query/page.tsx +8 -0
  179. package/recce-source/js/biome.json +313 -0
  180. package/recce-source/js/jest.config.js +34 -0
  181. package/recce-source/js/jest.globals.d.ts +32 -0
  182. package/recce-source/js/jest.setup.js +91 -0
  183. package/recce-source/js/next.config.js +16 -0
  184. package/recce-source/js/package-lock.json +13843 -0
  185. package/recce-source/js/package.json +123 -0
  186. package/recce-source/js/pnpm-lock.yaml +9235 -0
  187. package/recce-source/js/pnpm-workspace.yaml +6 -0
  188. package/recce-source/js/postcss.config.js +5 -0
  189. package/recce-source/js/public/auth_callback.html +68 -0
  190. package/recce-source/js/public/imgs/feedback/thumbs-down.png +0 -0
  191. package/recce-source/js/public/imgs/feedback/thumbs-up.png +0 -0
  192. package/recce-source/js/public/imgs/reload-image.svg +4 -0
  193. package/recce-source/js/public/logo/recce-logo-white.png +0 -0
  194. package/recce-source/js/src/components/AuthModal/AuthModal.tsx +202 -0
  195. package/recce-source/js/src/components/app/AvatarDropdown.tsx +159 -0
  196. package/recce-source/js/src/components/app/EnvInfo.tsx +357 -0
  197. package/recce-source/js/src/components/app/Filename.tsx +388 -0
  198. package/recce-source/js/src/components/app/SetupConnectionPopover.tsx +91 -0
  199. package/recce-source/js/src/components/app/StateExporter.tsx +57 -0
  200. package/recce-source/js/src/components/app/StateImporter.tsx +198 -0
  201. package/recce-source/js/src/components/app/StateSharing.tsx +145 -0
  202. package/recce-source/js/src/components/app/StateSynchronizer.tsx +205 -0
  203. package/recce-source/js/src/components/charts/HistogramChart.tsx +291 -0
  204. package/recce-source/js/src/components/charts/SquareIcon.tsx +51 -0
  205. package/recce-source/js/src/components/charts/TopKSummaryList.tsx +457 -0
  206. package/recce-source/js/src/components/charts/chartTheme.ts +74 -0
  207. package/recce-source/js/src/components/check/CheckBreadcrumb.tsx +97 -0
  208. package/recce-source/js/src/components/check/CheckDescription.tsx +134 -0
  209. package/recce-source/js/src/components/check/CheckDetail.tsx +797 -0
  210. package/recce-source/js/src/components/check/CheckEmptyState.tsx +84 -0
  211. package/recce-source/js/src/components/check/CheckList.tsx +320 -0
  212. package/recce-source/js/src/components/check/LineageDiffView.tsx +32 -0
  213. package/recce-source/js/src/components/check/PresetCheckTemplateView.tsx +48 -0
  214. package/recce-source/js/src/components/check/SchemaDiffView.tsx +290 -0
  215. package/recce-source/js/src/components/check/check.ts +25 -0
  216. package/recce-source/js/src/components/check/timeline/CheckTimeline.tsx +163 -0
  217. package/recce-source/js/src/components/check/timeline/CommentInput.tsx +84 -0
  218. package/recce-source/js/src/components/check/timeline/TimelineEvent.tsx +468 -0
  219. package/recce-source/js/src/components/check/timeline/index.ts +12 -0
  220. package/recce-source/js/src/components/check/utils.ts +12 -0
  221. package/recce-source/js/src/components/data-grid/ScreenshotDataGrid.tsx +333 -0
  222. package/recce-source/js/src/components/data-grid/agGridStyles.css +55 -0
  223. package/recce-source/js/src/components/data-grid/agGridTheme.ts +43 -0
  224. package/recce-source/js/src/components/editor/CodeEditor.tsx +107 -0
  225. package/recce-source/js/src/components/editor/DiffEditor.tsx +162 -0
  226. package/recce-source/js/src/components/editor/index.ts +12 -0
  227. package/recce-source/js/src/components/errorboundary/ErrorBoundary.tsx +87 -0
  228. package/recce-source/js/src/components/histogram/HistogramDiffForm.tsx +147 -0
  229. package/recce-source/js/src/components/histogram/HistogramDiffResultView.tsx +63 -0
  230. package/recce-source/js/src/components/icons/index.tsx +142 -0
  231. package/recce-source/js/src/components/lineage/ActionControl.tsx +63 -0
  232. package/recce-source/js/src/components/lineage/ActionTag.tsx +141 -0
  233. package/recce-source/js/src/components/lineage/ChangeStatusLegend.tsx +46 -0
  234. package/recce-source/js/src/components/lineage/ColumnLevelLineageControl.tsx +327 -0
  235. package/recce-source/js/src/components/lineage/ColumnLevelLineageLegend.tsx +57 -0
  236. package/recce-source/js/src/components/lineage/GraphColumnNode.tsx +199 -0
  237. package/recce-source/js/src/components/lineage/GraphEdge.tsx +59 -0
  238. package/recce-source/js/src/components/lineage/GraphNode.tsx +555 -0
  239. package/recce-source/js/src/components/lineage/LineagePage.tsx +10 -0
  240. package/recce-source/js/src/components/lineage/LineageView.tsx +1384 -0
  241. package/recce-source/js/src/components/lineage/LineageViewContext.tsx +86 -0
  242. package/recce-source/js/src/components/lineage/LineageViewContextMenu.tsx +637 -0
  243. package/recce-source/js/src/components/lineage/LineageViewNotification.tsx +64 -0
  244. package/recce-source/js/src/components/lineage/LineageViewTopBar.tsx +596 -0
  245. package/recce-source/js/src/components/lineage/NodeSqlView.tsx +136 -0
  246. package/recce-source/js/src/components/lineage/NodeTag.tsx +278 -0
  247. package/recce-source/js/src/components/lineage/NodeView.tsx +642 -0
  248. package/recce-source/js/src/components/lineage/SandboxView.tsx +436 -0
  249. package/recce-source/js/src/components/lineage/ServerDisconnectedModalContent.tsx +105 -0
  250. package/recce-source/js/src/components/lineage/SetupConnectionBanner.tsx +52 -0
  251. package/recce-source/js/src/components/lineage/SingleEnvironmentQueryView.tsx +152 -0
  252. package/recce-source/js/src/components/lineage/graph.test.ts +31 -0
  253. package/recce-source/js/src/components/lineage/graph.ts +58 -0
  254. package/recce-source/js/src/components/lineage/lineage.test.ts +169 -0
  255. package/recce-source/js/src/components/lineage/lineage.ts +521 -0
  256. package/recce-source/js/src/components/lineage/styles.css +42 -0
  257. package/recce-source/js/src/components/lineage/styles.tsx +165 -0
  258. package/recce-source/js/src/components/lineage/useMultiNodesAction.ts +352 -0
  259. package/recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx +108 -0
  260. package/recce-source/js/src/components/onboarding-guide/Notification.tsx +62 -0
  261. package/recce-source/js/src/components/profile/ProfileDiffForm.tsx +134 -0
  262. package/recce-source/js/src/components/profile/ProfileDiffResultView.tsx +245 -0
  263. package/recce-source/js/src/components/query/ChangedOnlyCheckbox.tsx +29 -0
  264. package/recce-source/js/src/components/query/DiffText.tsx +120 -0
  265. package/recce-source/js/src/components/query/QueryDiffResultView.tsx +470 -0
  266. package/recce-source/js/src/components/query/QueryForm.tsx +80 -0
  267. package/recce-source/js/src/components/query/QueryPage.tsx +282 -0
  268. package/recce-source/js/src/components/query/QueryResultView.tsx +180 -0
  269. package/recce-source/js/src/components/query/SetupConnectionGuide.tsx +57 -0
  270. package/recce-source/js/src/components/query/SqlEditor.tsx +245 -0
  271. package/recce-source/js/src/components/query/ToggleSwitch.tsx +84 -0
  272. package/recce-source/js/src/components/query/styles.css +21 -0
  273. package/recce-source/js/src/components/routing/DirectUrlAccess.test.tsx +428 -0
  274. package/recce-source/js/src/components/routing/LineageStatePreservation.test.tsx +311 -0
  275. package/recce-source/js/src/components/routing/Navigation.test.tsx +256 -0
  276. package/recce-source/js/src/components/rowcount/RowCountDiffResultView.tsx +109 -0
  277. package/recce-source/js/src/components/rowcount/delta.ts +11 -0
  278. package/recce-source/js/src/components/run/RunList.tsx +303 -0
  279. package/recce-source/js/src/components/run/RunModal.tsx +191 -0
  280. package/recce-source/js/src/components/run/RunPage.tsx +26 -0
  281. package/recce-source/js/src/components/run/RunResultPane.tsx +454 -0
  282. package/recce-source/js/src/components/run/RunStatusAndDate.tsx +106 -0
  283. package/recce-source/js/src/components/run/RunToolbar.tsx +70 -0
  284. package/recce-source/js/src/components/run/RunView.tsx +196 -0
  285. package/recce-source/js/src/components/run/registry.ts +214 -0
  286. package/recce-source/js/src/components/run/types.ts +14 -0
  287. package/recce-source/js/src/components/schema/ColumnNameCell.test.tsx +169 -0
  288. package/recce-source/js/src/components/schema/ColumnNameCell.tsx +198 -0
  289. package/recce-source/js/src/components/schema/SchemaView.tsx +337 -0
  290. package/recce-source/js/src/components/schema/schemaDiff.ts +32 -0
  291. package/recce-source/js/src/components/schema/style.css +134 -0
  292. package/recce-source/js/src/components/screenshot/ScreenshotBox.tsx +39 -0
  293. package/recce-source/js/src/components/shared/HistoryToggle.tsx +35 -0
  294. package/recce-source/js/src/components/split/Split.tsx +40 -0
  295. package/recce-source/js/src/components/split/styles.css +24 -0
  296. package/recce-source/js/src/components/summary/ChangeSummary.tsx +264 -0
  297. package/recce-source/js/src/components/summary/SchemaSummary.tsx +123 -0
  298. package/recce-source/js/src/components/summary/SummaryView.tsx +29 -0
  299. package/recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx +48 -0
  300. package/recce-source/js/src/components/top-k/TopKDiffForm.tsx +58 -0
  301. package/recce-source/js/src/components/top-k/TopKDiffResultView.tsx +73 -0
  302. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnGroupHeader.tsx +228 -0
  303. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnHeader.tsx +113 -0
  304. package/recce-source/js/src/components/ui/dataGrid/defaultRenderCell.tsx +72 -0
  305. package/recce-source/js/src/components/ui/dataGrid/index.ts +23 -0
  306. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.test.tsx +607 -0
  307. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.tsx +211 -0
  308. package/recce-source/js/src/components/ui/dataGrid/schemaCells.test.tsx +452 -0
  309. package/recce-source/js/src/components/ui/dataGrid/schemaCells.tsx +142 -0
  310. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.test.tsx +178 -0
  311. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.tsx +275 -0
  312. package/recce-source/js/src/components/ui/markdown/ExternalLinkConfirmDialog.tsx +134 -0
  313. package/recce-source/js/src/components/ui/markdown/MarkdownContent.tsx +364 -0
  314. package/recce-source/js/src/components/ui/mui/index.ts +13 -0
  315. package/recce-source/js/src/components/ui/mui-provider.tsx +67 -0
  316. package/recce-source/js/src/components/ui/mui-theme.ts +1039 -0
  317. package/recce-source/js/src/components/ui/mui-utils.ts +113 -0
  318. package/recce-source/js/src/components/ui/toaster.tsx +288 -0
  319. package/recce-source/js/src/components/valuediff/ValueDiffDetailResultView.tsx +217 -0
  320. package/recce-source/js/src/components/valuediff/ValueDiffForm.tsx +246 -0
  321. package/recce-source/js/src/components/valuediff/ValueDiffResultView.tsx +82 -0
  322. package/recce-source/js/src/components/valuediff/shared.ts +33 -0
  323. package/recce-source/js/src/constants/tooltipMessage.ts +3 -0
  324. package/recce-source/js/src/constants/urls.ts +1 -0
  325. package/recce-source/js/src/lib/UrlHash.ts +12 -0
  326. package/recce-source/js/src/lib/api/adhocQuery.ts +70 -0
  327. package/recce-source/js/src/lib/api/axiosClient.ts +9 -0
  328. package/recce-source/js/src/lib/api/cacheKeys.ts +13 -0
  329. package/recce-source/js/src/lib/api/checkEvents.ts +252 -0
  330. package/recce-source/js/src/lib/api/checks.ts +129 -0
  331. package/recce-source/js/src/lib/api/cll.ts +53 -0
  332. package/recce-source/js/src/lib/api/connectToCloud.ts +13 -0
  333. package/recce-source/js/src/lib/api/flag.ts +37 -0
  334. package/recce-source/js/src/lib/api/info.ts +198 -0
  335. package/recce-source/js/src/lib/api/instanceInfo.ts +25 -0
  336. package/recce-source/js/src/lib/api/keepAlive.ts +108 -0
  337. package/recce-source/js/src/lib/api/lineagecheck.ts +35 -0
  338. package/recce-source/js/src/lib/api/localStorageKeys.ts +7 -0
  339. package/recce-source/js/src/lib/api/models.ts +59 -0
  340. package/recce-source/js/src/lib/api/profile.ts +65 -0
  341. package/recce-source/js/src/lib/api/rowcount.ts +19 -0
  342. package/recce-source/js/src/lib/api/runs.ts +174 -0
  343. package/recce-source/js/src/lib/api/schemacheck.ts +31 -0
  344. package/recce-source/js/src/lib/api/select.ts +25 -0
  345. package/recce-source/js/src/lib/api/sessionStorageKeys.ts +8 -0
  346. package/recce-source/js/src/lib/api/state.ts +117 -0
  347. package/recce-source/js/src/lib/api/track.ts +281 -0
  348. package/recce-source/js/src/lib/api/types.ts +284 -0
  349. package/recce-source/js/src/lib/api/user.ts +42 -0
  350. package/recce-source/js/src/lib/api/valuediff.ts +46 -0
  351. package/recce-source/js/src/lib/api/version.ts +40 -0
  352. package/recce-source/js/src/lib/const.ts +9 -0
  353. package/recce-source/js/src/lib/dataGrid/crossFunctionConsistency.test.ts +626 -0
  354. package/recce-source/js/src/lib/dataGrid/dataGridFactory.test.ts +2140 -0
  355. package/recce-source/js/src/lib/dataGrid/dataGridFactory.ts +397 -0
  356. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.test.ts +132 -0
  357. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.ts +126 -0
  358. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.test.ts +1627 -0
  359. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.ts +140 -0
  360. package/recce-source/js/src/lib/dataGrid/generators/toDataGrid.ts +67 -0
  361. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.test.ts +142 -0
  362. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.ts +71 -0
  363. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.test.ts +258 -0
  364. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.ts +153 -0
  365. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.test.ts +951 -0
  366. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.ts +221 -0
  367. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.test.ts +395 -0
  368. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.ts +184 -0
  369. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.test.ts +884 -0
  370. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.ts +113 -0
  371. package/recce-source/js/src/lib/dataGrid/index.ts +51 -0
  372. package/recce-source/js/src/lib/dataGrid/propertyBased.test.ts +858 -0
  373. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.test.ts +482 -0
  374. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.ts +345 -0
  375. package/recce-source/js/src/lib/dataGrid/shared/dataTypeEdgeCases.test.ts +698 -0
  376. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.test.tsx +820 -0
  377. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.tsx +277 -0
  378. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.test.ts +785 -0
  379. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.ts +370 -0
  380. package/recce-source/js/src/lib/dataGrid/shared/index.ts +81 -0
  381. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.test.ts +909 -0
  382. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.ts +325 -0
  383. package/recce-source/js/src/lib/dataGrid/shared/simpleColumnBuilder.tsx +240 -0
  384. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.test.tsx +719 -0
  385. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.tsx +231 -0
  386. package/recce-source/js/src/lib/dataGrid/shared/validation.test.ts +559 -0
  387. package/recce-source/js/src/lib/dataGrid/shared/validation.ts +367 -0
  388. package/recce-source/js/src/lib/dataGrid/warehouseNamingConventions.test.ts +1117 -0
  389. package/recce-source/js/src/lib/formatSelect.ts +50 -0
  390. package/recce-source/js/src/lib/hooks/ApiConfigContext.tsx +181 -0
  391. package/recce-source/js/src/lib/hooks/IdleTimeoutContext.tsx +177 -0
  392. package/recce-source/js/src/lib/hooks/LineageGraphContext.tsx +512 -0
  393. package/recce-source/js/src/lib/hooks/RecceActionContext.tsx +269 -0
  394. package/recce-source/js/src/lib/hooks/RecceCheckContext.tsx +33 -0
  395. package/recce-source/js/src/lib/hooks/RecceContextProvider.tsx +54 -0
  396. package/recce-source/js/src/lib/hooks/RecceInstanceContext.tsx +129 -0
  397. package/recce-source/js/src/lib/hooks/RecceQueryContext.tsx +98 -0
  398. package/recce-source/js/src/lib/hooks/RecceShareStateContext.tsx +59 -0
  399. package/recce-source/js/src/lib/hooks/ScreenShot.tsx +399 -0
  400. package/recce-source/js/src/lib/hooks/useAppRouter.test.ts +211 -0
  401. package/recce-source/js/src/lib/hooks/useAppRouter.ts +200 -0
  402. package/recce-source/js/src/lib/hooks/useCheckEvents.ts +99 -0
  403. package/recce-source/js/src/lib/hooks/useCheckToast.tsx +14 -0
  404. package/recce-source/js/src/lib/hooks/useClipBoardToast.tsx +27 -0
  405. package/recce-source/js/src/lib/hooks/useCountdownToast.tsx +102 -0
  406. package/recce-source/js/src/lib/hooks/useFeedbackCollectionToast.tsx +130 -0
  407. package/recce-source/js/src/lib/hooks/useGuideToast.tsx +45 -0
  408. package/recce-source/js/src/lib/hooks/useIdleDetection.tsx +185 -0
  409. package/recce-source/js/src/lib/hooks/useModelColumns.tsx +113 -0
  410. package/recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx +13 -0
  411. package/recce-source/js/src/lib/hooks/useRecceServerFlag.tsx +13 -0
  412. package/recce-source/js/src/lib/hooks/useRun.tsx +89 -0
  413. package/recce-source/js/src/lib/hooks/useThemeColors.ts +115 -0
  414. package/recce-source/js/src/lib/mergeKeys.test.ts +89 -0
  415. package/recce-source/js/src/lib/mergeKeys.ts +86 -0
  416. package/recce-source/js/src/lib/result/ResultErrorFallback.tsx +9 -0
  417. package/recce-source/js/src/lib/utils/formatTime.ts +84 -0
  418. package/recce-source/js/src/lib/utils/urls.ts +16 -0
  419. package/recce-source/js/src/utils/DropdownValuesInput.tsx +297 -0
  420. package/recce-source/js/src/utils/formatters.tsx +237 -0
  421. package/recce-source/js/src/utils/transforms.ts +81 -0
  422. package/recce-source/js/tsconfig.json +47 -0
  423. package/recce-source/macros/README.md +8 -0
  424. package/recce-source/macros/recce_athena.sql +73 -0
  425. package/recce-source/pyproject.toml +109 -0
  426. package/recce-source/recce/VERSION +1 -0
  427. package/recce-source/recce/__init__.py +84 -0
  428. package/recce-source/recce/adapter/__init__.py +0 -0
  429. package/recce-source/recce/adapter/base.py +109 -0
  430. package/recce-source/recce/adapter/dbt_adapter/__init__.py +1699 -0
  431. package/recce-source/recce/adapter/dbt_adapter/dbt_version.py +42 -0
  432. package/recce-source/recce/adapter/sqlmesh_adapter.py +141 -0
  433. package/recce-source/recce/apis/__init__.py +0 -0
  434. package/recce-source/recce/apis/check_api.py +203 -0
  435. package/recce-source/recce/apis/check_events_api.py +353 -0
  436. package/recce-source/recce/apis/check_func.py +130 -0
  437. package/recce-source/recce/apis/run_api.py +130 -0
  438. package/recce-source/recce/apis/run_func.py +258 -0
  439. package/recce-source/recce/artifact.py +266 -0
  440. package/recce-source/recce/cli.py +1846 -0
  441. package/recce-source/recce/config.py +127 -0
  442. package/recce-source/recce/connect_to_cloud.py +138 -0
  443. package/recce-source/recce/core.py +334 -0
  444. package/recce-source/recce/diff.py +26 -0
  445. package/recce-source/recce/event/CONFIG +1 -0
  446. package/recce-source/recce/event/SENTRY_DNS +1 -0
  447. package/recce-source/recce/event/__init__.py +304 -0
  448. package/recce-source/recce/event/collector.py +184 -0
  449. package/recce-source/recce/event/track.py +158 -0
  450. package/recce-source/recce/exceptions.py +21 -0
  451. package/recce-source/recce/git.py +77 -0
  452. package/recce-source/recce/github.py +222 -0
  453. package/recce-source/recce/mcp_server.py +861 -0
  454. package/recce-source/recce/models/__init__.py +6 -0
  455. package/recce-source/recce/models/check.py +473 -0
  456. package/recce-source/recce/models/run.py +46 -0
  457. package/recce-source/recce/models/types.py +218 -0
  458. package/recce-source/recce/pull_request.py +124 -0
  459. package/recce-source/recce/run.py +390 -0
  460. package/recce-source/recce/server.py +877 -0
  461. package/recce-source/recce/state/__init__.py +31 -0
  462. package/recce-source/recce/state/cloud.py +644 -0
  463. package/recce-source/recce/state/const.py +26 -0
  464. package/recce-source/recce/state/local.py +56 -0
  465. package/recce-source/recce/state/state.py +119 -0
  466. package/recce-source/recce/state/state_loader.py +174 -0
  467. package/recce-source/recce/summary.py +575 -0
  468. package/recce-source/recce/tasks/__init__.py +23 -0
  469. package/recce-source/recce/tasks/core.py +134 -0
  470. package/recce-source/recce/tasks/dataframe.py +170 -0
  471. package/recce-source/recce/tasks/histogram.py +433 -0
  472. package/recce-source/recce/tasks/lineage.py +19 -0
  473. package/recce-source/recce/tasks/profile.py +298 -0
  474. package/recce-source/recce/tasks/query.py +450 -0
  475. package/recce-source/recce/tasks/rowcount.py +277 -0
  476. package/recce-source/recce/tasks/schema.py +65 -0
  477. package/recce-source/recce/tasks/top_k.py +172 -0
  478. package/recce-source/recce/tasks/utils.py +147 -0
  479. package/recce-source/recce/tasks/valuediff.py +497 -0
  480. package/recce-source/recce/util/__init__.py +4 -0
  481. package/recce-source/recce/util/api_token.py +80 -0
  482. package/recce-source/recce/util/breaking.py +330 -0
  483. package/recce-source/recce/util/cache.py +25 -0
  484. package/recce-source/recce/util/cll.py +355 -0
  485. package/recce-source/recce/util/cloud/__init__.py +15 -0
  486. package/recce-source/recce/util/cloud/base.py +115 -0
  487. package/recce-source/recce/util/cloud/check_events.py +190 -0
  488. package/recce-source/recce/util/cloud/checks.py +242 -0
  489. package/recce-source/recce/util/io.py +120 -0
  490. package/recce-source/recce/util/lineage.py +83 -0
  491. package/recce-source/recce/util/logger.py +25 -0
  492. package/recce-source/recce/util/onboarding_state.py +45 -0
  493. package/recce-source/recce/util/perf_tracking.py +85 -0
  494. package/recce-source/recce/util/pydantic_model.py +22 -0
  495. package/recce-source/recce/util/recce_cloud.py +454 -0
  496. package/recce-source/recce/util/singleton.py +18 -0
  497. package/recce-source/recce/util/startup_perf.py +121 -0
  498. package/recce-source/recce/yaml/__init__.py +58 -0
  499. package/recce-source/recce_cloud/README.md +780 -0
  500. package/recce-source/recce_cloud/VERSION +1 -0
  501. package/recce-source/recce_cloud/__init__.py +24 -0
  502. package/recce-source/recce_cloud/api/__init__.py +17 -0
  503. package/recce-source/recce_cloud/api/base.py +132 -0
  504. package/recce-source/recce_cloud/api/client.py +186 -0
  505. package/recce-source/recce_cloud/api/exceptions.py +26 -0
  506. package/recce-source/recce_cloud/api/factory.py +63 -0
  507. package/recce-source/recce_cloud/api/github.py +106 -0
  508. package/recce-source/recce_cloud/api/gitlab.py +111 -0
  509. package/recce-source/recce_cloud/artifact.py +57 -0
  510. package/recce-source/recce_cloud/ci_providers/__init__.py +9 -0
  511. package/recce-source/recce_cloud/ci_providers/base.py +82 -0
  512. package/recce-source/recce_cloud/ci_providers/detector.py +147 -0
  513. package/recce-source/recce_cloud/ci_providers/github_actions.py +136 -0
  514. package/recce-source/recce_cloud/ci_providers/gitlab_ci.py +130 -0
  515. package/recce-source/recce_cloud/cli.py +434 -0
  516. package/recce-source/recce_cloud/download.py +230 -0
  517. package/recce-source/recce_cloud/hatch_build.py +20 -0
  518. package/recce-source/recce_cloud/pyproject.toml +49 -0
  519. package/recce-source/recce_cloud/upload.py +214 -0
  520. package/recce-source/test.py +0 -0
  521. package/recce-source/tests/__init__.py +0 -0
  522. package/recce-source/tests/adapter/__init__.py +0 -0
  523. package/recce-source/tests/adapter/dbt_adapter/__init__.py +0 -0
  524. package/recce-source/tests/adapter/dbt_adapter/conftest.py +17 -0
  525. package/recce-source/tests/adapter/dbt_adapter/dbt_test_helper.py +298 -0
  526. package/recce-source/tests/adapter/dbt_adapter/test_dbt_adapter.py +25 -0
  527. package/recce-source/tests/adapter/dbt_adapter/test_dbt_cll.py +717 -0
  528. package/recce-source/tests/adapter/dbt_adapter/test_proj/dbt_project.yml +4 -0
  529. package/recce-source/tests/adapter/dbt_adapter/test_proj/manifest.json +1 -0
  530. package/recce-source/tests/adapter/dbt_adapter/test_proj/package-lock.yml +8 -0
  531. package/recce-source/tests/adapter/dbt_adapter/test_proj/packages.yml +7 -0
  532. package/recce-source/tests/adapter/dbt_adapter/test_proj/profiles.yml +6 -0
  533. package/recce-source/tests/adapter/dbt_adapter/test_selector.py +205 -0
  534. package/recce-source/tests/apis/__init__.py +0 -0
  535. package/recce-source/tests/apis/row_count_diff.json +59 -0
  536. package/recce-source/tests/apis/test_check_events_api.py +615 -0
  537. package/recce-source/tests/apis/test_run_func.py +433 -0
  538. package/recce-source/tests/catalog.json +527 -0
  539. package/recce-source/tests/data/manifest/base/catalog.json +1 -0
  540. package/recce-source/tests/data/manifest/base/manifest.json +1 -0
  541. package/recce-source/tests/data/manifest/pr2/catalog.json +1 -0
  542. package/recce-source/tests/data/manifest/pr2/manifest.json +1 -0
  543. package/recce-source/tests/manifest.json +10655 -0
  544. package/recce-source/tests/models/__init__.py +0 -0
  545. package/recce-source/tests/models/test_check.py +731 -0
  546. package/recce-source/tests/models/test_run_models.py +295 -0
  547. package/recce-source/tests/recce_cloud/__init__.py +0 -0
  548. package/recce-source/tests/recce_cloud/test_ci_providers.py +351 -0
  549. package/recce-source/tests/recce_cloud/test_cli.py +735 -0
  550. package/recce-source/tests/recce_cloud/test_client.py +379 -0
  551. package/recce-source/tests/recce_cloud/test_platform_clients.py +483 -0
  552. package/recce-source/tests/recce_state.json +1 -0
  553. package/recce-source/tests/state/test_cloud.py +719 -0
  554. package/recce-source/tests/state/test_local.py +164 -0
  555. package/recce-source/tests/state/test_state_loader.py +211 -0
  556. package/recce-source/tests/tasks/__init__.py +0 -0
  557. package/recce-source/tests/tasks/conftest.py +4 -0
  558. package/recce-source/tests/tasks/test_histogram.py +129 -0
  559. package/recce-source/tests/tasks/test_lineage.py +55 -0
  560. package/recce-source/tests/tasks/test_preset_checks.py +64 -0
  561. package/recce-source/tests/tasks/test_profile.py +397 -0
  562. package/recce-source/tests/tasks/test_query.py +528 -0
  563. package/recce-source/tests/tasks/test_row_count.py +133 -0
  564. package/recce-source/tests/tasks/test_schema.py +122 -0
  565. package/recce-source/tests/tasks/test_top_k.py +77 -0
  566. package/recce-source/tests/tasks/test_utils.py +439 -0
  567. package/recce-source/tests/tasks/test_valuediff.py +361 -0
  568. package/recce-source/tests/test_cli.py +236 -0
  569. package/recce-source/tests/test_cli_mcp_optional.py +45 -0
  570. package/recce-source/tests/test_cloud_listing_cli.py +324 -0
  571. package/recce-source/tests/test_config.py +43 -0
  572. package/recce-source/tests/test_connect_to_cloud.py +82 -0
  573. package/recce-source/tests/test_core.py +174 -0
  574. package/recce-source/tests/test_dbt.py +36 -0
  575. package/recce-source/tests/test_mcp_server.py +505 -0
  576. package/recce-source/tests/test_pull_request.py +130 -0
  577. package/recce-source/tests/test_server.py +202 -0
  578. package/recce-source/tests/test_server_lifespan.py +138 -0
  579. package/recce-source/tests/test_summary.py +73 -0
  580. package/recce-source/tests/util/__init__.py +0 -0
  581. package/recce-source/tests/util/cloud/__init__.py +0 -0
  582. package/recce-source/tests/util/cloud/test_check_events.py +255 -0
  583. package/recce-source/tests/util/cloud/test_checks.py +204 -0
  584. package/recce-source/tests/util/test_api_token.py +119 -0
  585. package/recce-source/tests/util/test_breaking.py +1427 -0
  586. package/recce-source/tests/util/test_cll.py +706 -0
  587. package/recce-source/tests/util/test_lineage.py +122 -0
  588. package/recce-source/tests/util/test_onboarding_state.py +84 -0
  589. package/recce-source/tests/util/test_recce_cloud.py +231 -0
  590. package/recce-source/tox.ini +40 -0
  591. package/recce-source/uv.lock +3928 -0
  592. package/src/api/index.ts +32 -0
  593. package/src/components/index.ts +154 -0
  594. package/src/global-styles.css +81 -0
  595. package/src/global.d.ts +14 -0
  596. package/src/hooks/index.ts +56 -0
  597. package/src/index.ts +17 -0
  598. package/src/lib/hooks/RouteConfigContext.ts +139 -0
  599. package/src/lib/hooks/useAppRouter.ts +240 -0
  600. package/src/mui-augmentation.d.ts +139 -0
  601. package/src/theme/index.ts +13 -0
  602. package/src/theme.ts +23 -0
  603. package/src/types/index.ts +23 -0
  604. package/dist/RecceCheckContext-DPpu9nG5.js +0 -303
  605. package/dist/RecceCheckContext-DPpu9nG5.js.map +0 -1
  606. package/dist/RecceCheckContext-bXdfQLGG.mjs +0 -229
  607. package/dist/RecceCheckContext-bXdfQLGG.mjs.map +0 -1
  608. package/dist/hooks-B9hsc1oD.js +0 -40
  609. package/dist/index-BNUP2V_N.d.ts.map +0 -1
  610. package/dist/index-DOPZuhD8.d.mts.map +0 -1
  611. package/dist/state-B9yzhuKs.mjs.map +0 -1
  612. package/dist/state-DOUPNifc.css.map +0 -1
  613. package/dist/state-IA7HWYOs.css.map +0 -1
  614. package/dist/state-lPCQsWy5.js.map +0 -1
  615. package/dist/theme.d.mts.map +0 -1
  616. package/dist/theme.d.ts.map +0 -1
  617. package/dist/urls-B1Ymdoz-.mjs.map +0 -1
  618. package/dist/urls-C4eAc82S.js.map +0 -1
  619. package/dist/version-Dh8sZhvs.js +0 -147
  620. package/dist/version-Dh8sZhvs.js.map +0 -1
  621. package/dist/version-OnOKzBeQ.mjs +0 -93
  622. package/dist/version-OnOKzBeQ.mjs.map +0 -1
@@ -0,0 +1,951 @@
1
+ /**
2
+ * @file toSchemaDataGrid.test.ts
3
+ * @description Tests for schema grid generators
4
+ *
5
+ * Tests cover:
6
+ * - mergeColumns: Column schema merging with status detection
7
+ * - toSchemaDataGrid: Diff view grid generation
8
+ * - toSingleEnvDataGrid: Single environment grid generation
9
+ */
10
+
11
+ import type { CellClassParams } from "ag-grid-community";
12
+ import React from "react";
13
+ import { NodeData } from "@/lib/api/info";
14
+ import { RowObjectType } from "@/lib/api/types";
15
+ import {
16
+ mergeColumns,
17
+ toSchemaDataGrid,
18
+ toSingleEnvDataGrid,
19
+ } from "./toSchemaDataGrid";
20
+
21
+ // ============================================================================
22
+ // Mocks
23
+ // ============================================================================
24
+
25
+ // Mock ag-grid-community to avoid ES module parsing issues
26
+ jest.mock("ag-grid-community", () => ({
27
+ ModuleRegistry: {
28
+ registerModules: jest.fn(),
29
+ },
30
+ }));
31
+
32
+ // ============================================================================
33
+ // Helper to create mock CellClassParams
34
+ // ============================================================================
35
+
36
+ /**
37
+ * Helper to create mock CellClassParams from a row
38
+ * This is needed because AG Grid cellClass functions expect CellClassParams
39
+ */
40
+ const createCellClassParams = (
41
+ row: RowObjectType,
42
+ ): CellClassParams<RowObjectType> =>
43
+ ({
44
+ data: row,
45
+ value: undefined,
46
+ node: undefined,
47
+ colDef: {},
48
+ column: {},
49
+ api: {},
50
+ rowIndex: 0,
51
+ }) as unknown as CellClassParams<RowObjectType>;
52
+
53
+ // Mock the schemaCells module
54
+ jest.mock("@/components/ui/dataGrid/schemaCells", () => ({
55
+ createColumnNameRenderer: jest.fn(() => jest.fn()),
56
+ createSingleEnvColumnNameRenderer: jest.fn(() => jest.fn()),
57
+ renderIndexCell: jest.fn(),
58
+ renderTypeCell: jest.fn(),
59
+ }));
60
+
61
+ // ============================================================================
62
+ // Types for testing (avoids ESM import issues with ag-grid-community)
63
+ // ============================================================================
64
+
65
+ /**
66
+ * Test-friendly Column type (mirrors AG Grid ColDef)
67
+ */
68
+ interface TestColumn {
69
+ field: string;
70
+ headerName?: React.ReactNode;
71
+ width?: number;
72
+ minWidth?: number;
73
+ resizable?: boolean;
74
+ cellClass?:
75
+ | string
76
+ | ((params: CellClassParams<RowObjectType>) => string | undefined);
77
+ headerClass?: string;
78
+ cellRenderer?: unknown;
79
+ }
80
+
81
+ // ============================================================================
82
+ // Test Helpers
83
+ // ============================================================================
84
+
85
+ /**
86
+ * Cast a column to TestColumn for accessing properties
87
+ */
88
+ function asColumn(col: unknown): TestColumn {
89
+ return col as TestColumn;
90
+ }
91
+
92
+ /**
93
+ * Get a specific column by index and cast to TestColumn
94
+ */
95
+ function getColumn(columns: unknown[], index: number): TestColumn {
96
+ return columns[index] as TestColumn;
97
+ }
98
+
99
+ /**
100
+ * Creates a NodeData["columns"] structure for testing
101
+ */
102
+ function createColumns(columns: Record<string, string>): NodeData["columns"] {
103
+ const result: NodeData["columns"] = {};
104
+ Object.entries(columns).forEach(([name, type]) => {
105
+ result[name] = { name, type };
106
+ });
107
+ return result;
108
+ }
109
+
110
+ /**
111
+ * Creates a minimal NodeData for testing
112
+ */
113
+ function createNodeData(name: string): NodeData {
114
+ return {
115
+ id: `model.test.${name}`,
116
+ name,
117
+ resource_type: "model",
118
+ columns: {},
119
+ } as NodeData;
120
+ }
121
+
122
+ // ============================================================================
123
+ // mergeColumns Tests
124
+ // ============================================================================
125
+
126
+ describe("mergeColumns", () => {
127
+ test("merges identical schemas", () => {
128
+ const columns = createColumns({ id: "INT", name: "VARCHAR" });
129
+
130
+ const result = mergeColumns(columns, columns);
131
+
132
+ expect(Object.keys(result)).toEqual(["id", "name"]);
133
+ expect(result.id.reordered).toBe(false);
134
+ expect(result.name.reordered).toBe(false);
135
+ });
136
+
137
+ test("detects added columns", () => {
138
+ const base = createColumns({ id: "INT" });
139
+ const current = createColumns({ id: "INT", email: "VARCHAR" });
140
+
141
+ const result = mergeColumns(base, current);
142
+
143
+ expect(Object.keys(result)).toContain("email");
144
+ expect(result.email.baseIndex).toBeUndefined();
145
+ expect(result.email.currentIndex).toBe(2);
146
+ });
147
+
148
+ test("detects removed columns", () => {
149
+ const base = createColumns({ id: "INT", legacy: "VARCHAR" });
150
+ const current = createColumns({ id: "INT" });
151
+
152
+ const result = mergeColumns(base, current);
153
+
154
+ expect(Object.keys(result)).toContain("legacy");
155
+ expect(result.legacy.baseIndex).toBe(2);
156
+ expect(result.legacy.currentIndex).toBeUndefined();
157
+ });
158
+
159
+ test("detects reordered columns", () => {
160
+ const base = createColumns({ id: "INT", name: "VARCHAR", age: "INT" });
161
+ const current = createColumns({ id: "INT", age: "INT", name: "VARCHAR" });
162
+
163
+ const result = mergeColumns(base, current);
164
+
165
+ // When columns swap positions, at least one is marked as reordered
166
+ // Note: mergeKeysWithStatus may not mark ALL swapped columns as reordered
167
+ expect(result.name.reordered).toBe(true);
168
+ expect(result.id.reordered).toBe(false);
169
+ });
170
+
171
+ test("detects type changes", () => {
172
+ const base = createColumns({ age: "INT" });
173
+ const current = createColumns({ age: "DECIMAL" });
174
+
175
+ const result = mergeColumns(base, current);
176
+
177
+ expect(result.age.baseType).toBe("INT");
178
+ expect(result.age.currentType).toBe("DECIMAL");
179
+ });
180
+
181
+ test("handles empty base columns", () => {
182
+ const current = createColumns({ id: "INT", name: "VARCHAR" });
183
+
184
+ const result = mergeColumns({}, current);
185
+
186
+ expect(Object.keys(result)).toEqual(["id", "name"]);
187
+ expect(result.id.baseIndex).toBeUndefined();
188
+ expect(result.id.currentIndex).toBe(1);
189
+ });
190
+
191
+ test("handles empty current columns", () => {
192
+ const base = createColumns({ id: "INT", name: "VARCHAR" });
193
+
194
+ const result = mergeColumns(base, {});
195
+
196
+ expect(Object.keys(result)).toEqual(["id", "name"]);
197
+ expect(result.id.baseIndex).toBe(1);
198
+ expect(result.id.currentIndex).toBeUndefined();
199
+ });
200
+
201
+ test("handles both empty", () => {
202
+ const result = mergeColumns({}, {});
203
+
204
+ expect(Object.keys(result)).toHaveLength(0);
205
+ });
206
+
207
+ test("handles undefined inputs", () => {
208
+ const result = mergeColumns(undefined, undefined);
209
+
210
+ expect(Object.keys(result)).toHaveLength(0);
211
+ });
212
+
213
+ test("filters null column entries", () => {
214
+ const base: NodeData["columns"] = {
215
+ id: { name: "id", type: "INT" },
216
+ broken: null as unknown as { name: string; type: string },
217
+ };
218
+ const current = createColumns({ id: "INT" });
219
+
220
+ const result = mergeColumns(base, current);
221
+
222
+ // broken column should still appear in keys (merged from both)
223
+ // but its baseIndex should be undefined since it was null
224
+ expect(result.id.baseIndex).toBe(1);
225
+ });
226
+
227
+ test("preserves order from merge", () => {
228
+ const base = createColumns({
229
+ id: "INT",
230
+ user_id: "INT",
231
+ name: "VARCHAR",
232
+ age: "INT",
233
+ });
234
+ const current = createColumns({
235
+ id: "INT",
236
+ fullname: "VARCHAR",
237
+ lastname: "VARCHAR",
238
+ age: "DECIMAL",
239
+ name: "VARCHAR",
240
+ });
241
+
242
+ const result = mergeColumns(base, current);
243
+
244
+ expect(Object.keys(result)).toStrictEqual([
245
+ "id",
246
+ "user_id",
247
+ "fullname",
248
+ "lastname",
249
+ "age",
250
+ "name",
251
+ ]);
252
+ });
253
+ });
254
+
255
+ // ============================================================================
256
+ // toSchemaDataGrid - Column Structure Tests
257
+ // ============================================================================
258
+
259
+ describe("toSchemaDataGrid - Column Structure", () => {
260
+ test("creates correct column structure with 3 merged columns", () => {
261
+ const schemaDiff = mergeColumns(
262
+ createColumns({ id: "INT" }),
263
+ createColumns({ id: "INT" }),
264
+ );
265
+
266
+ const { columns } = toSchemaDataGrid(schemaDiff);
267
+
268
+ expect(columns).toHaveLength(3);
269
+ expect(getColumn(columns, 0).field).toBe("index");
270
+ expect(getColumn(columns, 1).field).toBe("name");
271
+ expect(getColumn(columns, 2).field).toBe("type");
272
+ });
273
+
274
+ test("index column has correct sizing", () => {
275
+ const schemaDiff = mergeColumns(
276
+ createColumns({ id: "INT" }),
277
+ createColumns({ id: "INT" }),
278
+ );
279
+
280
+ const { columns } = toSchemaDataGrid(schemaDiff);
281
+
282
+ const indexCol = getColumn(columns, 0);
283
+
284
+ expect(indexCol.minWidth).toBe(35);
285
+ expect(indexCol.width).toBe(35);
286
+ });
287
+
288
+ test("all columns are resizable", () => {
289
+ const schemaDiff = mergeColumns(
290
+ createColumns({ id: "INT" }),
291
+ createColumns({ id: "INT" }),
292
+ );
293
+
294
+ const { columns } = toSchemaDataGrid(schemaDiff);
295
+
296
+ columns.forEach((col) => {
297
+ expect(asColumn(col).resizable).toBe(true);
298
+ });
299
+ });
300
+ });
301
+
302
+ // ============================================================================
303
+ // toSchemaDataGrid - Row Generation Tests
304
+ // ============================================================================
305
+
306
+ describe("toSchemaDataGrid - Row Generation", () => {
307
+ test("returns rows from schemaDiff", () => {
308
+ const schemaDiff = mergeColumns(
309
+ createColumns({ id: "INT", name: "VARCHAR" }),
310
+ createColumns({ id: "INT", name: "VARCHAR" }),
311
+ );
312
+
313
+ const { rows } = toSchemaDataGrid(schemaDiff);
314
+
315
+ expect(rows).toHaveLength(2);
316
+ expect(rows.map((r) => r.name)).toEqual(["id", "name"]);
317
+ });
318
+
319
+ test("rows have __status property", () => {
320
+ const schemaDiff = mergeColumns(
321
+ createColumns({ id: "INT" }),
322
+ createColumns({ id: "INT" }),
323
+ );
324
+
325
+ const { rows } = toSchemaDataGrid(schemaDiff);
326
+
327
+ rows.forEach((row) => {
328
+ expect("__status" in row).toBe(true);
329
+ });
330
+ });
331
+
332
+ test("handles empty schemaDiff", () => {
333
+ const schemaDiff = mergeColumns({}, {});
334
+
335
+ const { rows } = toSchemaDataGrid(schemaDiff);
336
+
337
+ expect(rows).toHaveLength(0);
338
+ });
339
+ });
340
+
341
+ // ============================================================================
342
+ // toSchemaDataGrid - Options Tests
343
+ // ============================================================================
344
+
345
+ describe("toSchemaDataGrid - Options", () => {
346
+ test("includes renderCell for name column when node provided", () => {
347
+ const schemaDiff = mergeColumns(
348
+ createColumns({ id: "INT" }),
349
+ createColumns({ id: "INT" }),
350
+ );
351
+ const node = createNodeData("test_model");
352
+
353
+ const { columns } = toSchemaDataGrid(schemaDiff, { node });
354
+
355
+ const nameColumn = getColumn(columns, 1);
356
+ expect(nameColumn.cellRenderer).toBeDefined();
357
+ });
358
+
359
+ test("omits renderCell for name column when node not provided", () => {
360
+ const schemaDiff = mergeColumns(
361
+ createColumns({ id: "INT" }),
362
+ createColumns({ id: "INT" }),
363
+ );
364
+
365
+ const { columns } = toSchemaDataGrid(schemaDiff);
366
+
367
+ const nameColumn = getColumn(columns, 1);
368
+ expect(nameColumn.cellRenderer).toBeUndefined();
369
+ });
370
+
371
+ test("accepts cllRunningMap option", () => {
372
+ const schemaDiff = mergeColumns(
373
+ createColumns({ id: "INT" }),
374
+ createColumns({ id: "INT" }),
375
+ );
376
+ const node = createNodeData("test_model");
377
+ const cllRunningMap = new Map([["id", true]]);
378
+
379
+ // Should not throw
380
+ const { columns } = toSchemaDataGrid(schemaDiff, { node, cllRunningMap });
381
+
382
+ expect(columns).toHaveLength(3);
383
+ });
384
+ });
385
+
386
+ // ============================================================================
387
+ // toSchemaDataGrid - Cell Class Tests
388
+ // ============================================================================
389
+
390
+ describe("toSchemaDataGrid - Cell Classes", () => {
391
+ test("index column has cellClass function", () => {
392
+ const schemaDiff = mergeColumns(
393
+ createColumns({ id: "INT" }),
394
+ createColumns({ id: "INT" }),
395
+ );
396
+
397
+ const { columns } = toSchemaDataGrid(schemaDiff);
398
+
399
+ const indexCol = getColumn(columns, 0);
400
+
401
+ expect(typeof indexCol.cellClass).toBe("function");
402
+ });
403
+
404
+ test("index cellClass returns reordered class when reordered", () => {
405
+ const schemaDiff = mergeColumns(
406
+ createColumns({ id: "INT", name: "VARCHAR" }),
407
+ createColumns({ name: "VARCHAR", id: "INT" }),
408
+ );
409
+
410
+ const { columns, rows } = toSchemaDataGrid(schemaDiff);
411
+
412
+ const indexCol = getColumn(columns, 0);
413
+ const cellClassFn = indexCol.cellClass as (
414
+ params: CellClassParams<RowObjectType>,
415
+ ) => string;
416
+
417
+ const reorderedRow = rows.find((r) => r.reordered === true);
418
+ expect(reorderedRow).toBeDefined();
419
+ if (reorderedRow) {
420
+ const result = cellClassFn(createCellClassParams(reorderedRow));
421
+ expect(result).toContain("column-index-reordered");
422
+ }
423
+ });
424
+
425
+ test("index cellClass returns normal class when not reordered", () => {
426
+ const schemaDiff = mergeColumns(
427
+ createColumns({ id: "INT" }),
428
+ createColumns({ id: "INT" }),
429
+ );
430
+
431
+ const { columns, rows } = toSchemaDataGrid(schemaDiff);
432
+
433
+ const indexCol = getColumn(columns, 0);
434
+ const cellClassFn = indexCol.cellClass as (
435
+ params: CellClassParams<RowObjectType>,
436
+ ) => string;
437
+
438
+ const result = cellClassFn(createCellClassParams(rows[0]));
439
+ expect(result).toBe("schema-column schema-column-index");
440
+ expect(result).not.toContain("reordered");
441
+ });
442
+
443
+ test("name column has schema-column cellClass", () => {
444
+ const schemaDiff = mergeColumns(
445
+ createColumns({ id: "INT" }),
446
+ createColumns({ id: "INT" }),
447
+ );
448
+
449
+ const { columns, rows } = toSchemaDataGrid(schemaDiff);
450
+
451
+ const nameCol = getColumn(columns, 1);
452
+ const cellClassFn = nameCol.cellClass as (
453
+ params: CellClassParams<RowObjectType>,
454
+ ) => string;
455
+
456
+ const result = cellClassFn(createCellClassParams(rows[0]));
457
+ expect(result).toBe("schema-column");
458
+ expect(result).not.toContain("type-changed");
459
+ });
460
+
461
+ test("type column has schema-column cellClass", () => {
462
+ const schemaDiff = mergeColumns(
463
+ createColumns({ id: "INT" }),
464
+ createColumns({ id: "INT" }),
465
+ );
466
+
467
+ const { columns, rows } = toSchemaDataGrid(schemaDiff);
468
+
469
+ const typeCol = getColumn(columns, 2);
470
+ const cellClassFn = typeCol.cellClass as (
471
+ params: CellClassParams<RowObjectType>,
472
+ ) => string;
473
+
474
+ expect(cellClassFn(createCellClassParams(rows[0]))).toBe("schema-column");
475
+ });
476
+ });
477
+
478
+ // ============================================================================
479
+ // toSingleEnvDataGrid - Column Structure Tests
480
+ // ============================================================================
481
+
482
+ describe("toSingleEnvDataGrid - Column Structure", () => {
483
+ test("creates correct column structure", () => {
484
+ const columns = createColumns({ id: "INT", name: "VARCHAR" });
485
+
486
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns);
487
+
488
+ expect(gridColumns).toHaveLength(3);
489
+ expect(getColumn(gridColumns, 0).field).toBe("index");
490
+ expect(getColumn(gridColumns, 1).field).toBe("name");
491
+ expect(getColumn(gridColumns, 2).field).toBe("type");
492
+ });
493
+
494
+ test("index column has correct sizing", () => {
495
+ const columns = createColumns({ id: "INT" });
496
+
497
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns);
498
+
499
+ const indexCol = getColumn(gridColumns, 0);
500
+ expect(indexCol.minWidth).toBe(35);
501
+ expect(indexCol.width).toBe(35);
502
+ });
503
+
504
+ test("all columns are resizable", () => {
505
+ const columns = createColumns({ id: "INT" });
506
+
507
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns);
508
+
509
+ gridColumns.forEach((col) => {
510
+ expect(asColumn(col).resizable).toBe(true);
511
+ });
512
+ });
513
+ });
514
+
515
+ // ============================================================================
516
+ // toSingleEnvDataGrid - Row Generation Tests
517
+ // ============================================================================
518
+
519
+ describe("toSingleEnvDataGrid - Row Generation", () => {
520
+ test("generates rows from columns", () => {
521
+ const columns = createColumns({ id: "INT", name: "VARCHAR", age: "INT" });
522
+
523
+ const { rows } = toSingleEnvDataGrid(columns);
524
+
525
+ expect(rows).toHaveLength(3);
526
+ expect(rows.map((r) => r.name)).toEqual(["id", "name", "age"]);
527
+ });
528
+
529
+ test("assigns sequential indices starting from 1", () => {
530
+ const columns = createColumns({ a: "INT", b: "INT", c: "INT" });
531
+
532
+ const { rows } = toSingleEnvDataGrid(columns);
533
+
534
+ expect(rows.map((r) => r.index)).toEqual([1, 2, 3]);
535
+ });
536
+
537
+ test("includes type from column definition", () => {
538
+ const columns = createColumns({ id: "INT", name: "VARCHAR" });
539
+
540
+ const { rows } = toSingleEnvDataGrid(columns);
541
+
542
+ expect(rows[0].type).toBe("INT");
543
+ expect(rows[1].type).toBe("VARCHAR");
544
+ });
545
+
546
+ test("rows have __status property", () => {
547
+ const columns = createColumns({ id: "INT" });
548
+
549
+ const { rows } = toSingleEnvDataGrid(columns);
550
+
551
+ rows.forEach((row) => {
552
+ expect("__status" in row).toBe(true);
553
+ expect(row.__status).toBeUndefined();
554
+ });
555
+ });
556
+
557
+ test("filters null columns", () => {
558
+ const columns: NodeData["columns"] = {
559
+ id: { name: "id", type: "INT" },
560
+ broken: null as unknown as { name: string; type: string },
561
+ name: { name: "name", type: "VARCHAR" },
562
+ };
563
+
564
+ const { rows } = toSingleEnvDataGrid(columns);
565
+
566
+ expect(rows).toHaveLength(2);
567
+ expect(rows.map((r) => r.name)).toEqual(["id", "name"]);
568
+ });
569
+
570
+ test("handles empty columns", () => {
571
+ const { rows } = toSingleEnvDataGrid({});
572
+
573
+ expect(rows).toHaveLength(0);
574
+ });
575
+
576
+ test("handles undefined columns", () => {
577
+ const { rows } = toSingleEnvDataGrid(undefined);
578
+
579
+ expect(rows).toHaveLength(0);
580
+ });
581
+ });
582
+
583
+ // ============================================================================
584
+ // toSingleEnvDataGrid - Options Tests
585
+ // ============================================================================
586
+
587
+ describe("toSingleEnvDataGrid - Options", () => {
588
+ test("includes renderCell when node provided", () => {
589
+ const columns = createColumns({ id: "INT" });
590
+ const node = createNodeData("test_model");
591
+
592
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns, { node });
593
+
594
+ const nameColumn = getColumn(gridColumns, 1);
595
+ expect(nameColumn.cellRenderer).toBeDefined();
596
+ });
597
+
598
+ test("omits renderCell when node not provided", () => {
599
+ const columns = createColumns({ id: "INT" });
600
+
601
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns);
602
+
603
+ const nameColumn = getColumn(gridColumns, 1);
604
+ expect(nameColumn.cellRenderer).toBeUndefined();
605
+ });
606
+
607
+ test("accepts cllRunningMap option", () => {
608
+ const columns = createColumns({ id: "INT" });
609
+ const node = createNodeData("test_model");
610
+ const cllRunningMap = new Map([["id", true]]);
611
+
612
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns, {
613
+ node,
614
+ cllRunningMap,
615
+ });
616
+
617
+ expect(gridColumns).toHaveLength(3);
618
+ });
619
+ });
620
+
621
+ // ============================================================================
622
+ // toSingleEnvDataGrid - Cell Class Tests
623
+ // ============================================================================
624
+
625
+ describe("toSingleEnvDataGrid - Cell Classes", () => {
626
+ test("index column has static cellClass", () => {
627
+ const columns = createColumns({ id: "INT" });
628
+
629
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns);
630
+
631
+ const indexCol = getColumn(gridColumns, 0);
632
+ expect(indexCol.cellClass).toBe("schema-column schema-column-index");
633
+ });
634
+
635
+ test("name column has schema-column cellClass", () => {
636
+ const columns = createColumns({ id: "INT" });
637
+
638
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns);
639
+
640
+ const nameCol = getColumn(gridColumns, 1);
641
+ expect(nameCol.cellClass).toBe("schema-column");
642
+ });
643
+
644
+ test("type column has schema-column cellClass", () => {
645
+ const columns = createColumns({ id: "INT" });
646
+
647
+ const { columns: gridColumns } = toSingleEnvDataGrid(columns);
648
+
649
+ const typeCol = getColumn(gridColumns, 2);
650
+ expect(typeCol.cellClass).toBe("schema-column");
651
+ });
652
+
653
+ // ============================================================================
654
+ // mergeColumns - Edge Cases
655
+ // ============================================================================
656
+
657
+ describe("mergeColumns - Edge Cases", () => {
658
+ test("handles columns with special characters in names", () => {
659
+ const base = createColumns({ "user-id": "INT", "first.name": "VARCHAR" });
660
+ const current = createColumns({
661
+ "user-id": "INT",
662
+ "first.name": "VARCHAR",
663
+ });
664
+
665
+ const result = mergeColumns(base, current);
666
+
667
+ expect(Object.keys(result)).toContain("user-id");
668
+ expect(Object.keys(result)).toContain("first.name");
669
+ expect(result["user-id"].baseIndex).toBe(1);
670
+ expect(result["first.name"].currentIndex).toBe(2);
671
+ });
672
+
673
+ test("handles columns with spaces in names", () => {
674
+ const base = createColumns({ "User ID": "INT", "Full Name": "VARCHAR" });
675
+ const current = createColumns({
676
+ "User ID": "INT",
677
+ "Full Name": "VARCHAR",
678
+ });
679
+
680
+ const result = mergeColumns(base, current);
681
+
682
+ expect(result["User ID"]).toBeDefined();
683
+ expect(result["Full Name"]).toBeDefined();
684
+ });
685
+
686
+ test("handles columns with unicode characters", () => {
687
+ const base = createColumns({ 用户名: "VARCHAR", prénom: "VARCHAR" });
688
+ const current = createColumns({ 用户名: "VARCHAR", prénom: "VARCHAR" });
689
+
690
+ const result = mergeColumns(base, current);
691
+
692
+ // biome-ignore lint/complexity/useLiteralKeys: Testing unicode keys
693
+ expect(result["用户名"]).toBeDefined();
694
+ // biome-ignore lint/complexity/useLiteralKeys: Testing unicode keys
695
+ expect(result["prénom"]).toBeDefined();
696
+ });
697
+
698
+ test("treats column names as case-sensitive", () => {
699
+ const base = createColumns({ ID: "INT", id: "INT" });
700
+ const current = createColumns({ ID: "INT", id: "INT" });
701
+
702
+ const result = mergeColumns(base, current);
703
+
704
+ expect(Object.keys(result)).toContain("ID");
705
+ expect(Object.keys(result)).toContain("id");
706
+ expect(
707
+ Object.keys(result).filter((k) => k.toLowerCase() === "id"),
708
+ ).toHaveLength(2);
709
+ });
710
+
711
+ test("handles empty string column name", () => {
712
+ const base: NodeData["columns"] = {
713
+ "": { name: "", type: "INT" },
714
+ id: { name: "id", type: "INT" },
715
+ };
716
+ const current: NodeData["columns"] = {
717
+ "": { name: "", type: "INT" },
718
+ id: { name: "id", type: "INT" },
719
+ };
720
+
721
+ const result = mergeColumns(base, current);
722
+
723
+ expect(result[""]).toBeDefined();
724
+ expect(result[""].baseIndex).toBeDefined();
725
+ });
726
+
727
+ test("handles columns with very long type strings", () => {
728
+ const longType = "DECIMAL(38,18)";
729
+ const base = createColumns({ amount: longType });
730
+ const current = createColumns({ amount: longType });
731
+
732
+ const result = mergeColumns(base, current);
733
+
734
+ expect(result.amount.baseType).toBe(longType);
735
+ expect(result.amount.currentType).toBe(longType);
736
+ });
737
+
738
+ test("handles complex type changes", () => {
739
+ const base = createColumns({
740
+ data: "VARCHAR(255)",
741
+ amount: "DECIMAL(10,2)",
742
+ });
743
+ const current = createColumns({
744
+ data: "TEXT",
745
+ amount: "DECIMAL(18,4)",
746
+ });
747
+
748
+ const result = mergeColumns(base, current);
749
+
750
+ expect(result.data.baseType).toBe("VARCHAR(255)");
751
+ expect(result.data.currentType).toBe("TEXT");
752
+ expect(result.amount.baseType).toBe("DECIMAL(10,2)");
753
+ expect(result.amount.currentType).toBe("DECIMAL(18,4)");
754
+ });
755
+
756
+ test("handles large number of columns", () => {
757
+ const columns: Record<string, string> = {};
758
+ for (let i = 0; i < 100; i++) {
759
+ columns[`col_${i}`] = "VARCHAR";
760
+ }
761
+ const base = createColumns(columns);
762
+ const current = createColumns(columns);
763
+
764
+ const result = mergeColumns(base, current);
765
+
766
+ expect(Object.keys(result)).toHaveLength(100);
767
+ expect(result.col_0.baseIndex).toBe(1);
768
+ expect(result.col_99.currentIndex).toBe(100);
769
+ });
770
+
771
+ test("handles all columns removed", () => {
772
+ const base = createColumns({ id: "INT", name: "VARCHAR", age: "INT" });
773
+ const current: NodeData["columns"] = {};
774
+
775
+ const result = mergeColumns(base, current);
776
+
777
+ expect(Object.keys(result)).toHaveLength(3);
778
+ Object.values(result).forEach((row) => {
779
+ expect(row.baseIndex).toBeDefined();
780
+ expect(row.currentIndex).toBeUndefined();
781
+ });
782
+ });
783
+
784
+ test("handles all columns added", () => {
785
+ const base: NodeData["columns"] = {};
786
+ const current = createColumns({ id: "INT", name: "VARCHAR", age: "INT" });
787
+
788
+ const result = mergeColumns(base, current);
789
+
790
+ expect(Object.keys(result)).toHaveLength(3);
791
+ Object.values(result).forEach((row) => {
792
+ expect(row.baseIndex).toBeUndefined();
793
+ expect(row.currentIndex).toBeDefined();
794
+ });
795
+ });
796
+
797
+ test("handles complete schema replacement", () => {
798
+ const base = createColumns({ old_id: "INT", old_name: "VARCHAR" });
799
+ const current = createColumns({ new_id: "INT", new_name: "VARCHAR" });
800
+
801
+ const result = mergeColumns(base, current);
802
+
803
+ expect(Object.keys(result)).toHaveLength(4);
804
+ expect(result.old_id.currentIndex).toBeUndefined();
805
+ expect(result.new_id.baseIndex).toBeUndefined();
806
+ });
807
+
808
+ test("handles mixed null and valid columns", () => {
809
+ const base: NodeData["columns"] = {
810
+ id: { name: "id", type: "INT" },
811
+ null1: null as unknown as { name: string; type: string },
812
+ name: { name: "name", type: "VARCHAR" },
813
+ null2: null as unknown as { name: string; type: string },
814
+ };
815
+ const current: NodeData["columns"] = {
816
+ id: { name: "id", type: "INT" },
817
+ name: { name: "name", type: "VARCHAR" },
818
+ };
819
+
820
+ const result = mergeColumns(base, current);
821
+
822
+ // Null columns appear in keys but don't get indices
823
+ expect(result.id.baseIndex).toBe(1);
824
+ expect(result.name.baseIndex).toBe(2);
825
+ expect(result.null1?.baseIndex).toBeUndefined();
826
+ });
827
+ });
828
+
829
+ // ============================================================================
830
+ // toSchemaDataGrid - Edge Cases
831
+ // ============================================================================
832
+
833
+ describe("toSchemaDataGrid - Edge Cases", () => {
834
+ test("handles empty schema diff", () => {
835
+ const schemaDiff = mergeColumns({}, {});
836
+
837
+ const { columns, rows } = toSchemaDataGrid(schemaDiff);
838
+
839
+ expect(columns).toHaveLength(3);
840
+ expect(rows).toHaveLength(0);
841
+ });
842
+
843
+ test("cell class handles row with only baseIndex (removed column)", () => {
844
+ const schemaDiff = mergeColumns(createColumns({ legacy: "INT" }), {});
845
+
846
+ const { columns, rows } = toSchemaDataGrid(schemaDiff);
847
+ const indexCol = getColumn(columns, 0);
848
+ const cellClassFn = indexCol.cellClass as (
849
+ params: CellClassParams<RowObjectType>,
850
+ ) => string;
851
+
852
+ // Row has baseIndex but no currentIndex
853
+ const result = cellClassFn(createCellClassParams(rows[0]));
854
+ expect(result).toBe("schema-column schema-column-index");
855
+ });
856
+
857
+ test("cell class handles row with only currentIndex (added column)", () => {
858
+ const schemaDiff = mergeColumns({}, createColumns({ new_col: "INT" }));
859
+
860
+ const { columns, rows } = toSchemaDataGrid(schemaDiff);
861
+ const indexCol = getColumn(columns, 0);
862
+ const cellClassFn = indexCol.cellClass as (
863
+ params: CellClassParams<RowObjectType>,
864
+ ) => string;
865
+
866
+ // Row has currentIndex but no baseIndex
867
+ const result = cellClassFn(createCellClassParams(rows[0]));
868
+ expect(result).toBe("schema-column schema-column-index");
869
+ });
870
+
871
+ test("handles schema with single column", () => {
872
+ const schemaDiff = mergeColumns(
873
+ createColumns({ id: "INT" }),
874
+ createColumns({ id: "INT" }),
875
+ );
876
+
877
+ const { rows } = toSchemaDataGrid(schemaDiff);
878
+
879
+ expect(rows).toHaveLength(1);
880
+ expect(rows[0].name).toBe("id");
881
+ });
882
+ });
883
+
884
+ // ============================================================================
885
+ // toSingleEnvDataGrid - Edge Cases
886
+ // ============================================================================
887
+
888
+ describe("toSingleEnvDataGrid - Edge Cases", () => {
889
+ test("handles columns with special characters", () => {
890
+ const columns = createColumns({
891
+ "user-id": "INT",
892
+ "first.name": "VARCHAR",
893
+ });
894
+
895
+ const { rows } = toSingleEnvDataGrid(columns);
896
+
897
+ expect(rows).toHaveLength(2);
898
+ expect(rows.map((r) => r.name)).toContain("user-id");
899
+ expect(rows.map((r) => r.name)).toContain("first.name");
900
+ });
901
+
902
+ test("handles single column", () => {
903
+ const columns = createColumns({ id: "INT" });
904
+
905
+ const { rows } = toSingleEnvDataGrid(columns);
906
+
907
+ expect(rows).toHaveLength(1);
908
+ expect(rows[0].index).toBe(1);
909
+ });
910
+
911
+ test("handles large number of columns", () => {
912
+ const cols: Record<string, string> = {};
913
+ for (let i = 0; i < 100; i++) {
914
+ cols[`col_${i}`] = "VARCHAR";
915
+ }
916
+ const columns = createColumns(cols);
917
+
918
+ const { rows } = toSingleEnvDataGrid(columns);
919
+
920
+ expect(rows).toHaveLength(100);
921
+ expect(rows[0].index).toBe(1);
922
+ expect(rows[99].index).toBe(100);
923
+ });
924
+
925
+ test("handles columns with undefined type", () => {
926
+ const columns: NodeData["columns"] = {
927
+ id: { name: "id", type: undefined as unknown as string },
928
+ };
929
+
930
+ const { rows } = toSingleEnvDataGrid(columns);
931
+
932
+ expect(rows).toHaveLength(1);
933
+ expect(rows[0].type).toBeUndefined();
934
+ });
935
+
936
+ test("preserves column order from input", () => {
937
+ const columns: NodeData["columns"] = {};
938
+ // Add in specific order
939
+ columns.zebra = { name: "zebra", type: "VARCHAR" };
940
+ columns.alpha = { name: "alpha", type: "VARCHAR" };
941
+ columns.beta = { name: "beta", type: "VARCHAR" };
942
+
943
+ const { rows } = toSingleEnvDataGrid(columns);
944
+
945
+ // Object.entries preserves insertion order
946
+ expect(rows[0].name).toBe("zebra");
947
+ expect(rows[1].name).toBe("alpha");
948
+ expect(rows[2].name).toBe("beta");
949
+ });
950
+ });
951
+ });