@datarecce/ui 0.1.29 → 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 (601) hide show
  1. package/dist/{RecceCheckContext-fAKHgsGz.js → RecceCheckContext-DPpu9nG5.js} +2 -2
  2. package/dist/{RecceCheckContext-fAKHgsGz.js.map → RecceCheckContext-DPpu9nG5.js.map} +1 -1
  3. package/dist/{RecceCheckContext-PT4-g1bW.mjs → RecceCheckContext-bXdfQLGG.mjs} +2 -2
  4. package/dist/{RecceCheckContext-PT4-g1bW.mjs.map → RecceCheckContext-bXdfQLGG.mjs.map} +1 -1
  5. package/dist/api.d.mts +1 -1
  6. package/dist/api.d.ts +1 -1
  7. package/dist/api.js +4 -3
  8. package/dist/api.mjs +4 -3
  9. package/dist/{components-B9F5oJbK.js → components-B-YxuuPz.js} +66 -65
  10. package/dist/{components-B9F5oJbK.js.map → components-B-YxuuPz.js.map} +1 -1
  11. package/dist/{components-D2DRqJsz.css → components-BeAjVBV3.css} +1 -1
  12. package/dist/{components-D2DRqJsz.css.map → components-BeAjVBV3.css.map} +1 -1
  13. package/dist/{components-gDC1ucjo.mjs → components-DCOI1YlQ.mjs} +8 -7
  14. package/dist/{components-gDC1ucjo.mjs.map → components-DCOI1YlQ.mjs.map} +1 -1
  15. package/dist/{components-dVXbmdqd.css → components-iUxcqtUB.css} +1 -1
  16. package/dist/{components-dVXbmdqd.css.map → components-iUxcqtUB.css.map} +1 -1
  17. package/dist/components.d.mts +1 -1
  18. package/dist/components.d.ts +1 -1
  19. package/dist/components.js +6 -5
  20. package/dist/components.mjs +6 -5
  21. package/dist/{hooks-C2jUJ9EN.js → hooks-B9hsc1oD.js} +3 -3
  22. package/dist/{hooks-C2jUJ9EN.js.map → hooks-B9hsc1oD.js.map} +1 -1
  23. package/dist/{hooks-4hRUjy9Q.mjs → hooks-DjBNmTdh.mjs} +3 -3
  24. package/dist/{hooks-4hRUjy9Q.mjs.map → hooks-DjBNmTdh.mjs.map} +1 -1
  25. package/dist/hooks.d.mts +1 -1
  26. package/dist/hooks.d.ts +1 -1
  27. package/dist/hooks.js +5 -4
  28. package/dist/hooks.mjs +5 -4
  29. package/dist/{html2canvas-pro.esm-BR5xeFe-.mjs → html2canvas-pro.esm-BInzOtWO.mjs} +1 -1
  30. package/dist/{html2canvas-pro.esm-BR5xeFe-.mjs.map → html2canvas-pro.esm-BInzOtWO.mjs.map} +1 -1
  31. package/dist/{html2canvas-pro.esm-CVOsBdk0.js → html2canvas-pro.esm-WJxOmKlq.js} +1 -1
  32. package/dist/{html2canvas-pro.esm-CVOsBdk0.js.map → html2canvas-pro.esm-WJxOmKlq.js.map} +1 -1
  33. package/dist/{index-Bv5R8iLo.d.mts → index-B9lSPJTi.d.ts} +192 -12
  34. package/dist/index-B9lSPJTi.d.ts.map +1 -0
  35. package/dist/{index-CUtFlKOo.d.ts → index-IIXVIoOL.d.mts} +262 -78
  36. package/dist/index-IIXVIoOL.d.mts.map +1 -0
  37. package/dist/index.d.mts +2 -2
  38. package/dist/index.d.ts +2 -2
  39. package/dist/index.js +15 -7
  40. package/dist/index.js.map +1 -1
  41. package/dist/index.mjs +10 -8
  42. package/dist/index.mjs.map +1 -1
  43. package/dist/mui-theme-B2wm_cvZ.js +732 -0
  44. package/dist/mui-theme-B2wm_cvZ.js.map +1 -0
  45. package/dist/mui-theme-CUhybmBq.mjs +696 -0
  46. package/dist/mui-theme-CUhybmBq.mjs.map +1 -0
  47. package/dist/{state-CELzQ0tM.mjs → state-B9yzhuKs.mjs} +5 -694
  48. package/dist/state-B9yzhuKs.mjs.map +1 -0
  49. package/dist/{state-eEsMhIy4.css → state-DOUPNifc.css} +1 -1
  50. package/dist/{state-eEsMhIy4.css.map → state-DOUPNifc.css.map} +1 -1
  51. package/dist/{state-CemiRRon.js → state-lPCQsWy5.js} +24 -737
  52. package/dist/state-lPCQsWy5.js.map +1 -0
  53. package/dist/styles.css +4 -0
  54. package/dist/theme.d.mts +3 -0
  55. package/dist/theme.d.ts +3 -0
  56. package/dist/theme.js +9 -0
  57. package/dist/theme.mjs +4 -0
  58. package/dist/{tooltipMessage-CrXjOmVM.mjs → tooltipMessage-B--I3p1V.mjs} +1 -1
  59. package/dist/{tooltipMessage-CrXjOmVM.mjs.map → tooltipMessage-B--I3p1V.mjs.map} +1 -1
  60. package/dist/{tooltipMessage-Dbi1kkfi.js → tooltipMessage-DosF13kZ.js} +1 -1
  61. package/dist/{tooltipMessage-Dbi1kkfi.js.map → tooltipMessage-DosF13kZ.js.map} +1 -1
  62. package/dist/types.d.mts +1 -1
  63. package/dist/types.d.ts +1 -1
  64. package/dist/types.js +2 -2
  65. package/dist/types.mjs +2 -2
  66. package/dist/{urls-D7PrPolY.mjs → urls-B1Ymdoz-.mjs} +1 -1
  67. package/dist/{urls-D7PrPolY.mjs.map → urls-B1Ymdoz-.mjs.map} +1 -1
  68. package/dist/{urls-SazAekCZ.js → urls-C4eAc82S.js} +1 -1
  69. package/dist/{urls-SazAekCZ.js.map → urls-C4eAc82S.js.map} +1 -1
  70. package/dist/{version-bWg7XwOu.js → version-Dh8sZhvs.js} +2 -2
  71. package/dist/{version-bWg7XwOu.js.map → version-Dh8sZhvs.js.map} +1 -1
  72. package/dist/{version-paZ9esBk.mjs → version-OnOKzBeQ.mjs} +2 -2
  73. package/dist/{version-paZ9esBk.mjs.map → version-OnOKzBeQ.mjs.map} +1 -1
  74. package/package.json +9 -2
  75. package/recce-source/.editorconfig +26 -0
  76. package/recce-source/.flake8 +37 -0
  77. package/recce-source/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
  78. package/recce-source/.github/ISSUE_TEMPLATE/custom.md +10 -0
  79. package/recce-source/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
  80. package/recce-source/.github/PULL_REQUEST_TEMPLATE.md +21 -0
  81. package/recce-source/.github/copilot-instructions.md +331 -0
  82. package/recce-source/.github/instructions/backend-instructions.md +541 -0
  83. package/recce-source/.github/instructions/frontend-instructions.md +317 -0
  84. package/recce-source/.github/workflows/build-statics.yaml +72 -0
  85. package/recce-source/.github/workflows/bump.yaml +48 -0
  86. package/recce-source/.github/workflows/integration-tests-cloud.yaml +92 -0
  87. package/recce-source/.github/workflows/integration-tests-sqlmesh.yaml +33 -0
  88. package/recce-source/.github/workflows/integration-tests.yaml +52 -0
  89. package/recce-source/.github/workflows/nightly.yaml +246 -0
  90. package/recce-source/.github/workflows/release.yaml +196 -0
  91. package/recce-source/.github/workflows/tests-js.yaml +58 -0
  92. package/recce-source/.github/workflows/tests-python.yaml +128 -0
  93. package/recce-source/.pre-commit-config.yaml +26 -0
  94. package/recce-source/CLAUDE.md +483 -0
  95. package/recce-source/CODE_OF_CONDUCT.md +128 -0
  96. package/recce-source/CONTRIBUTING.md +107 -0
  97. package/recce-source/LICENSE +201 -0
  98. package/recce-source/Makefile +126 -0
  99. package/recce-source/README.md +182 -0
  100. package/recce-source/RECCE_CLOUD.md +81 -0
  101. package/recce-source/SECURITY.md +25 -0
  102. package/recce-source/docs/PACKAGING.md +340 -0
  103. package/recce-source/docs/README.md +1 -0
  104. package/recce-source/integration_tests/dbt/dbt_project.yml +26 -0
  105. package/recce-source/integration_tests/dbt/models/customers.sql +69 -0
  106. package/recce-source/integration_tests/dbt/models/docs.md +14 -0
  107. package/recce-source/integration_tests/dbt/models/orders.sql +56 -0
  108. package/recce-source/integration_tests/dbt/models/schema.yml +82 -0
  109. package/recce-source/integration_tests/dbt/models/staging/schema.yml +31 -0
  110. package/recce-source/integration_tests/dbt/models/staging/stg_customers.sql +22 -0
  111. package/recce-source/integration_tests/dbt/models/staging/stg_orders.sql +23 -0
  112. package/recce-source/integration_tests/dbt/models/staging/stg_payments.sql +25 -0
  113. package/recce-source/integration_tests/dbt/packages.yml +7 -0
  114. package/recce-source/integration_tests/dbt/profiles.yml +8 -0
  115. package/recce-source/integration_tests/dbt/seeds/raw_customers.csv +101 -0
  116. package/recce-source/integration_tests/dbt/seeds/raw_orders.csv +100 -0
  117. package/recce-source/integration_tests/dbt/seeds/raw_payments.csv +114 -0
  118. package/recce-source/integration_tests/dbt/seeds/raw_statuses.csv +5 -0
  119. package/recce-source/integration_tests/dbt/smoke_test.sh +72 -0
  120. package/recce-source/integration_tests/dbt/smoke_test_cloud.sh +71 -0
  121. package/recce-source/integration_tests/sqlmesh/__init__.py +0 -0
  122. package/recce-source/integration_tests/sqlmesh/audits/assert_item_price_above_zero.sql +9 -0
  123. package/recce-source/integration_tests/sqlmesh/audits/items.sql +7 -0
  124. package/recce-source/integration_tests/sqlmesh/audits/order_items.sql +7 -0
  125. package/recce-source/integration_tests/sqlmesh/config.py +171 -0
  126. package/recce-source/integration_tests/sqlmesh/helper.py +20 -0
  127. package/recce-source/integration_tests/sqlmesh/hooks/__init__.py +0 -0
  128. package/recce-source/integration_tests/sqlmesh/macros/__init__.py +0 -0
  129. package/recce-source/integration_tests/sqlmesh/macros/macros.py +8 -0
  130. package/recce-source/integration_tests/sqlmesh/macros/macros.sql +8 -0
  131. package/recce-source/integration_tests/sqlmesh/macros/utils.py +11 -0
  132. package/recce-source/integration_tests/sqlmesh/metrics/metrics.sql +25 -0
  133. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_by_day.sql +41 -0
  134. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_lifetime.sql +60 -0
  135. package/recce-source/integration_tests/sqlmesh/models/customers.sql +32 -0
  136. package/recce-source/integration_tests/sqlmesh/models/items.py +95 -0
  137. package/recce-source/integration_tests/sqlmesh/models/marketing.sql +15 -0
  138. package/recce-source/integration_tests/sqlmesh/models/order_items.py +95 -0
  139. package/recce-source/integration_tests/sqlmesh/models/orders.py +70 -0
  140. package/recce-source/integration_tests/sqlmesh/models/raw_marketing.py +62 -0
  141. package/recce-source/integration_tests/sqlmesh/models/top_waiters.sql +23 -0
  142. package/recce-source/integration_tests/sqlmesh/models/waiter_as_customer_by_day.sql +29 -0
  143. package/recce-source/integration_tests/sqlmesh/models/waiter_names.sql +10 -0
  144. package/recce-source/integration_tests/sqlmesh/models/waiter_revenue_by_day.sql +29 -0
  145. package/recce-source/integration_tests/sqlmesh/models/waiters.py +62 -0
  146. package/recce-source/integration_tests/sqlmesh/prep_env.sh +16 -0
  147. package/recce-source/integration_tests/sqlmesh/schema.yaml +5 -0
  148. package/recce-source/integration_tests/sqlmesh/seeds/waiter_names.csv +11 -0
  149. package/recce-source/integration_tests/sqlmesh/test_server.sh +29 -0
  150. package/recce-source/integration_tests/sqlmesh/tests/test_customer_revenue_by_day.yaml +63 -0
  151. package/recce-source/integration_tests/sqlmesh/tests/test_order_items.yaml +72 -0
  152. package/recce-source/js/.editorconfig +27 -0
  153. package/recce-source/js/.env.development +5 -0
  154. package/recce-source/js/.husky/pre-commit +29 -0
  155. package/recce-source/js/.nvmrc +1 -0
  156. package/recce-source/js/README.md +39 -0
  157. package/recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx +65 -0
  158. package/recce-source/js/app/(mainComponents)/NavBar.tsx +228 -0
  159. package/recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx +107 -0
  160. package/recce-source/js/app/(mainComponents)/TopBar.tsx +252 -0
  161. package/recce-source/js/app/@lineage/default.tsx +20 -0
  162. package/recce-source/js/app/@lineage/page.tsx +14 -0
  163. package/recce-source/js/app/MainLayout.tsx +170 -0
  164. package/recce-source/js/app/Providers.tsx +49 -0
  165. package/recce-source/js/app/checks/page.tsx +296 -0
  166. package/recce-source/js/app/error.tsx +93 -0
  167. package/recce-source/js/app/favicon.ico +0 -0
  168. package/recce-source/js/app/global-error.tsx +115 -0
  169. package/recce-source/js/app/global.css +82 -0
  170. package/recce-source/js/app/layout.tsx +48 -0
  171. package/recce-source/js/app/lineage/page.tsx +15 -0
  172. package/recce-source/js/app/page.tsx +12 -0
  173. package/recce-source/js/app/query/page.tsx +8 -0
  174. package/recce-source/js/biome.json +313 -0
  175. package/recce-source/js/jest.config.js +34 -0
  176. package/recce-source/js/jest.globals.d.ts +32 -0
  177. package/recce-source/js/jest.setup.js +91 -0
  178. package/recce-source/js/next.config.js +16 -0
  179. package/recce-source/js/package-lock.json +13843 -0
  180. package/recce-source/js/package.json +123 -0
  181. package/recce-source/js/pnpm-lock.yaml +9235 -0
  182. package/recce-source/js/pnpm-workspace.yaml +6 -0
  183. package/recce-source/js/postcss.config.js +5 -0
  184. package/recce-source/js/public/auth_callback.html +68 -0
  185. package/recce-source/js/public/imgs/feedback/thumbs-down.png +0 -0
  186. package/recce-source/js/public/imgs/feedback/thumbs-up.png +0 -0
  187. package/recce-source/js/public/imgs/reload-image.svg +4 -0
  188. package/recce-source/js/public/logo/recce-logo-white.png +0 -0
  189. package/recce-source/js/src/components/AuthModal/AuthModal.tsx +202 -0
  190. package/recce-source/js/src/components/app/AvatarDropdown.tsx +159 -0
  191. package/recce-source/js/src/components/app/EnvInfo.tsx +357 -0
  192. package/recce-source/js/src/components/app/Filename.tsx +388 -0
  193. package/recce-source/js/src/components/app/SetupConnectionPopover.tsx +91 -0
  194. package/recce-source/js/src/components/app/StateExporter.tsx +57 -0
  195. package/recce-source/js/src/components/app/StateImporter.tsx +198 -0
  196. package/recce-source/js/src/components/app/StateSharing.tsx +145 -0
  197. package/recce-source/js/src/components/app/StateSynchronizer.tsx +205 -0
  198. package/recce-source/js/src/components/charts/HistogramChart.tsx +291 -0
  199. package/recce-source/js/src/components/charts/SquareIcon.tsx +51 -0
  200. package/recce-source/js/src/components/charts/TopKSummaryList.tsx +457 -0
  201. package/recce-source/js/src/components/charts/chartTheme.ts +74 -0
  202. package/recce-source/js/src/components/check/CheckBreadcrumb.tsx +97 -0
  203. package/recce-source/js/src/components/check/CheckDescription.tsx +134 -0
  204. package/recce-source/js/src/components/check/CheckDetail.tsx +797 -0
  205. package/recce-source/js/src/components/check/CheckEmptyState.tsx +84 -0
  206. package/recce-source/js/src/components/check/CheckList.tsx +320 -0
  207. package/recce-source/js/src/components/check/LineageDiffView.tsx +32 -0
  208. package/recce-source/js/src/components/check/PresetCheckTemplateView.tsx +48 -0
  209. package/recce-source/js/src/components/check/SchemaDiffView.tsx +290 -0
  210. package/recce-source/js/src/components/check/check.ts +25 -0
  211. package/recce-source/js/src/components/check/timeline/CheckTimeline.tsx +163 -0
  212. package/recce-source/js/src/components/check/timeline/CommentInput.tsx +84 -0
  213. package/recce-source/js/src/components/check/timeline/TimelineEvent.tsx +468 -0
  214. package/recce-source/js/src/components/check/timeline/index.ts +12 -0
  215. package/recce-source/js/src/components/check/utils.ts +12 -0
  216. package/recce-source/js/src/components/data-grid/ScreenshotDataGrid.tsx +333 -0
  217. package/recce-source/js/src/components/data-grid/agGridStyles.css +55 -0
  218. package/recce-source/js/src/components/data-grid/agGridTheme.ts +43 -0
  219. package/recce-source/js/src/components/editor/CodeEditor.tsx +107 -0
  220. package/recce-source/js/src/components/editor/DiffEditor.tsx +162 -0
  221. package/recce-source/js/src/components/editor/index.ts +12 -0
  222. package/recce-source/js/src/components/errorboundary/ErrorBoundary.tsx +87 -0
  223. package/recce-source/js/src/components/histogram/HistogramDiffForm.tsx +147 -0
  224. package/recce-source/js/src/components/histogram/HistogramDiffResultView.tsx +63 -0
  225. package/recce-source/js/src/components/icons/index.tsx +142 -0
  226. package/recce-source/js/src/components/lineage/ActionControl.tsx +63 -0
  227. package/recce-source/js/src/components/lineage/ActionTag.tsx +141 -0
  228. package/recce-source/js/src/components/lineage/ChangeStatusLegend.tsx +46 -0
  229. package/recce-source/js/src/components/lineage/ColumnLevelLineageControl.tsx +327 -0
  230. package/recce-source/js/src/components/lineage/ColumnLevelLineageLegend.tsx +57 -0
  231. package/recce-source/js/src/components/lineage/GraphColumnNode.tsx +199 -0
  232. package/recce-source/js/src/components/lineage/GraphEdge.tsx +59 -0
  233. package/recce-source/js/src/components/lineage/GraphNode.tsx +555 -0
  234. package/recce-source/js/src/components/lineage/LineagePage.tsx +10 -0
  235. package/recce-source/js/src/components/lineage/LineageView.tsx +1384 -0
  236. package/recce-source/js/src/components/lineage/LineageViewContext.tsx +86 -0
  237. package/recce-source/js/src/components/lineage/LineageViewContextMenu.tsx +637 -0
  238. package/recce-source/js/src/components/lineage/LineageViewNotification.tsx +64 -0
  239. package/recce-source/js/src/components/lineage/LineageViewTopBar.tsx +596 -0
  240. package/recce-source/js/src/components/lineage/NodeSqlView.tsx +136 -0
  241. package/recce-source/js/src/components/lineage/NodeTag.tsx +278 -0
  242. package/recce-source/js/src/components/lineage/NodeView.tsx +642 -0
  243. package/recce-source/js/src/components/lineage/SandboxView.tsx +436 -0
  244. package/recce-source/js/src/components/lineage/ServerDisconnectedModalContent.tsx +105 -0
  245. package/recce-source/js/src/components/lineage/SetupConnectionBanner.tsx +52 -0
  246. package/recce-source/js/src/components/lineage/SingleEnvironmentQueryView.tsx +152 -0
  247. package/recce-source/js/src/components/lineage/graph.test.ts +31 -0
  248. package/recce-source/js/src/components/lineage/graph.ts +58 -0
  249. package/recce-source/js/src/components/lineage/lineage.test.ts +169 -0
  250. package/recce-source/js/src/components/lineage/lineage.ts +521 -0
  251. package/recce-source/js/src/components/lineage/styles.css +42 -0
  252. package/recce-source/js/src/components/lineage/styles.tsx +165 -0
  253. package/recce-source/js/src/components/lineage/useMultiNodesAction.ts +352 -0
  254. package/recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx +108 -0
  255. package/recce-source/js/src/components/onboarding-guide/Notification.tsx +62 -0
  256. package/recce-source/js/src/components/profile/ProfileDiffForm.tsx +134 -0
  257. package/recce-source/js/src/components/profile/ProfileDiffResultView.tsx +245 -0
  258. package/recce-source/js/src/components/query/ChangedOnlyCheckbox.tsx +29 -0
  259. package/recce-source/js/src/components/query/DiffText.tsx +120 -0
  260. package/recce-source/js/src/components/query/QueryDiffResultView.tsx +470 -0
  261. package/recce-source/js/src/components/query/QueryForm.tsx +80 -0
  262. package/recce-source/js/src/components/query/QueryPage.tsx +282 -0
  263. package/recce-source/js/src/components/query/QueryResultView.tsx +180 -0
  264. package/recce-source/js/src/components/query/SetupConnectionGuide.tsx +57 -0
  265. package/recce-source/js/src/components/query/SqlEditor.tsx +245 -0
  266. package/recce-source/js/src/components/query/ToggleSwitch.tsx +84 -0
  267. package/recce-source/js/src/components/query/styles.css +21 -0
  268. package/recce-source/js/src/components/routing/DirectUrlAccess.test.tsx +428 -0
  269. package/recce-source/js/src/components/routing/LineageStatePreservation.test.tsx +311 -0
  270. package/recce-source/js/src/components/routing/Navigation.test.tsx +256 -0
  271. package/recce-source/js/src/components/rowcount/RowCountDiffResultView.tsx +109 -0
  272. package/recce-source/js/src/components/rowcount/delta.ts +11 -0
  273. package/recce-source/js/src/components/run/RunList.tsx +303 -0
  274. package/recce-source/js/src/components/run/RunModal.tsx +191 -0
  275. package/recce-source/js/src/components/run/RunPage.tsx +26 -0
  276. package/recce-source/js/src/components/run/RunResultPane.tsx +454 -0
  277. package/recce-source/js/src/components/run/RunStatusAndDate.tsx +106 -0
  278. package/recce-source/js/src/components/run/RunToolbar.tsx +70 -0
  279. package/recce-source/js/src/components/run/RunView.tsx +196 -0
  280. package/recce-source/js/src/components/run/registry.ts +214 -0
  281. package/recce-source/js/src/components/run/types.ts +14 -0
  282. package/recce-source/js/src/components/schema/ColumnNameCell.test.tsx +169 -0
  283. package/recce-source/js/src/components/schema/ColumnNameCell.tsx +198 -0
  284. package/recce-source/js/src/components/schema/SchemaView.tsx +337 -0
  285. package/recce-source/js/src/components/schema/schemaDiff.ts +32 -0
  286. package/recce-source/js/src/components/schema/style.css +134 -0
  287. package/recce-source/js/src/components/screenshot/ScreenshotBox.tsx +39 -0
  288. package/recce-source/js/src/components/shared/HistoryToggle.tsx +35 -0
  289. package/recce-source/js/src/components/split/Split.tsx +40 -0
  290. package/recce-source/js/src/components/split/styles.css +24 -0
  291. package/recce-source/js/src/components/summary/ChangeSummary.tsx +264 -0
  292. package/recce-source/js/src/components/summary/SchemaSummary.tsx +123 -0
  293. package/recce-source/js/src/components/summary/SummaryView.tsx +29 -0
  294. package/recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx +48 -0
  295. package/recce-source/js/src/components/top-k/TopKDiffForm.tsx +58 -0
  296. package/recce-source/js/src/components/top-k/TopKDiffResultView.tsx +73 -0
  297. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnGroupHeader.tsx +228 -0
  298. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnHeader.tsx +113 -0
  299. package/recce-source/js/src/components/ui/dataGrid/defaultRenderCell.tsx +72 -0
  300. package/recce-source/js/src/components/ui/dataGrid/index.ts +23 -0
  301. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.test.tsx +607 -0
  302. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.tsx +211 -0
  303. package/recce-source/js/src/components/ui/dataGrid/schemaCells.test.tsx +452 -0
  304. package/recce-source/js/src/components/ui/dataGrid/schemaCells.tsx +142 -0
  305. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.test.tsx +178 -0
  306. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.tsx +275 -0
  307. package/recce-source/js/src/components/ui/markdown/ExternalLinkConfirmDialog.tsx +134 -0
  308. package/recce-source/js/src/components/ui/markdown/MarkdownContent.tsx +364 -0
  309. package/recce-source/js/src/components/ui/mui/index.ts +13 -0
  310. package/recce-source/js/src/components/ui/mui-provider.tsx +67 -0
  311. package/recce-source/js/src/components/ui/mui-theme.ts +1039 -0
  312. package/recce-source/js/src/components/ui/mui-utils.ts +113 -0
  313. package/recce-source/js/src/components/ui/toaster.tsx +288 -0
  314. package/recce-source/js/src/components/valuediff/ValueDiffDetailResultView.tsx +217 -0
  315. package/recce-source/js/src/components/valuediff/ValueDiffForm.tsx +246 -0
  316. package/recce-source/js/src/components/valuediff/ValueDiffResultView.tsx +82 -0
  317. package/recce-source/js/src/components/valuediff/shared.ts +33 -0
  318. package/recce-source/js/src/constants/tooltipMessage.ts +3 -0
  319. package/recce-source/js/src/constants/urls.ts +1 -0
  320. package/recce-source/js/src/lib/UrlHash.ts +12 -0
  321. package/recce-source/js/src/lib/api/adhocQuery.ts +70 -0
  322. package/recce-source/js/src/lib/api/axiosClient.ts +9 -0
  323. package/recce-source/js/src/lib/api/cacheKeys.ts +13 -0
  324. package/recce-source/js/src/lib/api/checkEvents.ts +252 -0
  325. package/recce-source/js/src/lib/api/checks.ts +129 -0
  326. package/recce-source/js/src/lib/api/cll.ts +53 -0
  327. package/recce-source/js/src/lib/api/connectToCloud.ts +13 -0
  328. package/recce-source/js/src/lib/api/flag.ts +37 -0
  329. package/recce-source/js/src/lib/api/info.ts +198 -0
  330. package/recce-source/js/src/lib/api/instanceInfo.ts +25 -0
  331. package/recce-source/js/src/lib/api/keepAlive.ts +108 -0
  332. package/recce-source/js/src/lib/api/lineagecheck.ts +35 -0
  333. package/recce-source/js/src/lib/api/localStorageKeys.ts +7 -0
  334. package/recce-source/js/src/lib/api/models.ts +59 -0
  335. package/recce-source/js/src/lib/api/profile.ts +65 -0
  336. package/recce-source/js/src/lib/api/rowcount.ts +19 -0
  337. package/recce-source/js/src/lib/api/runs.ts +174 -0
  338. package/recce-source/js/src/lib/api/schemacheck.ts +31 -0
  339. package/recce-source/js/src/lib/api/select.ts +25 -0
  340. package/recce-source/js/src/lib/api/sessionStorageKeys.ts +8 -0
  341. package/recce-source/js/src/lib/api/state.ts +117 -0
  342. package/recce-source/js/src/lib/api/track.ts +281 -0
  343. package/recce-source/js/src/lib/api/types.ts +284 -0
  344. package/recce-source/js/src/lib/api/user.ts +42 -0
  345. package/recce-source/js/src/lib/api/valuediff.ts +46 -0
  346. package/recce-source/js/src/lib/api/version.ts +40 -0
  347. package/recce-source/js/src/lib/const.ts +9 -0
  348. package/recce-source/js/src/lib/dataGrid/crossFunctionConsistency.test.ts +626 -0
  349. package/recce-source/js/src/lib/dataGrid/dataGridFactory.test.ts +2140 -0
  350. package/recce-source/js/src/lib/dataGrid/dataGridFactory.ts +397 -0
  351. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.test.ts +132 -0
  352. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.ts +126 -0
  353. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.test.ts +1627 -0
  354. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.ts +140 -0
  355. package/recce-source/js/src/lib/dataGrid/generators/toDataGrid.ts +67 -0
  356. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.test.ts +142 -0
  357. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.ts +71 -0
  358. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.test.ts +258 -0
  359. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.ts +153 -0
  360. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.test.ts +951 -0
  361. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.ts +221 -0
  362. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.test.ts +395 -0
  363. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.ts +184 -0
  364. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.test.ts +884 -0
  365. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.ts +113 -0
  366. package/recce-source/js/src/lib/dataGrid/index.ts +51 -0
  367. package/recce-source/js/src/lib/dataGrid/propertyBased.test.ts +858 -0
  368. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.test.ts +482 -0
  369. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.ts +345 -0
  370. package/recce-source/js/src/lib/dataGrid/shared/dataTypeEdgeCases.test.ts +698 -0
  371. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.test.tsx +820 -0
  372. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.tsx +277 -0
  373. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.test.ts +785 -0
  374. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.ts +370 -0
  375. package/recce-source/js/src/lib/dataGrid/shared/index.ts +81 -0
  376. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.test.ts +909 -0
  377. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.ts +325 -0
  378. package/recce-source/js/src/lib/dataGrid/shared/simpleColumnBuilder.tsx +240 -0
  379. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.test.tsx +719 -0
  380. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.tsx +231 -0
  381. package/recce-source/js/src/lib/dataGrid/shared/validation.test.ts +559 -0
  382. package/recce-source/js/src/lib/dataGrid/shared/validation.ts +367 -0
  383. package/recce-source/js/src/lib/dataGrid/warehouseNamingConventions.test.ts +1117 -0
  384. package/recce-source/js/src/lib/formatSelect.ts +50 -0
  385. package/recce-source/js/src/lib/hooks/ApiConfigContext.tsx +181 -0
  386. package/recce-source/js/src/lib/hooks/IdleTimeoutContext.tsx +177 -0
  387. package/recce-source/js/src/lib/hooks/LineageGraphContext.tsx +512 -0
  388. package/recce-source/js/src/lib/hooks/RecceActionContext.tsx +269 -0
  389. package/recce-source/js/src/lib/hooks/RecceCheckContext.tsx +33 -0
  390. package/recce-source/js/src/lib/hooks/RecceContextProvider.tsx +54 -0
  391. package/recce-source/js/src/lib/hooks/RecceInstanceContext.tsx +129 -0
  392. package/recce-source/js/src/lib/hooks/RecceQueryContext.tsx +98 -0
  393. package/recce-source/js/src/lib/hooks/RecceShareStateContext.tsx +59 -0
  394. package/recce-source/js/src/lib/hooks/ScreenShot.tsx +399 -0
  395. package/recce-source/js/src/lib/hooks/useAppRouter.test.ts +211 -0
  396. package/recce-source/js/src/lib/hooks/useAppRouter.ts +200 -0
  397. package/recce-source/js/src/lib/hooks/useCheckEvents.ts +99 -0
  398. package/recce-source/js/src/lib/hooks/useCheckToast.tsx +14 -0
  399. package/recce-source/js/src/lib/hooks/useClipBoardToast.tsx +27 -0
  400. package/recce-source/js/src/lib/hooks/useCountdownToast.tsx +102 -0
  401. package/recce-source/js/src/lib/hooks/useFeedbackCollectionToast.tsx +130 -0
  402. package/recce-source/js/src/lib/hooks/useGuideToast.tsx +45 -0
  403. package/recce-source/js/src/lib/hooks/useIdleDetection.tsx +185 -0
  404. package/recce-source/js/src/lib/hooks/useModelColumns.tsx +113 -0
  405. package/recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx +13 -0
  406. package/recce-source/js/src/lib/hooks/useRecceServerFlag.tsx +13 -0
  407. package/recce-source/js/src/lib/hooks/useRun.tsx +89 -0
  408. package/recce-source/js/src/lib/hooks/useThemeColors.ts +115 -0
  409. package/recce-source/js/src/lib/mergeKeys.test.ts +89 -0
  410. package/recce-source/js/src/lib/mergeKeys.ts +86 -0
  411. package/recce-source/js/src/lib/result/ResultErrorFallback.tsx +9 -0
  412. package/recce-source/js/src/lib/utils/formatTime.ts +84 -0
  413. package/recce-source/js/src/lib/utils/urls.ts +16 -0
  414. package/recce-source/js/src/utils/DropdownValuesInput.tsx +297 -0
  415. package/recce-source/js/src/utils/formatters.tsx +237 -0
  416. package/recce-source/js/src/utils/transforms.ts +81 -0
  417. package/recce-source/js/tsconfig.json +47 -0
  418. package/recce-source/macros/README.md +8 -0
  419. package/recce-source/macros/recce_athena.sql +73 -0
  420. package/recce-source/pyproject.toml +109 -0
  421. package/recce-source/recce/VERSION +1 -0
  422. package/recce-source/recce/__init__.py +84 -0
  423. package/recce-source/recce/adapter/__init__.py +0 -0
  424. package/recce-source/recce/adapter/base.py +109 -0
  425. package/recce-source/recce/adapter/dbt_adapter/__init__.py +1699 -0
  426. package/recce-source/recce/adapter/dbt_adapter/dbt_version.py +42 -0
  427. package/recce-source/recce/adapter/sqlmesh_adapter.py +141 -0
  428. package/recce-source/recce/apis/__init__.py +0 -0
  429. package/recce-source/recce/apis/check_api.py +203 -0
  430. package/recce-source/recce/apis/check_events_api.py +353 -0
  431. package/recce-source/recce/apis/check_func.py +130 -0
  432. package/recce-source/recce/apis/run_api.py +130 -0
  433. package/recce-source/recce/apis/run_func.py +258 -0
  434. package/recce-source/recce/artifact.py +266 -0
  435. package/recce-source/recce/cli.py +1846 -0
  436. package/recce-source/recce/config.py +127 -0
  437. package/recce-source/recce/connect_to_cloud.py +138 -0
  438. package/recce-source/recce/core.py +334 -0
  439. package/recce-source/recce/diff.py +26 -0
  440. package/recce-source/recce/event/CONFIG +1 -0
  441. package/recce-source/recce/event/SENTRY_DNS +1 -0
  442. package/recce-source/recce/event/__init__.py +304 -0
  443. package/recce-source/recce/event/collector.py +184 -0
  444. package/recce-source/recce/event/track.py +158 -0
  445. package/recce-source/recce/exceptions.py +21 -0
  446. package/recce-source/recce/git.py +77 -0
  447. package/recce-source/recce/github.py +222 -0
  448. package/recce-source/recce/mcp_server.py +861 -0
  449. package/recce-source/recce/models/__init__.py +6 -0
  450. package/recce-source/recce/models/check.py +473 -0
  451. package/recce-source/recce/models/run.py +46 -0
  452. package/recce-source/recce/models/types.py +218 -0
  453. package/recce-source/recce/pull_request.py +124 -0
  454. package/recce-source/recce/run.py +390 -0
  455. package/recce-source/recce/server.py +877 -0
  456. package/recce-source/recce/state/__init__.py +31 -0
  457. package/recce-source/recce/state/cloud.py +644 -0
  458. package/recce-source/recce/state/const.py +26 -0
  459. package/recce-source/recce/state/local.py +56 -0
  460. package/recce-source/recce/state/state.py +119 -0
  461. package/recce-source/recce/state/state_loader.py +174 -0
  462. package/recce-source/recce/summary.py +575 -0
  463. package/recce-source/recce/tasks/__init__.py +23 -0
  464. package/recce-source/recce/tasks/core.py +134 -0
  465. package/recce-source/recce/tasks/dataframe.py +170 -0
  466. package/recce-source/recce/tasks/histogram.py +433 -0
  467. package/recce-source/recce/tasks/lineage.py +19 -0
  468. package/recce-source/recce/tasks/profile.py +298 -0
  469. package/recce-source/recce/tasks/query.py +450 -0
  470. package/recce-source/recce/tasks/rowcount.py +277 -0
  471. package/recce-source/recce/tasks/schema.py +65 -0
  472. package/recce-source/recce/tasks/top_k.py +172 -0
  473. package/recce-source/recce/tasks/utils.py +147 -0
  474. package/recce-source/recce/tasks/valuediff.py +497 -0
  475. package/recce-source/recce/util/__init__.py +4 -0
  476. package/recce-source/recce/util/api_token.py +80 -0
  477. package/recce-source/recce/util/breaking.py +330 -0
  478. package/recce-source/recce/util/cache.py +25 -0
  479. package/recce-source/recce/util/cll.py +355 -0
  480. package/recce-source/recce/util/cloud/__init__.py +15 -0
  481. package/recce-source/recce/util/cloud/base.py +115 -0
  482. package/recce-source/recce/util/cloud/check_events.py +190 -0
  483. package/recce-source/recce/util/cloud/checks.py +242 -0
  484. package/recce-source/recce/util/io.py +120 -0
  485. package/recce-source/recce/util/lineage.py +83 -0
  486. package/recce-source/recce/util/logger.py +25 -0
  487. package/recce-source/recce/util/onboarding_state.py +45 -0
  488. package/recce-source/recce/util/perf_tracking.py +85 -0
  489. package/recce-source/recce/util/pydantic_model.py +22 -0
  490. package/recce-source/recce/util/recce_cloud.py +454 -0
  491. package/recce-source/recce/util/singleton.py +18 -0
  492. package/recce-source/recce/util/startup_perf.py +121 -0
  493. package/recce-source/recce/yaml/__init__.py +58 -0
  494. package/recce-source/recce_cloud/README.md +780 -0
  495. package/recce-source/recce_cloud/VERSION +1 -0
  496. package/recce-source/recce_cloud/__init__.py +24 -0
  497. package/recce-source/recce_cloud/api/__init__.py +17 -0
  498. package/recce-source/recce_cloud/api/base.py +132 -0
  499. package/recce-source/recce_cloud/api/client.py +186 -0
  500. package/recce-source/recce_cloud/api/exceptions.py +26 -0
  501. package/recce-source/recce_cloud/api/factory.py +63 -0
  502. package/recce-source/recce_cloud/api/github.py +106 -0
  503. package/recce-source/recce_cloud/api/gitlab.py +111 -0
  504. package/recce-source/recce_cloud/artifact.py +57 -0
  505. package/recce-source/recce_cloud/ci_providers/__init__.py +9 -0
  506. package/recce-source/recce_cloud/ci_providers/base.py +82 -0
  507. package/recce-source/recce_cloud/ci_providers/detector.py +147 -0
  508. package/recce-source/recce_cloud/ci_providers/github_actions.py +136 -0
  509. package/recce-source/recce_cloud/ci_providers/gitlab_ci.py +130 -0
  510. package/recce-source/recce_cloud/cli.py +434 -0
  511. package/recce-source/recce_cloud/download.py +230 -0
  512. package/recce-source/recce_cloud/hatch_build.py +20 -0
  513. package/recce-source/recce_cloud/pyproject.toml +49 -0
  514. package/recce-source/recce_cloud/upload.py +214 -0
  515. package/recce-source/test.py +0 -0
  516. package/recce-source/tests/__init__.py +0 -0
  517. package/recce-source/tests/adapter/__init__.py +0 -0
  518. package/recce-source/tests/adapter/dbt_adapter/__init__.py +0 -0
  519. package/recce-source/tests/adapter/dbt_adapter/conftest.py +17 -0
  520. package/recce-source/tests/adapter/dbt_adapter/dbt_test_helper.py +298 -0
  521. package/recce-source/tests/adapter/dbt_adapter/test_dbt_adapter.py +25 -0
  522. package/recce-source/tests/adapter/dbt_adapter/test_dbt_cll.py +717 -0
  523. package/recce-source/tests/adapter/dbt_adapter/test_proj/dbt_project.yml +4 -0
  524. package/recce-source/tests/adapter/dbt_adapter/test_proj/manifest.json +1 -0
  525. package/recce-source/tests/adapter/dbt_adapter/test_proj/package-lock.yml +8 -0
  526. package/recce-source/tests/adapter/dbt_adapter/test_proj/packages.yml +7 -0
  527. package/recce-source/tests/adapter/dbt_adapter/test_proj/profiles.yml +6 -0
  528. package/recce-source/tests/adapter/dbt_adapter/test_selector.py +205 -0
  529. package/recce-source/tests/apis/__init__.py +0 -0
  530. package/recce-source/tests/apis/row_count_diff.json +59 -0
  531. package/recce-source/tests/apis/test_check_events_api.py +615 -0
  532. package/recce-source/tests/apis/test_run_func.py +433 -0
  533. package/recce-source/tests/catalog.json +527 -0
  534. package/recce-source/tests/data/manifest/base/catalog.json +1 -0
  535. package/recce-source/tests/data/manifest/base/manifest.json +1 -0
  536. package/recce-source/tests/data/manifest/pr2/catalog.json +1 -0
  537. package/recce-source/tests/data/manifest/pr2/manifest.json +1 -0
  538. package/recce-source/tests/manifest.json +10655 -0
  539. package/recce-source/tests/models/__init__.py +0 -0
  540. package/recce-source/tests/models/test_check.py +731 -0
  541. package/recce-source/tests/models/test_run_models.py +295 -0
  542. package/recce-source/tests/recce_cloud/__init__.py +0 -0
  543. package/recce-source/tests/recce_cloud/test_ci_providers.py +351 -0
  544. package/recce-source/tests/recce_cloud/test_cli.py +735 -0
  545. package/recce-source/tests/recce_cloud/test_client.py +379 -0
  546. package/recce-source/tests/recce_cloud/test_platform_clients.py +483 -0
  547. package/recce-source/tests/recce_state.json +1 -0
  548. package/recce-source/tests/state/test_cloud.py +719 -0
  549. package/recce-source/tests/state/test_local.py +164 -0
  550. package/recce-source/tests/state/test_state_loader.py +211 -0
  551. package/recce-source/tests/tasks/__init__.py +0 -0
  552. package/recce-source/tests/tasks/conftest.py +4 -0
  553. package/recce-source/tests/tasks/test_histogram.py +129 -0
  554. package/recce-source/tests/tasks/test_lineage.py +55 -0
  555. package/recce-source/tests/tasks/test_preset_checks.py +64 -0
  556. package/recce-source/tests/tasks/test_profile.py +397 -0
  557. package/recce-source/tests/tasks/test_query.py +528 -0
  558. package/recce-source/tests/tasks/test_row_count.py +133 -0
  559. package/recce-source/tests/tasks/test_schema.py +122 -0
  560. package/recce-source/tests/tasks/test_top_k.py +77 -0
  561. package/recce-source/tests/tasks/test_utils.py +439 -0
  562. package/recce-source/tests/tasks/test_valuediff.py +361 -0
  563. package/recce-source/tests/test_cli.py +236 -0
  564. package/recce-source/tests/test_cli_mcp_optional.py +45 -0
  565. package/recce-source/tests/test_cloud_listing_cli.py +324 -0
  566. package/recce-source/tests/test_config.py +43 -0
  567. package/recce-source/tests/test_connect_to_cloud.py +82 -0
  568. package/recce-source/tests/test_core.py +174 -0
  569. package/recce-source/tests/test_dbt.py +36 -0
  570. package/recce-source/tests/test_mcp_server.py +505 -0
  571. package/recce-source/tests/test_pull_request.py +130 -0
  572. package/recce-source/tests/test_server.py +202 -0
  573. package/recce-source/tests/test_server_lifespan.py +138 -0
  574. package/recce-source/tests/test_summary.py +73 -0
  575. package/recce-source/tests/util/__init__.py +0 -0
  576. package/recce-source/tests/util/cloud/__init__.py +0 -0
  577. package/recce-source/tests/util/cloud/test_check_events.py +255 -0
  578. package/recce-source/tests/util/cloud/test_checks.py +204 -0
  579. package/recce-source/tests/util/test_api_token.py +119 -0
  580. package/recce-source/tests/util/test_breaking.py +1427 -0
  581. package/recce-source/tests/util/test_cll.py +706 -0
  582. package/recce-source/tests/util/test_lineage.py +122 -0
  583. package/recce-source/tests/util/test_onboarding_state.py +84 -0
  584. package/recce-source/tests/util/test_recce_cloud.py +231 -0
  585. package/recce-source/tox.ini +40 -0
  586. package/recce-source/uv.lock +3928 -0
  587. package/src/api/index.ts +32 -0
  588. package/src/components/index.ts +154 -0
  589. package/src/global.d.ts +14 -0
  590. package/src/hooks/index.ts +56 -0
  591. package/src/index.ts +17 -0
  592. package/src/lib/hooks/RouteConfigContext.ts +139 -0
  593. package/src/lib/hooks/useAppRouter.ts +240 -0
  594. package/src/mui-augmentation.d.ts +139 -0
  595. package/src/theme/index.ts +13 -0
  596. package/src/theme.ts +23 -0
  597. package/src/types/index.ts +23 -0
  598. package/dist/index-Bv5R8iLo.d.mts.map +0 -1
  599. package/dist/index-CUtFlKOo.d.ts.map +0 -1
  600. package/dist/state-CELzQ0tM.mjs.map +0 -1
  601. package/dist/state-CemiRRon.js.map +0 -1
