@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,127 @@
1
+ # Configuration file for recce
2
+ from rich.console import Console
3
+
4
+ from recce import yaml
5
+ from recce.exceptions import RecceConfigException
6
+ from recce.util import SingletonMeta
7
+
8
+ RECCE_CONFIG_FILE = "recce.yml"
9
+ RECCE_PRESET_CHECK_COMMENT = """Preset Checks
10
+ Please see https://docs.datarecce.io/features/preset-checks/
11
+ """
12
+ RECCE_ERROR_LOG_FILE = "recce_error.log"
13
+ console = Console()
14
+
15
+
16
+ class RecceConfig(metaclass=SingletonMeta):
17
+ def __init__(self, config_file=RECCE_CONFIG_FILE):
18
+ self.config_file = config_file
19
+ self.config = None
20
+ self.load()
21
+
22
+ def load(self):
23
+ try:
24
+ with open(self.config_file, "r", encoding="utf-8") as f:
25
+ config = yaml.safe_load(f)
26
+ self.config = config if config else {}
27
+ self._verify_preset_checks()
28
+ except FileNotFoundError:
29
+ console.print(f"[[orange3]NOTICE[/orange3]] Generate default Recce config file at '{self.config_file}'")
30
+ self.config = self.generate_template()
31
+ self.save()
32
+
33
+ def _verify_preset_checks(self):
34
+ from recce.tasks.core import CheckValidator
35
+
36
+ if not self.config.get("checks"):
37
+ return
38
+
39
+ for check in self.config["checks"]:
40
+ try:
41
+ check_type = check.get("type")
42
+ if check_type is None:
43
+ raise ValueError(f'Check type is required for check "{check}"')
44
+ if check_type == "lineage_diff":
45
+ from recce.tasks.lineage import LineageDiffCheckValidator
46
+
47
+ validator = LineageDiffCheckValidator()
48
+ elif check_type == "schema_diff":
49
+ from recce.tasks.schema import SchemaDiffCheckValidator
50
+
51
+ validator = SchemaDiffCheckValidator()
52
+ elif check_type == "row_count_diff":
53
+ from recce.tasks.rowcount import RowCountDiffCheckValidator
54
+
55
+ validator = RowCountDiffCheckValidator()
56
+ elif check_type == "query":
57
+ from recce.tasks.query import QueryCheckValidator
58
+
59
+ validator = QueryCheckValidator()
60
+ elif check_type == "query_diff":
61
+ from recce.tasks.query import QueryDiffCheckValidator
62
+
63
+ validator = QueryDiffCheckValidator()
64
+ elif check_type == "value_diff" or check_type == "value_diff_detail":
65
+ from recce.tasks.valuediff import ValueDiffCheckValidator
66
+
67
+ validator = ValueDiffCheckValidator()
68
+ elif check_type == "profile_diff":
69
+ from recce.tasks.profile import ProfileCheckValidator
70
+
71
+ validator = ProfileCheckValidator()
72
+ elif check_type == "top_k_diff":
73
+ from recce.tasks.top_k import TopKDiffCheckValidator
74
+
75
+ validator = TopKDiffCheckValidator()
76
+ elif check_type == "histogram_diff":
77
+ from recce.tasks.histogram import HistogramDiffCheckValidator
78
+
79
+ validator = HistogramDiffCheckValidator()
80
+ else:
81
+ validator = CheckValidator()
82
+ validator.validate(check)
83
+ except Exception as e:
84
+ import json
85
+
86
+ raise RecceConfigException(
87
+ f"Load preset checks failed from '{self.config_file}'\n{json.dumps(check, indent=2)}", cause=e
88
+ )
89
+
90
+ def generate_template(self):
91
+ data = yaml.CommentedMap(checks=yaml.CommentedSeq())
92
+ data.yaml_set_comment_before_after_key("checks", before=RECCE_PRESET_CHECK_COMMENT)
93
+ # Define default preset checks
94
+ default_checks = [
95
+ yaml.CommentedMap(
96
+ name="Row count diff",
97
+ description="Check the row count diff for all table models.",
98
+ type="row_count_diff",
99
+ params={"select": "state:modified,config.materialized:table"},
100
+ ),
101
+ yaml.CommentedMap(
102
+ name="Schema diff",
103
+ description="Check the schema diff for all nodes.",
104
+ type="schema_diff",
105
+ ),
106
+ ]
107
+
108
+ for check in default_checks:
109
+ data["checks"].append(check)
110
+
111
+ return data
112
+
113
+ def get(self, key, default=None):
114
+ return self.config.get(key, default)
115
+
116
+ def set(self, key, value):
117
+ self.config[key] = value
118
+
119
+ def save(self):
120
+ with open(RECCE_CONFIG_FILE, "w", encoding="utf-8") as f:
121
+ yaml.dump(self.config, f)
122
+
123
+ def __str__(self):
124
+ return yaml.dump(self.config)
125
+
126
+ def __repr__(self):
127
+ return self.__str__()
@@ -0,0 +1,138 @@
1
+ import base64
2
+ import os.path
3
+ import random
4
+ import threading
5
+ from http.server import BaseHTTPRequestHandler, HTTPServer
6
+ from pathlib import Path
7
+ from typing import Tuple
8
+ from urllib.parse import parse_qs, urlparse
9
+
10
+ from cryptography.hazmat.backends import default_backend
11
+ from cryptography.hazmat.primitives import hashes, serialization
12
+ from cryptography.hazmat.primitives.asymmetric import padding, rsa
13
+ from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey
14
+ from rich.console import Console
15
+
16
+ from recce.event import update_recce_api_token
17
+ from recce.exceptions import RecceConfigException
18
+ from recce.util.onboarding_state import update_onboarding_state
19
+ from recce.util.recce_cloud import RECCE_CLOUD_BASE_URL, RecceCloud
20
+
21
+ console = Console()
22
+
23
+ static_folder_path = Path(__file__).parent / "data"
24
+ _server_lock = threading.Lock()
25
+ _connection_url = None
26
+
27
+
28
+ def decrypt_code(private_key: RSAPrivateKey, code: str) -> str:
29
+ ciphertext = base64.b64decode(code)
30
+ plaintext = private_key.decrypt(
31
+ ciphertext,
32
+ padding.OAEP(
33
+ mgf=padding.MGF1(algorithm=hashes.SHA1()), # Node.js uses SHA1 by default
34
+ algorithm=hashes.SHA1(),
35
+ label=None,
36
+ ),
37
+ )
38
+ return plaintext.decode("utf-8")
39
+
40
+
41
+ def handle_callback_request(query_string: str, private_key: RSAPrivateKey):
42
+ query_params = parse_qs(query_string)
43
+ code = query_params.get("code", [None])[0]
44
+ if not code:
45
+ raise RecceConfigException("Missing `code` in query")
46
+
47
+ api_token = decrypt_code(private_key, code)
48
+ if not RecceCloud(api_token).verify_token():
49
+ raise RecceConfigException("Invalid Recce Cloud API token")
50
+
51
+ update_recce_api_token(api_token)
52
+ update_onboarding_state(api_token, False)
53
+
54
+ return api_token # for testability/debugging
55
+
56
+
57
+ def make_callback_handler(private_key: RSAPrivateKey):
58
+ class OneTimeHTTPRequestHandler(BaseHTTPRequestHandler):
59
+ def do_GET(self):
60
+ try:
61
+ with open(os.path.join(static_folder_path, "auth_callback.html"), "r", encoding="utf-8") as f:
62
+ callback_html_content = f.read()
63
+
64
+ # Parse query parameters
65
+ parsed_url = urlparse(self.path)
66
+
67
+ handle_callback_request(parsed_url.query, private_key)
68
+
69
+ # Construct HTML content
70
+ self.send_response(200)
71
+ self.send_header("Content-Type", "text/html")
72
+ self.send_header("Content-Length", str(len(callback_html_content.encode())))
73
+ self.end_headers()
74
+ self.wfile.write(callback_html_content.encode())
75
+
76
+ except Exception:
77
+ console.print_exception()
78
+ self.send_response(500)
79
+ self.end_headers()
80
+ self.wfile.write(b"<h1>Internal Server Error</h1>")
81
+ finally:
82
+ # Shut down the server after handling the first request
83
+ # Shutdown in a new thread to avoid deadlock
84
+ self.server.server_close()
85
+ threading.Thread(target=self.server.shutdown, daemon=True).start()
86
+
87
+ def log_message(self, format, *args):
88
+ # Suppress default logging
89
+ return
90
+
91
+ return OneTimeHTTPRequestHandler
92
+
93
+
94
+ def is_callback_server_running():
95
+ return _server_lock.locked()
96
+
97
+
98
+ def get_connection_url():
99
+ return _connection_url
100
+
101
+
102
+ def run_one_time_http_server(private_key: RSAPrivateKey, port=8080):
103
+ handler = make_callback_handler(private_key)
104
+ server = HTTPServer(("localhost", port), handler)
105
+ server.serve_forever()
106
+
107
+
108
+ def prepare_connection_url(public_key: RSAPublicKey):
109
+ public_key_pem_bytes = public_key.public_bytes(
110
+ encoding=serialization.Encoding.PEM,
111
+ format=serialization.PublicFormat.SubjectPublicKeyInfo,
112
+ )
113
+ public_key_pem_str = base64.b64encode(public_key_pem_bytes).decode("utf-8")
114
+ callback_port = random.randint(10000, 15000)
115
+ connect_url = f"{RECCE_CLOUD_BASE_URL}/connect?_key={public_key_pem_str}&_port={callback_port}"
116
+ return connect_url, callback_port
117
+
118
+
119
+ def generate_key_pair() -> Tuple[RSAPrivateKey, RSAPublicKey]:
120
+ key_size = 2048 # Should be at least 2048
121
+
122
+ private_key = rsa.generate_private_key(
123
+ public_exponent=65537, key_size=key_size, backend=default_backend() # Do not change
124
+ )
125
+
126
+ public_key = private_key.public_key()
127
+ return private_key, public_key
128
+
129
+
130
+ def connect_to_cloud_background_task(private_key: RSAPrivateKey, callback_port, connection_url):
131
+ if is_callback_server_running():
132
+ return
133
+
134
+ with _server_lock:
135
+ global _connection_url
136
+ _connection_url = connection_url
137
+ run_one_time_http_server(private_key, callback_port)
138
+ _connection_url = None
@@ -0,0 +1,334 @@
1
+ import hashlib
2
+ import json
3
+ import logging
4
+ import os
5
+ from dataclasses import dataclass, field
6
+ from typing import Callable, Dict, List, Optional, Set, Tuple
7
+
8
+ from recce.adapter.base import BaseAdapter
9
+ from recce.models import Check, Run
10
+ from recce.models.types import LineageDiff
11
+ from recce.state import (
12
+ GitRepoInfo,
13
+ PullRequestInfo,
14
+ RecceState,
15
+ RecceStateLoader,
16
+ RecceStateMetadata,
17
+ )
18
+ from recce.util.recce_cloud import set_recce_cloud_onboarding_state
19
+
20
+ logger = logging.getLogger("uvicorn")
21
+
22
+
23
+ @dataclass
24
+ class RecceContext:
25
+ review_mode: bool = False
26
+ adapter_type: str = None
27
+ adapter: BaseAdapter = None
28
+ state_loader: RecceStateLoader = None
29
+ runs: List[Run] = field(default_factory=list)
30
+ checks: List[Check] = field(default_factory=list)
31
+
32
+ @classmethod
33
+ def load(cls, **kwargs):
34
+ state_loader: RecceStateLoader = kwargs.get("state_loader")
35
+ is_review_mode = kwargs.get("review", False)
36
+
37
+ context = cls(
38
+ review_mode=is_review_mode,
39
+ state_loader=state_loader,
40
+ )
41
+
42
+ # Initiate the adapter
43
+ if kwargs.get("sqlmesh", False):
44
+ logger.warning("SQLMesh adapter is still in EXPERIMENTAL mode.")
45
+ from recce.adapter.sqlmesh_adapter import SqlmeshAdapter
46
+
47
+ context.adapter_type = "sqlmesh"
48
+ context.adapter = SqlmeshAdapter.load(**kwargs)
49
+ else:
50
+ from recce.adapter.dbt_adapter import DbtAdapter
51
+
52
+ context.adapter_type = "dbt"
53
+ context.adapter = DbtAdapter.load(**kwargs)
54
+
55
+ # Import state
56
+ if state_loader is not None:
57
+ state = state_loader.load()
58
+ if state:
59
+ context.import_state(state)
60
+
61
+ if is_review_mode:
62
+ if not state:
63
+ raise Exception("The state file is required for review mode")
64
+
65
+ return context
66
+
67
+ def get_model(self, model_id: str, base=False):
68
+ return self.adapter.get_model(model_id, base=base)
69
+
70
+ def get_node_name_by_id(self, unique_id: object) -> object:
71
+ return self.adapter.get_node_name_by_id(unique_id)
72
+
73
+ def generate_sql(self, sql_template: str, base: bool = False, context: Dict = {}):
74
+ self.adapter.generate_sql(sql_template, base=base, context=context)
75
+
76
+ def get_lineage(self, base: Optional[bool] = False):
77
+ return self.adapter.get_lineage(base=base)
78
+
79
+ def get_lineage_diff(self) -> LineageDiff:
80
+ return self.adapter.get_lineage_diff()
81
+
82
+ def build_name_to_unique_id_index(self, excluded_types: Set = None) -> Dict[str, str]:
83
+ name_to_unique_id = {}
84
+ curr = self.get_lineage(base=False)
85
+ base = self.get_lineage(base=True)
86
+
87
+ for unique_id, node in curr["nodes"].items():
88
+ if excluded_types and node.get("resource_type") in excluded_types:
89
+ continue
90
+ name_to_unique_id[node["name"]] = unique_id
91
+ for unique_id, node in base["nodes"].items():
92
+ if excluded_types and node.get("resource_type") in excluded_types:
93
+ continue
94
+ name_to_unique_id[node["name"]] = unique_id
95
+ return name_to_unique_id
96
+
97
+ def start_monitor_artifacts(self, callback: Callable = None):
98
+ self.adapter.start_monitor_artifacts(callback=callback)
99
+
100
+ def stop_monitor_artifacts(self):
101
+ self.adapter.stop_monitor_artifacts()
102
+
103
+ def refresh_manifest(self, refresh_file_path: str = None):
104
+ self.adapter.refresh(refresh_file_path)
105
+
106
+ def start_monitor_base_env(self, callback: Callable = None):
107
+ self.adapter.start_monitor_base_env(callback=callback)
108
+
109
+ def stop_monitor_base_env(self):
110
+ self.adapter.stop_monitor_base_env()
111
+
112
+ def export_state(self) -> RecceState:
113
+ """
114
+ Export the state to a RecceState object.
115
+ """
116
+ state = RecceState()
117
+ state.metadata = RecceStateMetadata()
118
+
119
+ # runs & checks & artifacts
120
+ state.runs = self.runs
121
+ state.checks = self.checks
122
+ state.artifacts = self.adapter.export_artifacts()
123
+
124
+ # git & pull_request. If in review mode, use the review state
125
+ if self.review_mode:
126
+ state.git = self.state_loader.state.git
127
+ state.pull_request = self.state_loader.state.pull_request
128
+ else:
129
+ git = GitRepoInfo.from_current_repository()
130
+ if git:
131
+ state.git = git
132
+ if self.state_loader.pr_info:
133
+ state.pull_request = self.state_loader.pr_info
134
+
135
+ return state
136
+
137
+ def export_demo_state(self) -> RecceState:
138
+ """
139
+ Export the demo state to a RecceState object for the demo sites.
140
+ """
141
+ state = RecceState()
142
+ state.metadata = RecceStateMetadata()
143
+
144
+ # runs & checks
145
+ state.runs = self.runs
146
+ state.checks = self.checks
147
+ state.artifacts = self.adapter.export_artifacts()
148
+ git = GitRepoInfo.from_current_repository()
149
+ if git:
150
+ state.git = git
151
+ pr = PullRequestInfo(url=os.getenv("RECCE_PR_URL"))
152
+ state.pull_request = pr
153
+
154
+ return state
155
+
156
+ def sync_state(self, method: str):
157
+ """
158
+ Sync the state with the remote.
159
+
160
+ :param method: merge, revert, overwrite
161
+
162
+ """
163
+ if method == "merge":
164
+ self.state_loader.refresh()
165
+ self.import_state(self.state_loader.state, merge=True)
166
+ state = self.export_state()
167
+ self.state_loader.export(state)
168
+ elif method == "revert":
169
+ self.state_loader.refresh()
170
+ self.import_state(self.state_loader.state, merge=False)
171
+ elif method == "overwrite":
172
+ state = self.export_state()
173
+ self.state_loader.export(state)
174
+ else:
175
+ raise Exception(f"Unsupported method: {method}")
176
+
177
+ def _merge_checks(self, import_checks: list[Check]):
178
+ checks = list(self.checks)
179
+ imports = 0
180
+
181
+ def _calculate_checksum(c: Check):
182
+ payload = json.dumps(
183
+ {
184
+ "type": str(c.type),
185
+ "params": c.params,
186
+ "view_options": c.view_options,
187
+ },
188
+ sort_keys=True,
189
+ )
190
+ return hashlib.sha256(payload.encode()).hexdigest()
191
+
192
+ checksum_map = {_calculate_checksum(c): c for c in self.checks if c.is_preset}
193
+ check_map = {c.check_id: c for c in self.checks}
194
+
195
+ # merge checks
196
+ for imported in import_checks:
197
+ check: Check = None
198
+ if imported.check_id in check_map:
199
+ check = check_map[imported.check_id]
200
+ elif imported.is_preset:
201
+ checksum = _calculate_checksum(imported)
202
+ if checksum in checksum_map:
203
+ check = checksum_map[checksum]
204
+ if check:
205
+ is_merge = check.merge(imported)
206
+ if is_merge:
207
+ imports += 1
208
+ else:
209
+ checks.append(imported)
210
+ imports += 1
211
+ self.checks = checks
212
+ return imports
213
+
214
+ def _merge_runs(self, import_runs: list[Run]):
215
+ runs = list(self.runs)
216
+ run_set = {run.run_id for run in self.runs}
217
+ imports = 0
218
+
219
+ for run in import_runs:
220
+ if run.run_id not in run_set:
221
+ runs.append(run)
222
+ imports += 1
223
+
224
+ runs.sort(key=lambda x: x.run_at)
225
+ self.runs = runs
226
+ return imports
227
+
228
+ def import_state(self, import_state: RecceState, merge: bool = True):
229
+ """
230
+ Import the state from another RecceState object.
231
+
232
+ :param import_state: the state to import
233
+ :param merge: whether to merge the state or replace the current state
234
+ """
235
+ import_runs = 0
236
+ import_checks = 0
237
+ if merge:
238
+ import_runs = self._merge_runs(import_state.runs)
239
+ import_checks = self._merge_checks(import_state.checks)
240
+ else:
241
+ self.runs = list(import_state.runs)
242
+ import_runs = len(self.runs)
243
+ self.checks = list(import_state.checks)
244
+ import_checks = len(self.checks)
245
+
246
+ # always merge for artifacts
247
+ if self.adapter:
248
+ self.adapter.import_artifacts(import_state.artifacts)
249
+
250
+ return import_runs, import_checks
251
+
252
+ def import_checks(self, import_state: RecceState, merge: bool = True):
253
+ """
254
+ Import the checks from another RecceState object.
255
+
256
+ :param import_state: the state to import
257
+ :param merge: whether to merge the state or replace the current state
258
+ """
259
+
260
+ if merge:
261
+ import_checks = self._merge_checks(import_state.checks)
262
+ else:
263
+ self.checks = list(import_state.checks)
264
+ import_checks = len(self.checks)
265
+
266
+ return import_checks
267
+
268
+ def mark_onboarding_completed(self):
269
+ if self.state_loader.cloud_mode:
270
+ try:
271
+ token = self.state_loader.cloud_options.get("github_token")
272
+ set_recce_cloud_onboarding_state(token, "completed")
273
+ except Exception as e:
274
+ logger.debug(f"Failed to mark onboarding completed in Recce Cloud. Reason: {str(e)}")
275
+ else:
276
+ # Skip the onboarding state for non-cloud mode
277
+ pass
278
+
279
+ @staticmethod
280
+ def verify_required_artifacts(**kwargs) -> Tuple[bool, Optional[str]]:
281
+ if kwargs.get("sqlmesh", False):
282
+ pass
283
+ else:
284
+ from recce.adapter.dbt_adapter import DbtAdapter
285
+
286
+ try:
287
+ DbtAdapter.load(**kwargs)
288
+ except FileNotFoundError as e:
289
+ return False, f"Cannot load the manifest: '{e.filename}'. Type 'recce debug'."
290
+
291
+ return True, None
292
+
293
+ def support_tasks(self):
294
+ return self.adapter.support_tasks()
295
+
296
+ def state_loader_mode(self):
297
+ """
298
+ The state loader mode is used for telemetry purpose.
299
+ """
300
+ if os.environ.get("DEMO", False):
301
+ return "demo"
302
+
303
+ if not self.state_loader:
304
+ return "none"
305
+
306
+ if self.state_loader.cloud_mode:
307
+ return "cloud"
308
+ elif self.state_loader.state_file:
309
+ return "file"
310
+ else:
311
+ return "none"
312
+
313
+
314
+ recce_context: Optional[RecceContext] = None
315
+
316
+
317
+ def load_context(**kwargs) -> RecceContext:
318
+ global recce_context
319
+ if recce_context is None:
320
+ recce_context = RecceContext.load(**kwargs)
321
+ return recce_context
322
+
323
+
324
+ def default_context() -> RecceContext:
325
+ return recce_context
326
+
327
+
328
+ def set_default_context(context: RecceContext):
329
+ """
330
+ Set the default context for the recce. This is for test purpose.
331
+ """
332
+
333
+ global recce_context
334
+ recce_context = context
@@ -0,0 +1,26 @@
1
+ import difflib
2
+
3
+ import pandas as pd
4
+
5
+
6
+ def diff_text(before: str, after: str):
7
+ if before is None and after is None:
8
+ print("not found in both states")
9
+ return
10
+ elif before == after:
11
+ print("no changes")
12
+ return
13
+
14
+ diff_output = difflib.unified_diff(before.splitlines(), after.splitlines(), "base", "current", lineterm="")
15
+ for line in diff_output:
16
+ print(line)
17
+
18
+
19
+ def diff_dataframe(before: pd.DataFrame, after: pd.DataFrame):
20
+ if before is None and after is None:
21
+ print("not found in both states")
22
+ return
23
+
24
+ before_aligned, after_aligned = before.align(after)
25
+ diff = before_aligned.compare(after_aligned, result_names=("base", "current"))
26
+ print(diff.to_string(na_rep="-"))
@@ -0,0 +1 @@
1
+ event_api_key: <API_KEY>
@@ -0,0 +1 @@
1
+ https://64b0b12395a4f8596e081b26ca720719@o1081482.ingest.sentry.io/4506268402515968