@datarecce/ui 0.1.30 → 0.1.31

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 (549) hide show
  1. package/dist/api.d.mts +1 -1
  2. package/dist/api.d.ts +1 -1
  3. package/dist/components.d.mts +1 -1
  4. package/dist/components.d.ts +1 -1
  5. package/dist/hooks.d.mts +1 -1
  6. package/dist/hooks.d.ts +1 -1
  7. package/dist/{index-BNUP2V_N.d.ts → index-B9lSPJTi.d.ts} +184 -2
  8. package/dist/index-B9lSPJTi.d.ts.map +1 -0
  9. package/dist/{index-DOPZuhD8.d.mts → index-IIXVIoOL.d.mts} +253 -71
  10. package/dist/index-IIXVIoOL.d.mts.map +1 -0
  11. package/dist/index.d.mts +2 -2
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +8 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +3 -2
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/styles.css +4 -0
  18. package/dist/theme.d.mts +2 -185
  19. package/dist/theme.d.ts +2 -185
  20. package/dist/types.d.mts +1 -1
  21. package/dist/types.d.ts +1 -1
  22. package/package.json +4 -2
  23. package/recce-source/.editorconfig +26 -0
  24. package/recce-source/.flake8 +37 -0
  25. package/recce-source/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
  26. package/recce-source/.github/ISSUE_TEMPLATE/custom.md +10 -0
  27. package/recce-source/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
  28. package/recce-source/.github/PULL_REQUEST_TEMPLATE.md +21 -0
  29. package/recce-source/.github/copilot-instructions.md +331 -0
  30. package/recce-source/.github/instructions/backend-instructions.md +541 -0
  31. package/recce-source/.github/instructions/frontend-instructions.md +317 -0
  32. package/recce-source/.github/workflows/build-statics.yaml +72 -0
  33. package/recce-source/.github/workflows/bump.yaml +48 -0
  34. package/recce-source/.github/workflows/integration-tests-cloud.yaml +92 -0
  35. package/recce-source/.github/workflows/integration-tests-sqlmesh.yaml +33 -0
  36. package/recce-source/.github/workflows/integration-tests.yaml +52 -0
  37. package/recce-source/.github/workflows/nightly.yaml +246 -0
  38. package/recce-source/.github/workflows/release.yaml +196 -0
  39. package/recce-source/.github/workflows/tests-js.yaml +58 -0
  40. package/recce-source/.github/workflows/tests-python.yaml +128 -0
  41. package/recce-source/.pre-commit-config.yaml +26 -0
  42. package/recce-source/CLAUDE.md +483 -0
  43. package/recce-source/CODE_OF_CONDUCT.md +128 -0
  44. package/recce-source/CONTRIBUTING.md +107 -0
  45. package/recce-source/LICENSE +201 -0
  46. package/recce-source/Makefile +126 -0
  47. package/recce-source/README.md +182 -0
  48. package/recce-source/RECCE_CLOUD.md +81 -0
  49. package/recce-source/SECURITY.md +25 -0
  50. package/recce-source/docs/PACKAGING.md +340 -0
  51. package/recce-source/docs/README.md +1 -0
  52. package/recce-source/integration_tests/dbt/dbt_project.yml +26 -0
  53. package/recce-source/integration_tests/dbt/models/customers.sql +69 -0
  54. package/recce-source/integration_tests/dbt/models/docs.md +14 -0
  55. package/recce-source/integration_tests/dbt/models/orders.sql +56 -0
  56. package/recce-source/integration_tests/dbt/models/schema.yml +82 -0
  57. package/recce-source/integration_tests/dbt/models/staging/schema.yml +31 -0
  58. package/recce-source/integration_tests/dbt/models/staging/stg_customers.sql +22 -0
  59. package/recce-source/integration_tests/dbt/models/staging/stg_orders.sql +23 -0
  60. package/recce-source/integration_tests/dbt/models/staging/stg_payments.sql +25 -0
  61. package/recce-source/integration_tests/dbt/packages.yml +7 -0
  62. package/recce-source/integration_tests/dbt/profiles.yml +8 -0
  63. package/recce-source/integration_tests/dbt/seeds/raw_customers.csv +101 -0
  64. package/recce-source/integration_tests/dbt/seeds/raw_orders.csv +100 -0
  65. package/recce-source/integration_tests/dbt/seeds/raw_payments.csv +114 -0
  66. package/recce-source/integration_tests/dbt/seeds/raw_statuses.csv +5 -0
  67. package/recce-source/integration_tests/dbt/smoke_test.sh +72 -0
  68. package/recce-source/integration_tests/dbt/smoke_test_cloud.sh +71 -0
  69. package/recce-source/integration_tests/sqlmesh/__init__.py +0 -0
  70. package/recce-source/integration_tests/sqlmesh/audits/assert_item_price_above_zero.sql +9 -0
  71. package/recce-source/integration_tests/sqlmesh/audits/items.sql +7 -0
  72. package/recce-source/integration_tests/sqlmesh/audits/order_items.sql +7 -0
  73. package/recce-source/integration_tests/sqlmesh/config.py +171 -0
  74. package/recce-source/integration_tests/sqlmesh/helper.py +20 -0
  75. package/recce-source/integration_tests/sqlmesh/hooks/__init__.py +0 -0
  76. package/recce-source/integration_tests/sqlmesh/macros/__init__.py +0 -0
  77. package/recce-source/integration_tests/sqlmesh/macros/macros.py +8 -0
  78. package/recce-source/integration_tests/sqlmesh/macros/macros.sql +8 -0
  79. package/recce-source/integration_tests/sqlmesh/macros/utils.py +11 -0
  80. package/recce-source/integration_tests/sqlmesh/metrics/metrics.sql +25 -0
  81. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_by_day.sql +41 -0
  82. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_lifetime.sql +60 -0
  83. package/recce-source/integration_tests/sqlmesh/models/customers.sql +32 -0
  84. package/recce-source/integration_tests/sqlmesh/models/items.py +95 -0
  85. package/recce-source/integration_tests/sqlmesh/models/marketing.sql +15 -0
  86. package/recce-source/integration_tests/sqlmesh/models/order_items.py +95 -0
  87. package/recce-source/integration_tests/sqlmesh/models/orders.py +70 -0
  88. package/recce-source/integration_tests/sqlmesh/models/raw_marketing.py +62 -0
  89. package/recce-source/integration_tests/sqlmesh/models/top_waiters.sql +23 -0
  90. package/recce-source/integration_tests/sqlmesh/models/waiter_as_customer_by_day.sql +29 -0
  91. package/recce-source/integration_tests/sqlmesh/models/waiter_names.sql +10 -0
  92. package/recce-source/integration_tests/sqlmesh/models/waiter_revenue_by_day.sql +29 -0
  93. package/recce-source/integration_tests/sqlmesh/models/waiters.py +62 -0
  94. package/recce-source/integration_tests/sqlmesh/prep_env.sh +16 -0
  95. package/recce-source/integration_tests/sqlmesh/schema.yaml +5 -0
  96. package/recce-source/integration_tests/sqlmesh/seeds/waiter_names.csv +11 -0
  97. package/recce-source/integration_tests/sqlmesh/test_server.sh +29 -0
  98. package/recce-source/integration_tests/sqlmesh/tests/test_customer_revenue_by_day.yaml +63 -0
  99. package/recce-source/integration_tests/sqlmesh/tests/test_order_items.yaml +72 -0
  100. package/recce-source/js/.editorconfig +27 -0
  101. package/recce-source/js/.env.development +5 -0
  102. package/recce-source/js/.husky/pre-commit +29 -0
  103. package/recce-source/js/.nvmrc +1 -0
  104. package/recce-source/js/README.md +39 -0
  105. package/recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx +65 -0
  106. package/recce-source/js/app/(mainComponents)/NavBar.tsx +228 -0
  107. package/recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx +107 -0
  108. package/recce-source/js/app/(mainComponents)/TopBar.tsx +252 -0
  109. package/recce-source/js/app/@lineage/default.tsx +20 -0
  110. package/recce-source/js/app/@lineage/page.tsx +14 -0
  111. package/recce-source/js/app/MainLayout.tsx +170 -0
  112. package/recce-source/js/app/Providers.tsx +49 -0
  113. package/recce-source/js/app/checks/page.tsx +296 -0
  114. package/recce-source/js/app/error.tsx +93 -0
  115. package/recce-source/js/app/favicon.ico +0 -0
  116. package/recce-source/js/app/global-error.tsx +115 -0
  117. package/recce-source/js/app/global.css +82 -0
  118. package/recce-source/js/app/layout.tsx +48 -0
  119. package/recce-source/js/app/lineage/page.tsx +15 -0
  120. package/recce-source/js/app/page.tsx +12 -0
  121. package/recce-source/js/app/query/page.tsx +8 -0
  122. package/recce-source/js/biome.json +313 -0
  123. package/recce-source/js/jest.config.js +34 -0
  124. package/recce-source/js/jest.globals.d.ts +32 -0
  125. package/recce-source/js/jest.setup.js +91 -0
  126. package/recce-source/js/next.config.js +16 -0
  127. package/recce-source/js/package-lock.json +13843 -0
  128. package/recce-source/js/package.json +123 -0
  129. package/recce-source/js/pnpm-lock.yaml +9235 -0
  130. package/recce-source/js/pnpm-workspace.yaml +6 -0
  131. package/recce-source/js/postcss.config.js +5 -0
  132. package/recce-source/js/public/auth_callback.html +68 -0
  133. package/recce-source/js/public/imgs/feedback/thumbs-down.png +0 -0
  134. package/recce-source/js/public/imgs/feedback/thumbs-up.png +0 -0
  135. package/recce-source/js/public/imgs/reload-image.svg +4 -0
  136. package/recce-source/js/public/logo/recce-logo-white.png +0 -0
  137. package/recce-source/js/src/components/AuthModal/AuthModal.tsx +202 -0
  138. package/recce-source/js/src/components/app/AvatarDropdown.tsx +159 -0
  139. package/recce-source/js/src/components/app/EnvInfo.tsx +357 -0
  140. package/recce-source/js/src/components/app/Filename.tsx +388 -0
  141. package/recce-source/js/src/components/app/SetupConnectionPopover.tsx +91 -0
  142. package/recce-source/js/src/components/app/StateExporter.tsx +57 -0
  143. package/recce-source/js/src/components/app/StateImporter.tsx +198 -0
  144. package/recce-source/js/src/components/app/StateSharing.tsx +145 -0
  145. package/recce-source/js/src/components/app/StateSynchronizer.tsx +205 -0
  146. package/recce-source/js/src/components/charts/HistogramChart.tsx +291 -0
  147. package/recce-source/js/src/components/charts/SquareIcon.tsx +51 -0
  148. package/recce-source/js/src/components/charts/TopKSummaryList.tsx +457 -0
  149. package/recce-source/js/src/components/charts/chartTheme.ts +74 -0
  150. package/recce-source/js/src/components/check/CheckBreadcrumb.tsx +97 -0
  151. package/recce-source/js/src/components/check/CheckDescription.tsx +134 -0
  152. package/recce-source/js/src/components/check/CheckDetail.tsx +797 -0
  153. package/recce-source/js/src/components/check/CheckEmptyState.tsx +84 -0
  154. package/recce-source/js/src/components/check/CheckList.tsx +320 -0
  155. package/recce-source/js/src/components/check/LineageDiffView.tsx +32 -0
  156. package/recce-source/js/src/components/check/PresetCheckTemplateView.tsx +48 -0
  157. package/recce-source/js/src/components/check/SchemaDiffView.tsx +290 -0
  158. package/recce-source/js/src/components/check/check.ts +25 -0
  159. package/recce-source/js/src/components/check/timeline/CheckTimeline.tsx +163 -0
  160. package/recce-source/js/src/components/check/timeline/CommentInput.tsx +84 -0
  161. package/recce-source/js/src/components/check/timeline/TimelineEvent.tsx +468 -0
  162. package/recce-source/js/src/components/check/timeline/index.ts +12 -0
  163. package/recce-source/js/src/components/check/utils.ts +12 -0
  164. package/recce-source/js/src/components/data-grid/ScreenshotDataGrid.tsx +333 -0
  165. package/recce-source/js/src/components/data-grid/agGridStyles.css +55 -0
  166. package/recce-source/js/src/components/data-grid/agGridTheme.ts +43 -0
  167. package/recce-source/js/src/components/editor/CodeEditor.tsx +107 -0
  168. package/recce-source/js/src/components/editor/DiffEditor.tsx +162 -0
  169. package/recce-source/js/src/components/editor/index.ts +12 -0
  170. package/recce-source/js/src/components/errorboundary/ErrorBoundary.tsx +87 -0
  171. package/recce-source/js/src/components/histogram/HistogramDiffForm.tsx +147 -0
  172. package/recce-source/js/src/components/histogram/HistogramDiffResultView.tsx +63 -0
  173. package/recce-source/js/src/components/icons/index.tsx +142 -0
  174. package/recce-source/js/src/components/lineage/ActionControl.tsx +63 -0
  175. package/recce-source/js/src/components/lineage/ActionTag.tsx +141 -0
  176. package/recce-source/js/src/components/lineage/ChangeStatusLegend.tsx +46 -0
  177. package/recce-source/js/src/components/lineage/ColumnLevelLineageControl.tsx +327 -0
  178. package/recce-source/js/src/components/lineage/ColumnLevelLineageLegend.tsx +57 -0
  179. package/recce-source/js/src/components/lineage/GraphColumnNode.tsx +199 -0
  180. package/recce-source/js/src/components/lineage/GraphEdge.tsx +59 -0
  181. package/recce-source/js/src/components/lineage/GraphNode.tsx +555 -0
  182. package/recce-source/js/src/components/lineage/LineagePage.tsx +10 -0
  183. package/recce-source/js/src/components/lineage/LineageView.tsx +1384 -0
  184. package/recce-source/js/src/components/lineage/LineageViewContext.tsx +86 -0
  185. package/recce-source/js/src/components/lineage/LineageViewContextMenu.tsx +637 -0
  186. package/recce-source/js/src/components/lineage/LineageViewNotification.tsx +64 -0
  187. package/recce-source/js/src/components/lineage/LineageViewTopBar.tsx +596 -0
  188. package/recce-source/js/src/components/lineage/NodeSqlView.tsx +136 -0
  189. package/recce-source/js/src/components/lineage/NodeTag.tsx +278 -0
  190. package/recce-source/js/src/components/lineage/NodeView.tsx +642 -0
  191. package/recce-source/js/src/components/lineage/SandboxView.tsx +436 -0
  192. package/recce-source/js/src/components/lineage/ServerDisconnectedModalContent.tsx +105 -0
  193. package/recce-source/js/src/components/lineage/SetupConnectionBanner.tsx +52 -0
  194. package/recce-source/js/src/components/lineage/SingleEnvironmentQueryView.tsx +152 -0
  195. package/recce-source/js/src/components/lineage/graph.test.ts +31 -0
  196. package/recce-source/js/src/components/lineage/graph.ts +58 -0
  197. package/recce-source/js/src/components/lineage/lineage.test.ts +169 -0
  198. package/recce-source/js/src/components/lineage/lineage.ts +521 -0
  199. package/recce-source/js/src/components/lineage/styles.css +42 -0
  200. package/recce-source/js/src/components/lineage/styles.tsx +165 -0
  201. package/recce-source/js/src/components/lineage/useMultiNodesAction.ts +352 -0
  202. package/recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx +108 -0
  203. package/recce-source/js/src/components/onboarding-guide/Notification.tsx +62 -0
  204. package/recce-source/js/src/components/profile/ProfileDiffForm.tsx +134 -0
  205. package/recce-source/js/src/components/profile/ProfileDiffResultView.tsx +245 -0
  206. package/recce-source/js/src/components/query/ChangedOnlyCheckbox.tsx +29 -0
  207. package/recce-source/js/src/components/query/DiffText.tsx +120 -0
  208. package/recce-source/js/src/components/query/QueryDiffResultView.tsx +470 -0
  209. package/recce-source/js/src/components/query/QueryForm.tsx +80 -0
  210. package/recce-source/js/src/components/query/QueryPage.tsx +282 -0
  211. package/recce-source/js/src/components/query/QueryResultView.tsx +180 -0
  212. package/recce-source/js/src/components/query/SetupConnectionGuide.tsx +57 -0
  213. package/recce-source/js/src/components/query/SqlEditor.tsx +245 -0
  214. package/recce-source/js/src/components/query/ToggleSwitch.tsx +84 -0
  215. package/recce-source/js/src/components/query/styles.css +21 -0
  216. package/recce-source/js/src/components/routing/DirectUrlAccess.test.tsx +428 -0
  217. package/recce-source/js/src/components/routing/LineageStatePreservation.test.tsx +311 -0
  218. package/recce-source/js/src/components/routing/Navigation.test.tsx +256 -0
  219. package/recce-source/js/src/components/rowcount/RowCountDiffResultView.tsx +109 -0
  220. package/recce-source/js/src/components/rowcount/delta.ts +11 -0
  221. package/recce-source/js/src/components/run/RunList.tsx +303 -0
  222. package/recce-source/js/src/components/run/RunModal.tsx +191 -0
  223. package/recce-source/js/src/components/run/RunPage.tsx +26 -0
  224. package/recce-source/js/src/components/run/RunResultPane.tsx +454 -0
  225. package/recce-source/js/src/components/run/RunStatusAndDate.tsx +106 -0
  226. package/recce-source/js/src/components/run/RunToolbar.tsx +70 -0
  227. package/recce-source/js/src/components/run/RunView.tsx +196 -0
  228. package/recce-source/js/src/components/run/registry.ts +214 -0
  229. package/recce-source/js/src/components/run/types.ts +14 -0
  230. package/recce-source/js/src/components/schema/ColumnNameCell.test.tsx +169 -0
  231. package/recce-source/js/src/components/schema/ColumnNameCell.tsx +198 -0
  232. package/recce-source/js/src/components/schema/SchemaView.tsx +337 -0
  233. package/recce-source/js/src/components/schema/schemaDiff.ts +32 -0
  234. package/recce-source/js/src/components/schema/style.css +134 -0
  235. package/recce-source/js/src/components/screenshot/ScreenshotBox.tsx +39 -0
  236. package/recce-source/js/src/components/shared/HistoryToggle.tsx +35 -0
  237. package/recce-source/js/src/components/split/Split.tsx +40 -0
  238. package/recce-source/js/src/components/split/styles.css +24 -0
  239. package/recce-source/js/src/components/summary/ChangeSummary.tsx +264 -0
  240. package/recce-source/js/src/components/summary/SchemaSummary.tsx +123 -0
  241. package/recce-source/js/src/components/summary/SummaryView.tsx +29 -0
  242. package/recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx +48 -0
  243. package/recce-source/js/src/components/top-k/TopKDiffForm.tsx +58 -0
  244. package/recce-source/js/src/components/top-k/TopKDiffResultView.tsx +73 -0
  245. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnGroupHeader.tsx +228 -0
  246. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnHeader.tsx +113 -0
  247. package/recce-source/js/src/components/ui/dataGrid/defaultRenderCell.tsx +72 -0
  248. package/recce-source/js/src/components/ui/dataGrid/index.ts +23 -0
  249. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.test.tsx +607 -0
  250. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.tsx +211 -0
  251. package/recce-source/js/src/components/ui/dataGrid/schemaCells.test.tsx +452 -0
  252. package/recce-source/js/src/components/ui/dataGrid/schemaCells.tsx +142 -0
  253. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.test.tsx +178 -0
  254. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.tsx +275 -0
  255. package/recce-source/js/src/components/ui/markdown/ExternalLinkConfirmDialog.tsx +134 -0
  256. package/recce-source/js/src/components/ui/markdown/MarkdownContent.tsx +364 -0
  257. package/recce-source/js/src/components/ui/mui/index.ts +13 -0
  258. package/recce-source/js/src/components/ui/mui-provider.tsx +67 -0
  259. package/recce-source/js/src/components/ui/mui-theme.ts +1039 -0
  260. package/recce-source/js/src/components/ui/mui-utils.ts +113 -0
  261. package/recce-source/js/src/components/ui/toaster.tsx +288 -0
  262. package/recce-source/js/src/components/valuediff/ValueDiffDetailResultView.tsx +217 -0
  263. package/recce-source/js/src/components/valuediff/ValueDiffForm.tsx +246 -0
  264. package/recce-source/js/src/components/valuediff/ValueDiffResultView.tsx +82 -0
  265. package/recce-source/js/src/components/valuediff/shared.ts +33 -0
  266. package/recce-source/js/src/constants/tooltipMessage.ts +3 -0
  267. package/recce-source/js/src/constants/urls.ts +1 -0
  268. package/recce-source/js/src/lib/UrlHash.ts +12 -0
  269. package/recce-source/js/src/lib/api/adhocQuery.ts +70 -0
  270. package/recce-source/js/src/lib/api/axiosClient.ts +9 -0
  271. package/recce-source/js/src/lib/api/cacheKeys.ts +13 -0
  272. package/recce-source/js/src/lib/api/checkEvents.ts +252 -0
  273. package/recce-source/js/src/lib/api/checks.ts +129 -0
  274. package/recce-source/js/src/lib/api/cll.ts +53 -0
  275. package/recce-source/js/src/lib/api/connectToCloud.ts +13 -0
  276. package/recce-source/js/src/lib/api/flag.ts +37 -0
  277. package/recce-source/js/src/lib/api/info.ts +198 -0
  278. package/recce-source/js/src/lib/api/instanceInfo.ts +25 -0
  279. package/recce-source/js/src/lib/api/keepAlive.ts +108 -0
  280. package/recce-source/js/src/lib/api/lineagecheck.ts +35 -0
  281. package/recce-source/js/src/lib/api/localStorageKeys.ts +7 -0
  282. package/recce-source/js/src/lib/api/models.ts +59 -0
  283. package/recce-source/js/src/lib/api/profile.ts +65 -0
  284. package/recce-source/js/src/lib/api/rowcount.ts +19 -0
  285. package/recce-source/js/src/lib/api/runs.ts +174 -0
  286. package/recce-source/js/src/lib/api/schemacheck.ts +31 -0
  287. package/recce-source/js/src/lib/api/select.ts +25 -0
  288. package/recce-source/js/src/lib/api/sessionStorageKeys.ts +8 -0
  289. package/recce-source/js/src/lib/api/state.ts +117 -0
  290. package/recce-source/js/src/lib/api/track.ts +281 -0
  291. package/recce-source/js/src/lib/api/types.ts +284 -0
  292. package/recce-source/js/src/lib/api/user.ts +42 -0
  293. package/recce-source/js/src/lib/api/valuediff.ts +46 -0
  294. package/recce-source/js/src/lib/api/version.ts +40 -0
  295. package/recce-source/js/src/lib/const.ts +9 -0
  296. package/recce-source/js/src/lib/dataGrid/crossFunctionConsistency.test.ts +626 -0
  297. package/recce-source/js/src/lib/dataGrid/dataGridFactory.test.ts +2140 -0
  298. package/recce-source/js/src/lib/dataGrid/dataGridFactory.ts +397 -0
  299. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.test.ts +132 -0
  300. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.ts +126 -0
  301. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.test.ts +1627 -0
  302. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.ts +140 -0
  303. package/recce-source/js/src/lib/dataGrid/generators/toDataGrid.ts +67 -0
  304. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.test.ts +142 -0
  305. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.ts +71 -0
  306. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.test.ts +258 -0
  307. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.ts +153 -0
  308. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.test.ts +951 -0
  309. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.ts +221 -0
  310. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.test.ts +395 -0
  311. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.ts +184 -0
  312. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.test.ts +884 -0
  313. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.ts +113 -0
  314. package/recce-source/js/src/lib/dataGrid/index.ts +51 -0
  315. package/recce-source/js/src/lib/dataGrid/propertyBased.test.ts +858 -0
  316. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.test.ts +482 -0
  317. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.ts +345 -0
  318. package/recce-source/js/src/lib/dataGrid/shared/dataTypeEdgeCases.test.ts +698 -0
  319. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.test.tsx +820 -0
  320. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.tsx +277 -0
  321. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.test.ts +785 -0
  322. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.ts +370 -0
  323. package/recce-source/js/src/lib/dataGrid/shared/index.ts +81 -0
  324. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.test.ts +909 -0
  325. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.ts +325 -0
  326. package/recce-source/js/src/lib/dataGrid/shared/simpleColumnBuilder.tsx +240 -0
  327. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.test.tsx +719 -0
  328. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.tsx +231 -0
  329. package/recce-source/js/src/lib/dataGrid/shared/validation.test.ts +559 -0
  330. package/recce-source/js/src/lib/dataGrid/shared/validation.ts +367 -0
  331. package/recce-source/js/src/lib/dataGrid/warehouseNamingConventions.test.ts +1117 -0
  332. package/recce-source/js/src/lib/formatSelect.ts +50 -0
  333. package/recce-source/js/src/lib/hooks/ApiConfigContext.tsx +181 -0
  334. package/recce-source/js/src/lib/hooks/IdleTimeoutContext.tsx +177 -0
  335. package/recce-source/js/src/lib/hooks/LineageGraphContext.tsx +512 -0
  336. package/recce-source/js/src/lib/hooks/RecceActionContext.tsx +269 -0
  337. package/recce-source/js/src/lib/hooks/RecceCheckContext.tsx +33 -0
  338. package/recce-source/js/src/lib/hooks/RecceContextProvider.tsx +54 -0
  339. package/recce-source/js/src/lib/hooks/RecceInstanceContext.tsx +129 -0
  340. package/recce-source/js/src/lib/hooks/RecceQueryContext.tsx +98 -0
  341. package/recce-source/js/src/lib/hooks/RecceShareStateContext.tsx +59 -0
  342. package/recce-source/js/src/lib/hooks/ScreenShot.tsx +399 -0
  343. package/recce-source/js/src/lib/hooks/useAppRouter.test.ts +211 -0
  344. package/recce-source/js/src/lib/hooks/useAppRouter.ts +200 -0
  345. package/recce-source/js/src/lib/hooks/useCheckEvents.ts +99 -0
  346. package/recce-source/js/src/lib/hooks/useCheckToast.tsx +14 -0
  347. package/recce-source/js/src/lib/hooks/useClipBoardToast.tsx +27 -0
  348. package/recce-source/js/src/lib/hooks/useCountdownToast.tsx +102 -0
  349. package/recce-source/js/src/lib/hooks/useFeedbackCollectionToast.tsx +130 -0
  350. package/recce-source/js/src/lib/hooks/useGuideToast.tsx +45 -0
  351. package/recce-source/js/src/lib/hooks/useIdleDetection.tsx +185 -0
  352. package/recce-source/js/src/lib/hooks/useModelColumns.tsx +113 -0
  353. package/recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx +13 -0
  354. package/recce-source/js/src/lib/hooks/useRecceServerFlag.tsx +13 -0
  355. package/recce-source/js/src/lib/hooks/useRun.tsx +89 -0
  356. package/recce-source/js/src/lib/hooks/useThemeColors.ts +115 -0
  357. package/recce-source/js/src/lib/mergeKeys.test.ts +89 -0
  358. package/recce-source/js/src/lib/mergeKeys.ts +86 -0
  359. package/recce-source/js/src/lib/result/ResultErrorFallback.tsx +9 -0
  360. package/recce-source/js/src/lib/utils/formatTime.ts +84 -0
  361. package/recce-source/js/src/lib/utils/urls.ts +16 -0
  362. package/recce-source/js/src/utils/DropdownValuesInput.tsx +297 -0
  363. package/recce-source/js/src/utils/formatters.tsx +237 -0
  364. package/recce-source/js/src/utils/transforms.ts +81 -0
  365. package/recce-source/js/tsconfig.json +47 -0
  366. package/recce-source/macros/README.md +8 -0
  367. package/recce-source/macros/recce_athena.sql +73 -0
  368. package/recce-source/pyproject.toml +109 -0
  369. package/recce-source/recce/VERSION +1 -0
  370. package/recce-source/recce/__init__.py +84 -0
  371. package/recce-source/recce/adapter/__init__.py +0 -0
  372. package/recce-source/recce/adapter/base.py +109 -0
  373. package/recce-source/recce/adapter/dbt_adapter/__init__.py +1699 -0
  374. package/recce-source/recce/adapter/dbt_adapter/dbt_version.py +42 -0
  375. package/recce-source/recce/adapter/sqlmesh_adapter.py +141 -0
  376. package/recce-source/recce/apis/__init__.py +0 -0
  377. package/recce-source/recce/apis/check_api.py +203 -0
  378. package/recce-source/recce/apis/check_events_api.py +353 -0
  379. package/recce-source/recce/apis/check_func.py +130 -0
  380. package/recce-source/recce/apis/run_api.py +130 -0
  381. package/recce-source/recce/apis/run_func.py +258 -0
  382. package/recce-source/recce/artifact.py +266 -0
  383. package/recce-source/recce/cli.py +1846 -0
  384. package/recce-source/recce/config.py +127 -0
  385. package/recce-source/recce/connect_to_cloud.py +138 -0
  386. package/recce-source/recce/core.py +334 -0
  387. package/recce-source/recce/diff.py +26 -0
  388. package/recce-source/recce/event/CONFIG +1 -0
  389. package/recce-source/recce/event/SENTRY_DNS +1 -0
  390. package/recce-source/recce/event/__init__.py +304 -0
  391. package/recce-source/recce/event/collector.py +184 -0
  392. package/recce-source/recce/event/track.py +158 -0
  393. package/recce-source/recce/exceptions.py +21 -0
  394. package/recce-source/recce/git.py +77 -0
  395. package/recce-source/recce/github.py +222 -0
  396. package/recce-source/recce/mcp_server.py +861 -0
  397. package/recce-source/recce/models/__init__.py +6 -0
  398. package/recce-source/recce/models/check.py +473 -0
  399. package/recce-source/recce/models/run.py +46 -0
  400. package/recce-source/recce/models/types.py +218 -0
  401. package/recce-source/recce/pull_request.py +124 -0
  402. package/recce-source/recce/run.py +390 -0
  403. package/recce-source/recce/server.py +877 -0
  404. package/recce-source/recce/state/__init__.py +31 -0
  405. package/recce-source/recce/state/cloud.py +644 -0
  406. package/recce-source/recce/state/const.py +26 -0
  407. package/recce-source/recce/state/local.py +56 -0
  408. package/recce-source/recce/state/state.py +119 -0
  409. package/recce-source/recce/state/state_loader.py +174 -0
  410. package/recce-source/recce/summary.py +575 -0
  411. package/recce-source/recce/tasks/__init__.py +23 -0
  412. package/recce-source/recce/tasks/core.py +134 -0
  413. package/recce-source/recce/tasks/dataframe.py +170 -0
  414. package/recce-source/recce/tasks/histogram.py +433 -0
  415. package/recce-source/recce/tasks/lineage.py +19 -0
  416. package/recce-source/recce/tasks/profile.py +298 -0
  417. package/recce-source/recce/tasks/query.py +450 -0
  418. package/recce-source/recce/tasks/rowcount.py +277 -0
  419. package/recce-source/recce/tasks/schema.py +65 -0
  420. package/recce-source/recce/tasks/top_k.py +172 -0
  421. package/recce-source/recce/tasks/utils.py +147 -0
  422. package/recce-source/recce/tasks/valuediff.py +497 -0
  423. package/recce-source/recce/util/__init__.py +4 -0
  424. package/recce-source/recce/util/api_token.py +80 -0
  425. package/recce-source/recce/util/breaking.py +330 -0
  426. package/recce-source/recce/util/cache.py +25 -0
  427. package/recce-source/recce/util/cll.py +355 -0
  428. package/recce-source/recce/util/cloud/__init__.py +15 -0
  429. package/recce-source/recce/util/cloud/base.py +115 -0
  430. package/recce-source/recce/util/cloud/check_events.py +190 -0
  431. package/recce-source/recce/util/cloud/checks.py +242 -0
  432. package/recce-source/recce/util/io.py +120 -0
  433. package/recce-source/recce/util/lineage.py +83 -0
  434. package/recce-source/recce/util/logger.py +25 -0
  435. package/recce-source/recce/util/onboarding_state.py +45 -0
  436. package/recce-source/recce/util/perf_tracking.py +85 -0
  437. package/recce-source/recce/util/pydantic_model.py +22 -0
  438. package/recce-source/recce/util/recce_cloud.py +454 -0
  439. package/recce-source/recce/util/singleton.py +18 -0
  440. package/recce-source/recce/util/startup_perf.py +121 -0
  441. package/recce-source/recce/yaml/__init__.py +58 -0
  442. package/recce-source/recce_cloud/README.md +780 -0
  443. package/recce-source/recce_cloud/VERSION +1 -0
  444. package/recce-source/recce_cloud/__init__.py +24 -0
  445. package/recce-source/recce_cloud/api/__init__.py +17 -0
  446. package/recce-source/recce_cloud/api/base.py +132 -0
  447. package/recce-source/recce_cloud/api/client.py +186 -0
  448. package/recce-source/recce_cloud/api/exceptions.py +26 -0
  449. package/recce-source/recce_cloud/api/factory.py +63 -0
  450. package/recce-source/recce_cloud/api/github.py +106 -0
  451. package/recce-source/recce_cloud/api/gitlab.py +111 -0
  452. package/recce-source/recce_cloud/artifact.py +57 -0
  453. package/recce-source/recce_cloud/ci_providers/__init__.py +9 -0
  454. package/recce-source/recce_cloud/ci_providers/base.py +82 -0
  455. package/recce-source/recce_cloud/ci_providers/detector.py +147 -0
  456. package/recce-source/recce_cloud/ci_providers/github_actions.py +136 -0
  457. package/recce-source/recce_cloud/ci_providers/gitlab_ci.py +130 -0
  458. package/recce-source/recce_cloud/cli.py +434 -0
  459. package/recce-source/recce_cloud/download.py +230 -0
  460. package/recce-source/recce_cloud/hatch_build.py +20 -0
  461. package/recce-source/recce_cloud/pyproject.toml +49 -0
  462. package/recce-source/recce_cloud/upload.py +214 -0
  463. package/recce-source/test.py +0 -0
  464. package/recce-source/tests/__init__.py +0 -0
  465. package/recce-source/tests/adapter/__init__.py +0 -0
  466. package/recce-source/tests/adapter/dbt_adapter/__init__.py +0 -0
  467. package/recce-source/tests/adapter/dbt_adapter/conftest.py +17 -0
  468. package/recce-source/tests/adapter/dbt_adapter/dbt_test_helper.py +298 -0
  469. package/recce-source/tests/adapter/dbt_adapter/test_dbt_adapter.py +25 -0
  470. package/recce-source/tests/adapter/dbt_adapter/test_dbt_cll.py +717 -0
  471. package/recce-source/tests/adapter/dbt_adapter/test_proj/dbt_project.yml +4 -0
  472. package/recce-source/tests/adapter/dbt_adapter/test_proj/manifest.json +1 -0
  473. package/recce-source/tests/adapter/dbt_adapter/test_proj/package-lock.yml +8 -0
  474. package/recce-source/tests/adapter/dbt_adapter/test_proj/packages.yml +7 -0
  475. package/recce-source/tests/adapter/dbt_adapter/test_proj/profiles.yml +6 -0
  476. package/recce-source/tests/adapter/dbt_adapter/test_selector.py +205 -0
  477. package/recce-source/tests/apis/__init__.py +0 -0
  478. package/recce-source/tests/apis/row_count_diff.json +59 -0
  479. package/recce-source/tests/apis/test_check_events_api.py +615 -0
  480. package/recce-source/tests/apis/test_run_func.py +433 -0
  481. package/recce-source/tests/catalog.json +527 -0
  482. package/recce-source/tests/data/manifest/base/catalog.json +1 -0
  483. package/recce-source/tests/data/manifest/base/manifest.json +1 -0
  484. package/recce-source/tests/data/manifest/pr2/catalog.json +1 -0
  485. package/recce-source/tests/data/manifest/pr2/manifest.json +1 -0
  486. package/recce-source/tests/manifest.json +10655 -0
  487. package/recce-source/tests/models/__init__.py +0 -0
  488. package/recce-source/tests/models/test_check.py +731 -0
  489. package/recce-source/tests/models/test_run_models.py +295 -0
  490. package/recce-source/tests/recce_cloud/__init__.py +0 -0
  491. package/recce-source/tests/recce_cloud/test_ci_providers.py +351 -0
  492. package/recce-source/tests/recce_cloud/test_cli.py +735 -0
  493. package/recce-source/tests/recce_cloud/test_client.py +379 -0
  494. package/recce-source/tests/recce_cloud/test_platform_clients.py +483 -0
  495. package/recce-source/tests/recce_state.json +1 -0
  496. package/recce-source/tests/state/test_cloud.py +719 -0
  497. package/recce-source/tests/state/test_local.py +164 -0
  498. package/recce-source/tests/state/test_state_loader.py +211 -0
  499. package/recce-source/tests/tasks/__init__.py +0 -0
  500. package/recce-source/tests/tasks/conftest.py +4 -0
  501. package/recce-source/tests/tasks/test_histogram.py +129 -0
  502. package/recce-source/tests/tasks/test_lineage.py +55 -0
  503. package/recce-source/tests/tasks/test_preset_checks.py +64 -0
  504. package/recce-source/tests/tasks/test_profile.py +397 -0
  505. package/recce-source/tests/tasks/test_query.py +528 -0
  506. package/recce-source/tests/tasks/test_row_count.py +133 -0
  507. package/recce-source/tests/tasks/test_schema.py +122 -0
  508. package/recce-source/tests/tasks/test_top_k.py +77 -0
  509. package/recce-source/tests/tasks/test_utils.py +439 -0
  510. package/recce-source/tests/tasks/test_valuediff.py +361 -0
  511. package/recce-source/tests/test_cli.py +236 -0
  512. package/recce-source/tests/test_cli_mcp_optional.py +45 -0
  513. package/recce-source/tests/test_cloud_listing_cli.py +324 -0
  514. package/recce-source/tests/test_config.py +43 -0
  515. package/recce-source/tests/test_connect_to_cloud.py +82 -0
  516. package/recce-source/tests/test_core.py +174 -0
  517. package/recce-source/tests/test_dbt.py +36 -0
  518. package/recce-source/tests/test_mcp_server.py +505 -0
  519. package/recce-source/tests/test_pull_request.py +130 -0
  520. package/recce-source/tests/test_server.py +202 -0
  521. package/recce-source/tests/test_server_lifespan.py +138 -0
  522. package/recce-source/tests/test_summary.py +73 -0
  523. package/recce-source/tests/util/__init__.py +0 -0
  524. package/recce-source/tests/util/cloud/__init__.py +0 -0
  525. package/recce-source/tests/util/cloud/test_check_events.py +255 -0
  526. package/recce-source/tests/util/cloud/test_checks.py +204 -0
  527. package/recce-source/tests/util/test_api_token.py +119 -0
  528. package/recce-source/tests/util/test_breaking.py +1427 -0
  529. package/recce-source/tests/util/test_cll.py +706 -0
  530. package/recce-source/tests/util/test_lineage.py +122 -0
  531. package/recce-source/tests/util/test_onboarding_state.py +84 -0
  532. package/recce-source/tests/util/test_recce_cloud.py +231 -0
  533. package/recce-source/tox.ini +40 -0
  534. package/recce-source/uv.lock +3928 -0
  535. package/src/api/index.ts +32 -0
  536. package/src/components/index.ts +154 -0
  537. package/src/global.d.ts +14 -0
  538. package/src/hooks/index.ts +56 -0
  539. package/src/index.ts +17 -0
  540. package/src/lib/hooks/RouteConfigContext.ts +139 -0
  541. package/src/lib/hooks/useAppRouter.ts +240 -0
  542. package/src/mui-augmentation.d.ts +139 -0
  543. package/src/theme/index.ts +13 -0
  544. package/src/theme.ts +23 -0
  545. package/src/types/index.ts +23 -0
  546. package/dist/index-BNUP2V_N.d.ts.map +0 -1
  547. package/dist/index-DOPZuhD8.d.mts.map +0 -1
  548. package/dist/theme.d.mts.map +0 -1
  549. package/dist/theme.d.ts.map +0 -1