@@ -0,0 +1,355 @@
1
+ import time
2
+ from dataclasses import dataclass
3
+ from typing import Dict, List, Optional, Tuple
4
+
5
+ import sqlglot.expressions as exp
6
+ from sqlglot import Dialect, parse_one
7
+ from sqlglot.errors import OptimizeError, SqlglotError
8
+ from sqlglot.optimizer import Scope, traverse_scope
9
+ from sqlglot.optimizer.qualify import qualify
10
+
11
+ from recce.exceptions import RecceException
12
+ from recce.models.types import CllColumn, CllColumnDep
13
+
14
+ CllResult = Tuple[
15
+ List[CllColumnDep], # Model to column dependencies
16
+ Dict[str, CllColumn], # Column to column dependencies
17
+ ]
18
+
19
+
20
+ @dataclass
21
+ class CLLPerformanceTracking:
22
+ lineage_start = None
23
+ lineage_elapsed = None
24
+ column_lineage_start = None
25
+ column_lineage_elapsed = None
26
+
27
+ total_nodes = None
28
+ sqlglot_error_nodes = 0
29
+ other_error_nodes = 0
30
+
31
+ def start_lineage(self):
32
+ self.lineage_start = time.perf_counter_ns()
33
+
34
+ def end_lineage(self):
35
+ if self.lineage_start is None:
36
+ return
37
+ self.lineage_elapsed = (time.perf_counter_ns() - self.lineage_start) / 1000000
38
+
39
+ def start_column_lineage(self):
40
+ self.column_lineage_start = time.perf_counter_ns()
41
+
42
+ def end_column_lineage(self):
43
+ if self.column_lineage_start is None:
44
+ return
45
+ self.column_lineage_elapsed = (time.perf_counter_ns() - self.column_lineage_start) / 1000000
46
+
47
+ def set_total_nodes(self, total_nodes):
48
+ self.total_nodes = total_nodes
49
+
50
+ def increment_sqlglot_error_nodes(self):
51
+ self.sqlglot_error_nodes += 1
52
+
53
+ def increment_other_error_nodes(self):
54
+ self.other_error_nodes += 1
55
+
56
+ def to_dict(self):
57
+ return {
58
+ "lineage_elapsed_ms": self.lineage_elapsed,
59
+ "column_lineage_elapsed_ms": self.column_lineage_elapsed,
60
+ "total_nodes": self.total_nodes,
61
+ "sqlglot_error_nodes": self.sqlglot_error_nodes,
62
+ "other_error_nodes": self.other_error_nodes,
63
+ }
64
+
65
+ def reset(self):
66
+ self.lineage_start = None
67
+ self.lineage_elapsed = None
68
+ self.column_lineage_start = None
69
+ self.column_lineage_elapsed = None
70
+
71
+ self.total_nodes = None
72
+ self.sqlglot_error_nodes = 0
73
+ self.other_error_nodes = 0
74
+
75
+
76
+ def _cll_column(proj, table_alias_map) -> CllColumn:
77
+ # given an expression, return the columns depends on
78
+ # [{node: table, column: column}, ...]
79
+ type = "source"
80
+ depends_on: List[CllColumnDep] = []
81
+
82
+ # instance of Column
83
+ if isinstance(proj, exp.Alias):
84
+ # 'select a as b'
85
+ # 'select CURRENT_TIMESTAMP() as create_at'
86
+ root = proj.this
87
+
88
+ for expression in root.walk(bfs=False):
89
+ if isinstance(expression, exp.Column):
90
+ column = expression
91
+ alias = column.table
92
+
93
+ if alias is None:
94
+ table = next(iter(table_alias_map.values()))
95
+ else:
96
+ table = table_alias_map.get(alias, alias)
97
+ depends_on.append(CllColumnDep(table, column.name))
98
+ if type == "source":
99
+ type = "passthrough"
100
+ elif isinstance(expression, (exp.Paren, exp.Identifier)):
101
+ pass
102
+ else:
103
+ type = "derived"
104
+
105
+ depends_on = _dedeup_depends_on(depends_on)
106
+
107
+ if len(depends_on) == 0:
108
+ type = "source"
109
+
110
+ if isinstance(proj, exp.Alias):
111
+ alias = proj
112
+ if type == "passthrough" and depends_on[0].column != alias.alias_or_name:
113
+ type = "renamed"
114
+
115
+ return CllColumn(type=type, depends_on=depends_on)
116
+
117
+
118
+ def _dedeup_depends_on(depends_on: List[CllColumnDep]) -> List[CllColumnDep]:
119
+ # deduplicate the depends_on list
120
+ dedup_set = set()
121
+ dedup_list = []
122
+ for col_dep in depends_on:
123
+ node_col = col_dep.node + "." + col_dep.column
124
+ if node_col not in dedup_set:
125
+ dedup_list.append(col_dep)
126
+ dedup_set.add(node_col)
127
+ return dedup_list
128
+
129
+
130
+ def _cll_set_scope(scope: Scope, scope_cll_map: dict[Scope, CllResult]) -> CllResult:
131
+ # model-to-column
132
+ m2c: List[CllColumnDep] = []
133
+ # column-to-column
134
+ c2c_map: Dict[str, CllColumn] = {}
135
+
136
+ for union_scope in scope.union_scopes:
137
+ sub_scope_result = scope_cll_map.get(union_scope)
138
+ if sub_scope_result is None:
139
+ raise RecceException(f"Scope {union_scope} not found in scope_cll_map")
140
+ sub_m2c, sub_c2c_map = sub_scope_result
141
+
142
+ for k, v in sub_c2c_map.items():
143
+ if k not in c2c_map:
144
+ c2c_map[k] = v
145
+ else:
146
+ c2c_map[k].depends_on.extend(v.depends_on)
147
+ c2c_map[k].transformation_type = "derived"
148
+
149
+ m2c.extend(sub_m2c)
150
+ return m2c, c2c_map
151
+
152
+
153
+ def _cll_select_scope(scope: Scope, scope_cll_map: dict[Scope, CllResult]) -> CllResult:
154
+ assert scope.expression.key == "select"
155
+
156
+ # model-to-column
157
+ m2c: List[CllColumnDep] = []
158
+ # column-to-column
159
+ c2c_map: Dict[str, CllColumn] = {}
160
+
161
+ table_alias_map = {t.alias_or_name: t.name for t in scope.tables}
162
+ select = scope.expression
163
+
164
+ def source_column_dependency(ref_column: exp.Column) -> Optional[CllColumn]:
165
+ column_name = ref_column.name
166
+ table_name = ref_column.table if ref_column.table != "" else next(iter(table_alias_map.values()))
167
+ source = scope.sources.get(table_name, None) # transformation_type: exp.Table | Scope
168
+ if isinstance(source, Scope):
169
+ ref_cll_result = scope_cll_map.get(source)
170
+ if ref_cll_result is None:
171
+ return None
172
+ _, sub_c2c_map = ref_cll_result
173
+ return sub_c2c_map.get(column_name)
174
+ elif isinstance(source, exp.Table):
175
+ return CllColumn(
176
+ name=column_name,
177
+ transformation_type="passthrough",
178
+ depends_on=[CllColumnDep(node=source.name, column=column_name)],
179
+ )
180
+ else:
181
+ return None
182
+
183
+ def subquery_cll(subquery: exp.Subquery) -> Optional[CllResult]:
184
+ select = subquery.find(exp.Select)
185
+ if select is None:
186
+ return None
187
+
188
+ matched_scope = None
189
+ for sub_scope in scope.subquery_scopes:
190
+ if sub_scope.expression == select:
191
+ matched_scope = sub_scope
192
+ break
193
+ if matched_scope is None:
194
+ return None
195
+
196
+ return scope_cll_map.get(matched_scope)
197
+
198
+ for proj in scope.expression.selects:
199
+ transformation_type = "source"
200
+ column_depends_on: List[CllColumnDep] = []
201
+ root = proj.this if isinstance(proj, exp.Alias) else proj
202
+ for expression in root.walk(bfs=False):
203
+ if isinstance(expression, exp.Column):
204
+ ref_column_dependency = source_column_dependency(expression)
205
+ if ref_column_dependency is not None:
206
+ column_depends_on.extend(ref_column_dependency.depends_on)
207
+ if ref_column_dependency.transformation_type == "derived":
208
+ transformation_type = "derived"
209
+ elif ref_column_dependency.transformation_type == "renamed":
210
+ if transformation_type == "source" or transformation_type == "passthrough":
211
+ transformation_type = "renamed"
212
+ elif ref_column_dependency.transformation_type == "passthrough":
213
+ if transformation_type == "source":
214
+ transformation_type = "passthrough"
215
+ else:
216
+ column_depends_on.append(CllColumnDep(expression.table, expression.name))
217
+ if transformation_type == "source":
218
+ transformation_type = "passthrough"
219
+
220
+ elif isinstance(expression, (exp.Paren, exp.Identifier)):
221
+ pass
222
+ else:
223
+ transformation_type = "derived"
224
+
225
+ column_depends_on = _dedeup_depends_on(column_depends_on)
226
+
227
+ if len(column_depends_on) == 0 and transformation_type != "source":
228
+ transformation_type = "source"
229
+
230
+ if isinstance(proj, exp.Alias):
231
+ alias = proj
232
+ if transformation_type == "passthrough" and column_depends_on[0].column != alias.alias_or_name:
233
+ transformation_type = "renamed"
234
+
235
+ c2c_map[proj.alias_or_name] = CllColumn(
236
+ name=proj.alias_or_name, transformation_type=transformation_type, depends_on=column_depends_on
237
+ )
238
+
239
+ def selected_column_dependency(ref_column: exp.Column) -> Optional[CllColumn]:
240
+ column_name = ref_column.name
241
+ return c2c_map.get(column_name)
242
+
243
+ # joins clause: Reference the source columns
244
+ if select.args.get("joins"):
245
+ joins = select.args.get("joins")
246
+ for join in joins:
247
+ if isinstance(join, exp.Join):
248
+ for ref_column in join.find_all(exp.Column):
249
+ if source_column_dependency(ref_column) is not None:
250
+ m2c.extend(source_column_dependency(ref_column).depends_on)
251
+
252
+ # where clauses: Reference the source columns
253
+ if select.args.get("where"):
254
+ where = select.args.get("where")
255
+ if isinstance(where, exp.Where):
256
+ for ref_column in where.find_all(exp.Column):
257
+ if source_column_dependency(ref_column) is not None:
258
+ m2c.extend(source_column_dependency(ref_column).depends_on)
259
+ for subquery in where.find_all(exp.Subquery):
260
+ sub_cll = subquery_cll(subquery)
261
+ if sub_cll is not None:
262
+ sub_m2c, sub_c2c_map = sub_cll
263
+ m2c.extend(sub_m2c)
264
+ for sub_c in sub_c2c_map.values():
265
+ m2c.extend(sub_c.depends_on)
266
+
267
+ # group by clause: Reference the source columns, column index
268
+ if select.args.get("group"):
269
+ group = select.args.get("group")
270
+ if isinstance(group, exp.Group):
271
+ for ref_column in group.find_all(exp.Column):
272
+ if source_column_dependency(ref_column) is not None:
273
+ m2c.extend(source_column_dependency(ref_column).depends_on)
274
+
275
+ # having clause: Reference the source columns, selected columns
276
+ if select.args.get("having"):
277
+ having = select.args.get("having")
278
+ if isinstance(having, exp.Having):
279
+ for ref_column in having.find_all(exp.Column):
280
+ if source_column_dependency(ref_column) is not None:
281
+ m2c.extend(source_column_dependency(ref_column).depends_on)
282
+ elif selected_column_dependency(ref_column) is not None:
283
+ m2c.extend(selected_column_dependency(ref_column).depends_on)
284
+ for subquery in having.find_all(exp.Subquery):
285
+ sub_cll = subquery_cll(subquery)
286
+ if sub_cll is not None:
287
+ sub_m2c, sub_c2c_map = sub_cll
288
+ m2c.extend(sub_m2c)
289
+ for sub_c in sub_c2c_map.values():
290
+ m2c.extend(sub_c.depends_on)
291
+
292
+ # order by clause: Reference the source columns, selected columns, column index
293
+ if select.args.get("order"):
294
+ order = select.args.get("order")
295
+ if isinstance(order, exp.Order):
296
+ for ref_column in order.find_all(exp.Column):
297
+ if source_column_dependency(ref_column) is not None:
298
+ m2c.extend(source_column_dependency(ref_column).depends_on)
299
+ elif selected_column_dependency(ref_column) is not None:
300
+ m2c.extend(selected_column_dependency(ref_column).depends_on)
301
+
302
+ for source in scope.sources.values():
303
+ scope_cll_result = scope_cll_map.get(source)
304
+ if scope_cll_result is None:
305
+ continue
306
+ sub_m2c, _ = scope_cll_result
307
+ m2c.extend(sub_m2c)
308
+
309
+ m2c = _dedeup_depends_on(m2c)
310
+
311
+ return m2c, c2c_map
312
+
313
+
314
+ def cll(sql, schema=None, dialect=None) -> CllResult:
315
+ # given a sql, return the cll for the sql
316
+ # {
317
+ # 'depends_on': [{'node': 'model_id', 'column': 'column'}],
318
+ # 'columns': {
319
+ # 'column1': {
320
+ # 'type': 'derived',
321
+ # 'depends_on': [{'node': 'model_id', 'column': 'column'}],
322
+ # }
323
+ # }
324
+ # }
325
+
326
+ dialect = Dialect.get(dialect) if dialect is not None else None
327
+
328
+ try:
329
+ expression = parse_one(sql, dialect=dialect)
330
+ except SqlglotError as e:
331
+ raise RecceException(f"Failed to parse SQL: {str(e)}")
332
+
333
+ try:
334
+ expression = qualify(expression, schema=schema, dialect=dialect)
335
+ except OptimizeError as e:
336
+ raise RecceException(f"Failed to optimize SQL: {str(e)}")
337
+ except SqlglotError as e:
338
+ raise RecceException(f"Failed to qualify SQL: {str(e)}")
339
+
340
+ result = None
341
+ scope_cll_map = {}
342
+ for scope in traverse_scope(expression):
343
+ scope_type = scope.expression.key
344
+ if scope_type == "union" or scope_type == "intersect" or scope_type == "except":
345
+ result = _cll_set_scope(scope, scope_cll_map)
346
+ elif scope_type == "select":
347
+ result = _cll_select_scope(scope, scope_cll_map)
348
+ else:
349
+ continue
350
+
351
+ scope_cll_map[scope] = result
352
+
353
+ if result is None:
354
+ raise RecceException("Failed to extract CLL from SQL")
355
+ return result
@@ -0,0 +1,15 @@
1
+ """
2
+ Recce Cloud API client modules.
3
+
4
+ This package provides modular access to Recce Cloud API endpoints.
5
+ """
6
+
7
+ from recce.util.cloud.base import CloudBase
8
+ from recce.util.cloud.check_events import CheckEventsCloud
9
+ from recce.util.cloud.checks import ChecksCloud
10
+
11
+ __all__ = [
12
+ "CloudBase",
13
+ "CheckEventsCloud",
14
+ "ChecksCloud",
15
+ ]
@@ -0,0 +1,115 @@
1
+ """
2
+ Base class for Recce Cloud API clients.
3
+
4
+ This module provides the common functionality shared across all cloud API clients.
5
+ """
6
+
7
+ import os
8
+ from typing import Dict, Optional
9
+
10
+ import requests
11
+
12
+ from recce.util.recce_cloud import (
13
+ DOCKER_INTERNAL_URL_PREFIX,
14
+ LOCALHOST_URL_PREFIX,
15
+ RECCE_CLOUD_API_HOST,
16
+ RecceCloudException,
17
+ )
18
+
19
+
20
+ class CloudBase:
21
+ """
22
+ Base class for Recce Cloud API operations.
23
+
24
+ Provides common functionality for making authenticated requests to the Recce Cloud API,
25
+ including request handling, error management, and Docker environment URL conversion.
26
+
27
+ Attributes:
28
+ token: Authentication token (API token or GitHub token)
29
+ token_type: Type of token ("api_token" or "github_token")
30
+ base_url: Base URL for API v1 endpoints
31
+ base_url_v2: Base URL for API v2 endpoints
32
+ """
33
+
34
+ def __init__(self, token: str):
35
+ """
36
+ Initialize the CloudBase client.
37
+
38
+ Args:
39
+ token: Authentication token for Recce Cloud API
40
+
41
+ Raises:
42
+ ValueError: If token is None
43
+ """
44
+ if token is None:
45
+ raise ValueError("Token cannot be None.")
46
+
47
+ self.token = token
48
+ self.token_type = "github_token" if token.startswith(("ghp_", "gho_", "ghu_", "ghs_", "ghr_")) else "api_token"
49
+ self.base_url = f"{RECCE_CLOUD_API_HOST}/api/v1"
50
+ self.base_url_v2 = f"{RECCE_CLOUD_API_HOST}/api/v2"
51
+
52
+ def _request(self, method: str, url: str, headers: Optional[Dict] = None, **kwargs):
53
+ """
54
+ Make an authenticated HTTP request to Recce Cloud API.
55
+
56
+ Args:
57
+ method: HTTP method (GET, POST, PATCH, DELETE, etc.)
58
+ url: Full URL for the request
59
+ headers: Optional additional headers
60
+ **kwargs: Additional arguments passed to requests.request
61
+
62
+ Returns:
63
+ Response object from requests library
64
+ """
65
+ headers = {
66
+ **(headers or {}),
67
+ "Authorization": f"Bearer {self.token}",
68
+ }
69
+ url = self._replace_localhost_with_docker_internal(url)
70
+ return requests.request(method, url, headers=headers, **kwargs)
71
+
72
+ @staticmethod
73
+ def _replace_localhost_with_docker_internal(url: str) -> Optional[str]:
74
+ """
75
+ Convert localhost URLs to docker internal URLs if running in Docker.
76
+
77
+ This is useful for local development when Recce is running inside a Docker container
78
+ and needs to access localhost services on the host machine.
79
+
80
+ Args:
81
+ url: URL that might contain localhost
82
+
83
+ Returns:
84
+ URL with localhost replaced by host.docker.internal if in Docker, otherwise original URL
85
+ """
86
+ if url is None:
87
+ return None
88
+
89
+ if (
90
+ os.environ.get("RECCE_SHARE_INSTANCE_ENV") == "docker"
91
+ or os.environ.get("RECCE_TASK_INSTANCE_ENV") == "docker"
92
+ or os.environ.get("RECCE_INSTANCE_ENV") == "docker"
93
+ ):
94
+ if url.startswith(LOCALHOST_URL_PREFIX):
95
+ return url.replace(LOCALHOST_URL_PREFIX, DOCKER_INTERNAL_URL_PREFIX)
96
+
97
+ return url
98
+
99
+ def _raise_for_status(self, response, message: str):
100
+ """
101
+ Raise RecceCloudException if the response status is not successful.
102
+
103
+ Args:
104
+ response: Response object from requests
105
+ message: Error message to include in the exception
106
+
107
+ Raises:
108
+ RecceCloudException: If response status code is not 2xx
109
+ """
110
+ if not response.ok:
111
+ raise RecceCloudException(
112
+ message=message,
113
+ reason=response.text,
114
+ status_code=response.status_code,
115
+ )
@@ -0,0 +1,190 @@
1
+ """
2
+ Recce Cloud API client for check event operations.
3
+
4
+ This module provides methods for managing check events (timeline/conversation) in Recce Cloud,
5
+ including CRUD operations for comments and retrieving state change events.
6
+ """
7
+
8
+ from typing import Dict, List
9
+
10
+ from recce.util.cloud.base import CloudBase
11
+
12
+
13
+ class CheckEventsCloud(CloudBase):
14
+ """
15
+ Client for Recce Cloud check event operations.
16
+
17
+ Provides methods to list, create, update, and delete check events
18
+ (comments and state changes) within Recce Cloud sessions.
19
+
20
+ Examples:
21
+ >>> client = CheckEventsCloud(token="your-api-token")
22
+ >>> events = client.list_events(
23
+ ... org_id="org123",
24
+ ... project_id="proj456",
25
+ ... session_id="sess789",
26
+ ... check_id="check001"
27
+ ... )
28
+ """
29
+
30
+ def _build_events_url(self, org_id: str, project_id: str, session_id: str, check_id: str) -> str:
31
+ """Build the base URL for check events endpoints."""
32
+ return f"{self.base_url_v2}/organizations/{org_id}/projects/{project_id}/sessions/{session_id}/checks/{check_id}/events"
33
+
34
+ def list_events(self, org_id: str, project_id: str, session_id: str, check_id: str) -> List[Dict]:
35
+ """
36
+ List all events for a check in chronological order.
37
+
38
+ Args:
39
+ org_id: Organization ID
40
+ project_id: Project ID
41
+ session_id: Session ID
42
+ check_id: Check ID
43
+
44
+ Returns:
45
+ List of event dictionaries
46
+
47
+ Raises:
48
+ RecceCloudException: If the request fails
49
+
50
+ Example:
51
+ >>> events = client.list_events("org123", "proj456", "sess789", "check001")
52
+ >>> for event in events:
53
+ ... print(f"{event['event_type']}: {event['content']}")
54
+ """
55
+ api_url = self._build_events_url(org_id, project_id, session_id, check_id)
56
+ query_params = {"include_deleted": True}
57
+ response = self._request("GET", api_url, params=query_params)
58
+
59
+ self._raise_for_status(
60
+ response,
61
+ "Failed to list check events from Recce Cloud.",
62
+ )
63
+
64
+ data = response.json()
65
+ # Response is wrapped: {"events": [...]}
66
+ return data.get("events", [])
67
+
68
+ def get_event(self, org_id: str, project_id: str, session_id: str, check_id: str, event_id: str) -> Dict:
69
+ """
70
+ Get a specific event by ID.
71
+
72
+ Args:
73
+ org_id: Organization ID
74
+ project_id: Project ID
75
+ session_id: Session ID
76
+ check_id: Check ID
77
+ event_id: Event ID
78
+
79
+ Returns:
80
+ Event dictionary
81
+
82
+ Raises:
83
+ RecceCloudException: If the request fails or event not found
84
+ """
85
+ api_url = f"{self._build_events_url(org_id, project_id, session_id, check_id)}/{event_id}"
86
+ response = self._request("GET", api_url)
87
+
88
+ self._raise_for_status(
89
+ response,
90
+ f"Failed to get check event {event_id} from Recce Cloud.",
91
+ )
92
+
93
+ data = response.json()
94
+ # Response is wrapped: {"event": {...}}
95
+ return data.get("event", {})
96
+
97
+ def create_comment(self, org_id: str, project_id: str, session_id: str, check_id: str, content: str) -> Dict:
98
+ """
99
+ Create a new comment on a check.
100
+
101
+ Args:
102
+ org_id: Organization ID
103
+ project_id: Project ID
104
+ session_id: Session ID
105
+ check_id: Check ID
106
+ content: Comment content (plain text or markdown)
107
+
108
+ Returns:
109
+ Created event dictionary
110
+
111
+ Raises:
112
+ RecceCloudException: If the request fails
113
+
114
+ Example:
115
+ >>> event = client.create_comment(
116
+ ... "org123", "proj456", "sess789", "check001",
117
+ ... "This looks good to me!"
118
+ ... )
119
+ >>> print(f"Created comment with ID: {event['id']}")
120
+ """
121
+ api_url = self._build_events_url(org_id, project_id, session_id, check_id)
122
+ response = self._request("POST", api_url, json={"content": content})
123
+
124
+ self._raise_for_status(
125
+ response,
126
+ "Failed to create comment in Recce Cloud.",
127
+ )
128
+
129
+ data = response.json()
130
+ # Response is wrapped: {"event": {...}}
131
+ return data.get("event", {})
132
+
133
+ def update_comment(
134
+ self, org_id: str, project_id: str, session_id: str, check_id: str, event_id: str, content: str
135
+ ) -> Dict:
136
+ """
137
+ Update an existing comment.
138
+
139
+ Only the author or an admin can update a comment.
140
+
141
+ Args:
142
+ org_id: Organization ID
143
+ project_id: Project ID
144
+ session_id: Session ID
145
+ check_id: Check ID
146
+ event_id: Event ID of the comment to update
147
+ content: New comment content
148
+
149
+ Returns:
150
+ Updated event dictionary
151
+
152
+ Raises:
153
+ RecceCloudException: If the request fails or user is not authorized
154
+ """
155
+ api_url = f"{self._build_events_url(org_id, project_id, session_id, check_id)}/{event_id}"
156
+ response = self._request("PATCH", api_url, json={"content": content})
157
+
158
+ self._raise_for_status(
159
+ response,
160
+ f"Failed to update comment {event_id} in Recce Cloud.",
161
+ )
162
+
163
+ data = response.json()
164
+ # Response is wrapped: {"event": {...}}
165
+ return data.get("event", {})
166
+
167
+ def delete_comment(self, org_id: str, project_id: str, session_id: str, check_id: str, event_id: str) -> None:
168
+ """
169
+ Delete a comment (soft delete).
170
+
171
+ Only the author or an admin can delete a comment.
172
+ The comment will be marked as deleted but remain in the timeline.
173
+
174
+ Args:
175
+ org_id: Organization ID
176
+ project_id: Project ID
177
+ session_id: Session ID
178
+ check_id: Check ID
179
+ event_id: Event ID of the comment to delete
180
+
181
+ Raises:
182
+ RecceCloudException: If the request fails or user is not authorized
183
+ """
184
+ api_url = f"{self._build_events_url(org_id, project_id, session_id, check_id)}/{event_id}"
185
+ response = self._request("DELETE", api_url)
186
+
187
+ self._raise_for_status(
188
+ response,
189
+ f"Failed to delete comment {event_id} in Recce Cloud.",
190
+ )