@@ -0,0 +1,185 @@
1
+ import throttle from "lodash/throttle";
2
+ import { useCallback, useEffect, useMemo } from "react";
3
+ import { sendKeepAlive } from "@/lib/api/keepAlive";
4
+ import { useApiConfig } from "./ApiConfigContext";
5
+ import { useIdleTimeoutSafe } from "./IdleTimeoutContext";
6
+ import { useRecceInstanceInfo } from "./useRecceInstanceInfo";
7
+
8
+ /**
9
+ * Check if debug logging is enabled via window.RECCE_DEBUG_IDLE
10
+ * Enable in browser console: window.RECCE_DEBUG_IDLE = true
11
+ * Disable: delete window.RECCE_DEBUG_IDLE
12
+ */
13
+ function isDebugEnabled(): boolean {
14
+ // biome-ignore lint/suspicious/noExplicitAny: window flag for debug logging
15
+ return typeof window !== "undefined" && !!(window as any).RECCE_DEBUG_IDLE;
16
+ }
17
+
18
+ /**
19
+ * Log function that only outputs when debug is enabled
20
+ */
21
+ function debugLog(message: string, data?: Record<string, unknown>) {
22
+ if (isDebugEnabled()) {
23
+ if (data) {
24
+ console.log(message, data);
25
+ } else {
26
+ console.log(message);
27
+ }
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Configuration for idle detection behavior
33
+ */
34
+ const IDLE_DETECTION_CONFIG = {
35
+ /** Events to listen for user activity */
36
+ ACTIVITY_EVENTS: ["focus", "mousemove", "keydown", "scroll"] as const,
37
+ /**
38
+ * Throttle event handler execution to reduce JS overhead (150ms).
39
+ * Uses lodash.throttle with { leading: true, trailing: true } to ensure
40
+ * immediate response on first activity (leading) and also capture the final
41
+ * event in a burst (trailing), which is important for user experience.
42
+ */
43
+ EVENT_THROTTLE_MS: 150,
44
+ } as const;
45
+
46
+ /**
47
+ * Hook to detect user activity and send keep-alive signals to prevent server idle timeout.
48
+ *
49
+ * This hook:
50
+ * - Listens for user activities (focus, mouse, keyboard, scroll)
51
+ * - Sends keep-alive requests (throttled at axios layer to minimum 3 seconds)
52
+ * - Pauses when the tab is inactive (using Page Visibility API)
53
+ * - Immediately sends a keep-alive when tab becomes active
54
+ * - Only activates when idle_timeout is configured on the server
55
+ *
56
+ * Note: The countdown in IdleTimeoutContext is based on successful keep-alive
57
+ * API calls, not on user activity. This ensures accurate server state tracking.
58
+ */
59
+ export function useIdleDetection() {
60
+ const { data: instanceInfo, isLoading, isError } = useRecceInstanceInfo();
61
+ const idleTimeoutContext = useIdleTimeoutSafe();
62
+ const isDisconnected = idleTimeoutContext?.isDisconnected ?? false;
63
+ const { apiClient } = useApiConfig();
64
+
65
+ // Only enable idle detection if idle_timeout is configured and not disconnected
66
+ const idleTimeout = instanceInfo?.idle_timeout;
67
+ const isEnabled =
68
+ idleTimeout !== undefined && idleTimeout > 0 && !isDisconnected;
69
+
70
+ // Debug: Log instance info state when debug is enabled
71
+ debugLog("[Idle Detection] Instance info", {
72
+ isLoading,
73
+ isError,
74
+ hasIdleTimeout: idleTimeout !== undefined,
75
+ idleTimeout:
76
+ idleTimeout !== undefined ? `${idleTimeout}s` : "not configured",
77
+ isDisconnected,
78
+ isEnabled,
79
+ });
80
+
81
+ /**
82
+ * Send keep-alive signal to server
83
+ * Throttling is handled at the axios layer (minimum 3 seconds between API calls)
84
+ * The successful send will notify IdleTimeoutContext to reset countdown
85
+ */
86
+ const sendKeepAliveNow = useCallback(async () => {
87
+ if (document.hidden) return;
88
+
89
+ const sent = await sendKeepAlive(apiClient);
90
+
91
+ if (sent) {
92
+ debugLog("[Idle Detection] Keep-alive sent successfully", {
93
+ timestamp: new Date().toISOString(),
94
+ });
95
+ }
96
+ }, [apiClient]);
97
+
98
+ /**
99
+ * Handle any user activity event
100
+ * Attempts to send keep-alive (axios layer handles throttling)
101
+ */
102
+ const handleActivity = useCallback(
103
+ (event: Event) => {
104
+ if (isEnabled && !document.hidden) {
105
+ debugLog("[Idle Detection] Activity detected", {
106
+ event: event.type,
107
+ tabActive: !document.hidden,
108
+ });
109
+
110
+ // Send keep-alive API call (axios layer handles throttling)
111
+ void sendKeepAliveNow();
112
+ }
113
+ },
114
+ [isEnabled, sendKeepAliveNow],
115
+ );
116
+
117
+ /**
118
+ * Handle tab visibility changes
119
+ * When tab becomes active, attempt to send keep-alive
120
+ */
121
+ const handleVisibilityChange = useCallback(() => {
122
+ if (!isEnabled) return;
123
+
124
+ if (!document.hidden) {
125
+ debugLog("[Idle Detection] Tab became active", {
126
+ timestamp: new Date().toISOString(),
127
+ });
128
+
129
+ // Send keep-alive (axios layer handles throttling)
130
+ void sendKeepAliveNow();
131
+ }
132
+ }, [isEnabled, sendKeepAliveNow]);
133
+
134
+ // Create throttled handler using lodash to reduce JS overhead from high-frequency events
135
+ // useMemo ensures stable reference and proper cleanup
136
+ const throttledHandler = useMemo(
137
+ () =>
138
+ throttle(handleActivity, IDLE_DETECTION_CONFIG.EVENT_THROTTLE_MS, {
139
+ leading: true,
140
+ trailing: true,
141
+ }),
142
+ [handleActivity],
143
+ );
144
+
145
+ useEffect(() => {
146
+ if (!isEnabled) {
147
+ debugLog("[Idle Detection] Disabled", {
148
+ idleTimeout: idleTimeout,
149
+ reason:
150
+ idleTimeout === undefined
151
+ ? "idle_timeout not configured on server"
152
+ : idleTimeout === 0
153
+ ? "idle_timeout is 0"
154
+ : "disconnected",
155
+ });
156
+ return;
157
+ }
158
+
159
+ debugLog("[Idle Detection] Initialized", {
160
+ enabled: true,
161
+ idleTimeout: `${idleTimeout}s`,
162
+ eventThrottle: `${IDLE_DETECTION_CONFIG.EVENT_THROTTLE_MS}ms`,
163
+ apiThrottle: "3s (axios layer)",
164
+ monitoredEvents: IDLE_DETECTION_CONFIG.ACTIVITY_EVENTS.join(", "),
165
+ });
166
+
167
+ // Register activity event listeners with throttled handler
168
+ IDLE_DETECTION_CONFIG.ACTIVITY_EVENTS.forEach((eventType) => {
169
+ window.addEventListener(eventType, throttledHandler, { passive: true });
170
+ });
171
+
172
+ // Register visibility change listener (not throttled - immediate response needed)
173
+ document.addEventListener("visibilitychange", handleVisibilityChange);
174
+
175
+ // Cleanup function
176
+ return () => {
177
+ debugLog("[Idle Detection] Cleanup - removing event listeners");
178
+ IDLE_DETECTION_CONFIG.ACTIVITY_EVENTS.forEach((eventType) => {
179
+ window.removeEventListener(eventType, throttledHandler);
180
+ });
181
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
182
+ throttledHandler.cancel(); // Cancel any pending throttled calls
183
+ };
184
+ }, [isEnabled, throttledHandler, handleVisibilityChange, idleTimeout]);
185
+ }
@@ -0,0 +1,113 @@
1
+ import _ from "lodash";
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
+ import { LineageGraphNode } from "@/components/lineage/lineage";
4
+ import { getModelInfo, NodeColumnData, NodeData } from "../api/info";
5
+ import { useLineageGraphContext } from "./LineageGraphContext";
6
+
7
+ export function extractColumns(node: LineageGraphNode) {
8
+ function getColumns(nodeData: NodeData | undefined) {
9
+ return nodeData?.columns
10
+ ? Object.values(nodeData.columns).filter((c) => c != null)
11
+ : [];
12
+ }
13
+
14
+ const baseColumns = getColumns(node.data.data.base);
15
+ const currentColumns = getColumns(node.data.data.current);
16
+
17
+ return unionColumns(baseColumns, currentColumns);
18
+ }
19
+
20
+ export function unionColumns(
21
+ baseColumns: NodeColumnData[],
22
+ currentColumns: NodeColumnData[],
23
+ ) {
24
+ const union: NodeColumnData[] = [];
25
+ baseColumns.forEach((column) => {
26
+ if (!union.some((c) => c.name === column.name)) {
27
+ union.push(column);
28
+ }
29
+ });
30
+ currentColumns.forEach((column) => {
31
+ if (!union.some((c) => c.name === column.name)) {
32
+ union.push(column);
33
+ }
34
+ });
35
+
36
+ return union;
37
+ }
38
+
39
+ const useModelColumns = (model: string | undefined) => {
40
+ const { lineageGraph } = useLineageGraphContext();
41
+
42
+ const node = _.find(lineageGraph?.nodes, {
43
+ data: {
44
+ name: model,
45
+ },
46
+ });
47
+
48
+ const nodeColumns = useMemo(() => {
49
+ return node ? extractColumns(node) : [];
50
+ }, [node]);
51
+
52
+ const [columns, setColumns] = useState<NodeColumnData[]>([]);
53
+ const [primaryKey, setPrimaryKey] = useState<string>();
54
+ const [isLoading, setIsLoading] = useState<boolean>(true);
55
+ const [error, setError] = useState<Error | null>(null);
56
+ const [prevNodeColumns, setPrevNodeColumns] = useState<NodeColumnData[]>([]);
57
+ const [prevNodeId, setPrevNodeId] = useState(node?.id);
58
+
59
+ const nodePrimaryKey = node ? node.data.data.current?.primary_key : undefined;
60
+
61
+ const fetchData = useCallback(async () => {
62
+ if (!node) {
63
+ return;
64
+ }
65
+ try {
66
+ const data = await getModelInfo(node.id);
67
+ const modelInfo = data.model;
68
+ if (!modelInfo.base.columns || !modelInfo.current.columns) {
69
+ setColumns([]);
70
+ return;
71
+ }
72
+ setPrimaryKey(modelInfo.current.primary_key);
73
+ const baseColumns = Object.values(modelInfo.base.columns);
74
+ const currentColumns = Object.values(modelInfo.current.columns);
75
+ setColumns(unionColumns(baseColumns, currentColumns));
76
+ } catch (error) {
77
+ setError(error as Error);
78
+ }
79
+ }, [node]);
80
+
81
+ // Adjust state during render when node changes
82
+ if (nodeColumns !== prevNodeColumns || node?.id !== prevNodeId) {
83
+ setPrevNodeColumns(nodeColumns);
84
+ setPrevNodeId(node?.id);
85
+
86
+ if (nodeColumns.length > 0) {
87
+ setColumns(nodeColumns);
88
+ setPrimaryKey(nodePrimaryKey);
89
+ setIsLoading(false);
90
+ } else if (node?.id === undefined) {
91
+ setColumns([]);
92
+ setIsLoading(false);
93
+ }
94
+ // Note: fetchData case is handled separately in effect below
95
+ }
96
+
97
+ // Fetch data effect - only runs when we need to fetch
98
+ useEffect(() => {
99
+ if (nodeColumns.length === 0 && node?.id !== undefined) {
100
+ // fetchData() is a legitimate side effect, leaving
101
+ // eslint-disable-next-line react-hooks/set-state-in-effect
102
+ fetchData().catch((e: unknown) => {
103
+ // error is already handled in fetchData()
104
+ console.error(e);
105
+ });
106
+ setIsLoading(false);
107
+ }
108
+ }, [fetchData, node?.id, nodeColumns]);
109
+
110
+ return { columns, primaryKey, isLoading, error };
111
+ };
112
+
113
+ export default useModelColumns;
@@ -0,0 +1,13 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { cacheKeys } from "../api/cacheKeys";
3
+ import { getRecceInstanceInfo, RecceInstanceInfo } from "../api/instanceInfo";
4
+ import { useApiConfig } from "./ApiConfigContext";
5
+
6
+ export const useRecceInstanceInfo = () => {
7
+ const { apiClient } = useApiConfig();
8
+
9
+ return useQuery<RecceInstanceInfo>({
10
+ queryKey: cacheKeys.instanceInfo(),
11
+ queryFn: () => getRecceInstanceInfo(apiClient),
12
+ });
13
+ };
@@ -0,0 +1,13 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { cacheKeys } from "../api/cacheKeys";
3
+ import { getServerFlag, RecceServerFlags } from "../api/flag";
4
+ import { useApiConfig } from "./ApiConfigContext";
5
+
6
+ export const useRecceServerFlag = () => {
7
+ const { apiClient } = useApiConfig();
8
+
9
+ return useQuery<RecceServerFlags>({
10
+ queryKey: cacheKeys.flag(),
11
+ queryFn: () => getServerFlag(apiClient),
12
+ });
13
+ };
@@ -0,0 +1,89 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ import {
4
+ findByRunType,
5
+ RegistryEntry,
6
+ runTypeHasRef,
7
+ } from "@/components/run/registry";
8
+ import { cacheKeys } from "@/lib/api/cacheKeys";
9
+ import { cancelRun, waitRun } from "@/lib/api/runs";
10
+ import { Run } from "../api/types";
11
+ import { useApiConfig } from "./ApiConfigContext";
12
+ import { useRunsAggregated } from "./LineageGraphContext";
13
+
14
+ interface UseRunResult {
15
+ run?: Run;
16
+ aborting: boolean;
17
+ isRunning: boolean;
18
+ error: Error | null;
19
+ onCancel: () => Promise<void>;
20
+ RunResultView?: RegistryEntry["RunResultView"] | undefined;
21
+ }
22
+
23
+ export const useRun = (runId?: string): UseRunResult => {
24
+ const { apiClient } = useApiConfig();
25
+ const [isRunning, setIsRunning] = useState(false);
26
+ const [aborting, setAborting] = useState(false);
27
+ const [, refetchRunsAggregated] = useRunsAggregated();
28
+
29
+ const { error, data: run } = useQuery({
30
+ queryKey: cacheKeys.run(runId ?? ""),
31
+ queryFn: async () => {
32
+ return await waitRun(runId ?? "", isRunning ? 2 : 0, apiClient);
33
+ },
34
+ enabled: !!runId,
35
+ refetchInterval: isRunning ? 50 : false,
36
+ retry: false,
37
+ });
38
+
39
+ // Track previous run state to detect changes
40
+ const [prevRun, setPrevRun] = useState(run);
41
+ const [prevError, setPrevError] = useState(error);
42
+
43
+ // Adjust isRunning during render when run/error state changes
44
+ if (run !== prevRun || error !== prevError) {
45
+ setPrevRun(run);
46
+ setPrevError(error);
47
+
48
+ if (error || run?.result || run?.error) {
49
+ setIsRunning(false);
50
+ } else if (run?.status === "running") {
51
+ setIsRunning(true);
52
+ }
53
+ }
54
+
55
+ // Side effect: refetch aggregated runs when row count runs complete
56
+ useEffect(() => {
57
+ if (
58
+ (error || run?.result || run?.error) &&
59
+ (run?.type === "row_count_diff" || run?.type === "row_count")
60
+ ) {
61
+ refetchRunsAggregated();
62
+ }
63
+ }, [run, error, refetchRunsAggregated]);
64
+
65
+ const onCancel = useCallback(async () => {
66
+ setAborting(true);
67
+ if (!runId) {
68
+ return;
69
+ }
70
+
71
+ await cancelRun(runId, apiClient);
72
+ return;
73
+ }, [runId, apiClient]);
74
+
75
+ let RunResultView: RegistryEntry["RunResultView"] | undefined;
76
+ if (run && runTypeHasRef(run.type)) {
77
+ RunResultView = findByRunType(run.type)
78
+ .RunResultView as RegistryEntry["RunResultView"];
79
+ }
80
+
81
+ return {
82
+ run,
83
+ isRunning,
84
+ aborting,
85
+ error,
86
+ onCancel,
87
+ RunResultView,
88
+ };
89
+ };
@@ -0,0 +1,115 @@
1
+ "use client";
2
+
3
+ import { useTheme as useMuiTheme } from "@mui/material/styles";
4
+ import { useTheme as useNextTheme } from "next-themes";
5
+ import { useEffect, useState } from "react";
6
+ import { colors } from "@/components/ui/mui-theme";
7
+
8
+ /**
9
+ * Theme-aware color utility hook
10
+ *
11
+ * Uses next-themes to determine dark/light mode, which is more reliable
12
+ * when the host app uses MUI CSS variables mode with nested ThemeProviders.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * function MyComponent() {
17
+ * const { isDark, background, text, border } = useThemeColors();
18
+ *
19
+ * return (
20
+ * <Box sx={{
21
+ * bgcolor: background.paper,
22
+ * color: text.primary,
23
+ * borderColor: border.default,
24
+ * }}>
25
+ * Content
26
+ * </Box>
27
+ * );
28
+ * }
29
+ * ```
30
+ */
31
+ export function useThemeColors() {
32
+ const muiTheme = useMuiTheme();
33
+ const { resolvedTheme } = useNextTheme();
34
+ const [mounted, setMounted] = useState(false);
35
+
36
+ useEffect(() => {
37
+ setMounted(true);
38
+ }, []);
39
+
40
+ // Use next-themes to determine dark mode (more reliable with CSS variables mode)
41
+ const isDark = mounted ? resolvedTheme === "dark" : false;
42
+
43
+ return {
44
+ /** Whether the current theme is dark mode */
45
+ isDark,
46
+
47
+ /** MUI theme object for direct access when needed */
48
+ theme: muiTheme,
49
+
50
+ /** Background colors */
51
+ background: {
52
+ /** Default page background */
53
+ default: isDark ? colors.neutral[900] : colors.white,
54
+ /** Paper/card background */
55
+ paper: isDark ? colors.neutral[800] : colors.white,
56
+ /** Subtle background for slight elevation (e.g., hover states, inputs) */
57
+ subtle: isDark ? colors.neutral[800] : colors.neutral[50],
58
+ /** Emphasized background for higher contrast areas */
59
+ emphasized: isDark ? colors.neutral[700] : colors.neutral[100],
60
+ },
61
+
62
+ /** Text colors */
63
+ text: {
64
+ /** Primary text color */
65
+ primary: isDark ? colors.neutral[50] : colors.neutral[900],
66
+ /** Secondary/muted text color */
67
+ secondary: isDark ? colors.neutral[400] : colors.neutral[600],
68
+ /** Disabled text color */
69
+ disabled: isDark ? colors.neutral[500] : colors.neutral[400],
70
+ /** Inverted text (for use on dark backgrounds in light mode, etc.) */
71
+ inverted: isDark ? colors.neutral[900] : colors.neutral[50],
72
+ },
73
+
74
+ /** Border colors */
75
+ border: {
76
+ /** Light border for subtle separations */
77
+ light: isDark ? colors.neutral[700] : colors.neutral[200],
78
+ /** Default border color */
79
+ default: isDark ? colors.neutral[600] : colors.neutral[300],
80
+ /** Strong border for emphasis */
81
+ strong: isDark ? colors.neutral[500] : colors.neutral[400],
82
+ },
83
+
84
+ /** Status/semantic colors */
85
+ status: {
86
+ /** Added/success backgrounds */
87
+ added: {
88
+ bg: isDark ? colors.green[900] : colors.green[100],
89
+ text: isDark ? colors.neutral[50] : colors.neutral[900],
90
+ },
91
+ /** Removed/error backgrounds */
92
+ removed: {
93
+ bg: isDark ? colors.red[950] : colors.red[200],
94
+ text: isDark ? colors.neutral[50] : colors.neutral[900],
95
+ },
96
+ /** Modified/warning backgrounds */
97
+ modified: {
98
+ bg: isDark ? colors.yellow[900] : colors.amber[100],
99
+ text: isDark ? colors.neutral[50] : colors.neutral[900],
100
+ },
101
+ },
102
+
103
+ /** Interactive element colors */
104
+ interactive: {
105
+ /** Hover state background */
106
+ hover: isDark ? colors.neutral[700] : colors.neutral[100],
107
+ /** Active/pressed state background */
108
+ active: isDark ? colors.neutral[600] : colors.neutral[200],
109
+ /** Focus ring color */
110
+ focus: colors.iochmara[500],
111
+ },
112
+ };
113
+ }
114
+
115
+ export type ThemeColors = ReturnType<typeof useThemeColors>;
@@ -0,0 +1,89 @@
1
+ import { mergeKeys, mergeKeysWithStatus } from "./mergeKeys";
2
+
3
+ test("should merge keys from base and target arrays while preserving order", () => {
4
+ const base = ["id", "name", "age", "email"];
5
+ const curr = ["name", "age", "city"];
6
+
7
+ const result = mergeKeysWithStatus(base, curr);
8
+
9
+ // The expected result after merging is: ['id', 'name', 'age', 'city', 'email']
10
+ expect(result).toEqual({
11
+ id: "removed",
12
+ name: undefined,
13
+ age: undefined,
14
+ email: "removed",
15
+ city: "added",
16
+ });
17
+ });
18
+
19
+ test("should merge keys from base and target arrays while preserving order (case 2)", () => {
20
+ const base = ["id", "name", "age", "city"];
21
+ const curr = ["id", "fullname", "age", "city"];
22
+
23
+ const result = mergeKeysWithStatus(base, curr);
24
+ const expected = {
25
+ id: undefined,
26
+ name: "removed",
27
+ fullname: "added",
28
+ age: undefined,
29
+ city: undefined,
30
+ };
31
+
32
+ expect(Object.keys(result)).toEqual(Object.keys(expected));
33
+ expect(result).toEqual(expected);
34
+ });
35
+
36
+ test("should handle empty arrays", () => {
37
+ const base = [] as string[];
38
+ const curr = ["name", "age", "city"];
39
+
40
+ const result = mergeKeys(base, curr);
41
+
42
+ // The expected result is the target array itself when the base array is empty
43
+ expect(result).toEqual(curr);
44
+ });
45
+
46
+ test("should handle duplicate keys in base and target arrays", () => {
47
+ const base = ["id", "name", "age", "email"];
48
+ const curr = ["name", "age", "id", "city", "name"];
49
+
50
+ const result = mergeKeysWithStatus(base, curr);
51
+ const expected = {
52
+ name: undefined,
53
+ age: undefined,
54
+ id: "reordered",
55
+ email: "removed",
56
+ city: "added",
57
+ };
58
+
59
+ expect(Object.keys(result)).toEqual(Object.keys(expected));
60
+ expect(result).toEqual(expected);
61
+ });
62
+
63
+ test("should handle reoder keys", () => {
64
+ const base = ["address", "id", "name", "age", "city"];
65
+ const curr = ["email", "city", "age", "name", "id"];
66
+
67
+ const result = mergeKeysWithStatus(base, curr);
68
+ const expected = {
69
+ address: "removed",
70
+ email: "added",
71
+ city: undefined,
72
+ age: "reordered",
73
+ name: "reordered",
74
+ id: "reordered",
75
+ };
76
+
77
+ expect(Object.keys(result)).toEqual(Object.keys(expected));
78
+ expect(result).toEqual(expected);
79
+ });
80
+
81
+ test("should handle both arrays having the same keys", () => {
82
+ const base = ["id", "name", "age"];
83
+ const curr = ["id", "name", "age"];
84
+
85
+ const result = mergeKeys(base, curr);
86
+
87
+ // The expected result after merging is the same as the base array
88
+ expect(result).toEqual(base);
89
+ });