@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.
- package/dist/api.d.mts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/components.d.mts +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/hooks.d.mts +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/{index-BNUP2V_N.d.ts → index-B9lSPJTi.d.ts} +184 -2
- package/dist/index-B9lSPJTi.d.ts.map +1 -0
- package/dist/{index-DOPZuhD8.d.mts → index-IIXVIoOL.d.mts} +253 -71
- package/dist/index-IIXVIoOL.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +4 -0
- package/dist/theme.d.mts +2 -185
- package/dist/theme.d.ts +2 -185
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +4 -2
- package/recce-source/.editorconfig +26 -0
- package/recce-source/.flake8 +37 -0
- package/recce-source/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
- package/recce-source/.github/ISSUE_TEMPLATE/custom.md +10 -0
- package/recce-source/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
- package/recce-source/.github/PULL_REQUEST_TEMPLATE.md +21 -0
- package/recce-source/.github/copilot-instructions.md +331 -0
- package/recce-source/.github/instructions/backend-instructions.md +541 -0
- package/recce-source/.github/instructions/frontend-instructions.md +317 -0
- package/recce-source/.github/workflows/build-statics.yaml +72 -0
- package/recce-source/.github/workflows/bump.yaml +48 -0
- package/recce-source/.github/workflows/integration-tests-cloud.yaml +92 -0
- package/recce-source/.github/workflows/integration-tests-sqlmesh.yaml +33 -0
- package/recce-source/.github/workflows/integration-tests.yaml +52 -0
- package/recce-source/.github/workflows/nightly.yaml +246 -0
- package/recce-source/.github/workflows/release.yaml +196 -0
- package/recce-source/.github/workflows/tests-js.yaml +58 -0
- package/recce-source/.github/workflows/tests-python.yaml +128 -0
- package/recce-source/.pre-commit-config.yaml +26 -0
- package/recce-source/CLAUDE.md +483 -0
- package/recce-source/CODE_OF_CONDUCT.md +128 -0
- package/recce-source/CONTRIBUTING.md +107 -0
- package/recce-source/LICENSE +201 -0
- package/recce-source/Makefile +126 -0
- package/recce-source/README.md +182 -0
- package/recce-source/RECCE_CLOUD.md +81 -0
- package/recce-source/SECURITY.md +25 -0
- package/recce-source/docs/PACKAGING.md +340 -0
- package/recce-source/docs/README.md +1 -0
- package/recce-source/integration_tests/dbt/dbt_project.yml +26 -0
- package/recce-source/integration_tests/dbt/models/customers.sql +69 -0
- package/recce-source/integration_tests/dbt/models/docs.md +14 -0
- package/recce-source/integration_tests/dbt/models/orders.sql +56 -0
- package/recce-source/integration_tests/dbt/models/schema.yml +82 -0
- package/recce-source/integration_tests/dbt/models/staging/schema.yml +31 -0
- package/recce-source/integration_tests/dbt/models/staging/stg_customers.sql +22 -0
- package/recce-source/integration_tests/dbt/models/staging/stg_orders.sql +23 -0
- package/recce-source/integration_tests/dbt/models/staging/stg_payments.sql +25 -0
- package/recce-source/integration_tests/dbt/packages.yml +7 -0
- package/recce-source/integration_tests/dbt/profiles.yml +8 -0
- package/recce-source/integration_tests/dbt/seeds/raw_customers.csv +101 -0
- package/recce-source/integration_tests/dbt/seeds/raw_orders.csv +100 -0
- package/recce-source/integration_tests/dbt/seeds/raw_payments.csv +114 -0
- package/recce-source/integration_tests/dbt/seeds/raw_statuses.csv +5 -0
- package/recce-source/integration_tests/dbt/smoke_test.sh +72 -0
- package/recce-source/integration_tests/dbt/smoke_test_cloud.sh +71 -0
- package/recce-source/integration_tests/sqlmesh/__init__.py +0 -0
- package/recce-source/integration_tests/sqlmesh/audits/assert_item_price_above_zero.sql +9 -0
- package/recce-source/integration_tests/sqlmesh/audits/items.sql +7 -0
- package/recce-source/integration_tests/sqlmesh/audits/order_items.sql +7 -0
- package/recce-source/integration_tests/sqlmesh/config.py +171 -0
- package/recce-source/integration_tests/sqlmesh/helper.py +20 -0
- package/recce-source/integration_tests/sqlmesh/hooks/__init__.py +0 -0
- package/recce-source/integration_tests/sqlmesh/macros/__init__.py +0 -0
- package/recce-source/integration_tests/sqlmesh/macros/macros.py +8 -0
- package/recce-source/integration_tests/sqlmesh/macros/macros.sql +8 -0
- package/recce-source/integration_tests/sqlmesh/macros/utils.py +11 -0
- package/recce-source/integration_tests/sqlmesh/metrics/metrics.sql +25 -0
- package/recce-source/integration_tests/sqlmesh/models/customer_revenue_by_day.sql +41 -0
- package/recce-source/integration_tests/sqlmesh/models/customer_revenue_lifetime.sql +60 -0
- package/recce-source/integration_tests/sqlmesh/models/customers.sql +32 -0
- package/recce-source/integration_tests/sqlmesh/models/items.py +95 -0
- package/recce-source/integration_tests/sqlmesh/models/marketing.sql +15 -0
- package/recce-source/integration_tests/sqlmesh/models/order_items.py +95 -0
- package/recce-source/integration_tests/sqlmesh/models/orders.py +70 -0
- package/recce-source/integration_tests/sqlmesh/models/raw_marketing.py +62 -0
- package/recce-source/integration_tests/sqlmesh/models/top_waiters.sql +23 -0
- package/recce-source/integration_tests/sqlmesh/models/waiter_as_customer_by_day.sql +29 -0
- package/recce-source/integration_tests/sqlmesh/models/waiter_names.sql +10 -0
- package/recce-source/integration_tests/sqlmesh/models/waiter_revenue_by_day.sql +29 -0
- package/recce-source/integration_tests/sqlmesh/models/waiters.py +62 -0
- package/recce-source/integration_tests/sqlmesh/prep_env.sh +16 -0
- package/recce-source/integration_tests/sqlmesh/schema.yaml +5 -0
- package/recce-source/integration_tests/sqlmesh/seeds/waiter_names.csv +11 -0
- package/recce-source/integration_tests/sqlmesh/test_server.sh +29 -0
- package/recce-source/integration_tests/sqlmesh/tests/test_customer_revenue_by_day.yaml +63 -0
- package/recce-source/integration_tests/sqlmesh/tests/test_order_items.yaml +72 -0
- package/recce-source/js/.editorconfig +27 -0
- package/recce-source/js/.env.development +5 -0
- package/recce-source/js/.husky/pre-commit +29 -0
- package/recce-source/js/.nvmrc +1 -0
- package/recce-source/js/README.md +39 -0
- package/recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx +65 -0
- package/recce-source/js/app/(mainComponents)/NavBar.tsx +228 -0
- package/recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx +107 -0
- package/recce-source/js/app/(mainComponents)/TopBar.tsx +252 -0
- package/recce-source/js/app/@lineage/default.tsx +20 -0
- package/recce-source/js/app/@lineage/page.tsx +14 -0
- package/recce-source/js/app/MainLayout.tsx +170 -0
- package/recce-source/js/app/Providers.tsx +49 -0
- package/recce-source/js/app/checks/page.tsx +296 -0
- package/recce-source/js/app/error.tsx +93 -0
- package/recce-source/js/app/favicon.ico +0 -0
- package/recce-source/js/app/global-error.tsx +115 -0
- package/recce-source/js/app/global.css +82 -0
- package/recce-source/js/app/layout.tsx +48 -0
- package/recce-source/js/app/lineage/page.tsx +15 -0
- package/recce-source/js/app/page.tsx +12 -0
- package/recce-source/js/app/query/page.tsx +8 -0
- package/recce-source/js/biome.json +313 -0
- package/recce-source/js/jest.config.js +34 -0
- package/recce-source/js/jest.globals.d.ts +32 -0
- package/recce-source/js/jest.setup.js +91 -0
- package/recce-source/js/next.config.js +16 -0
- package/recce-source/js/package-lock.json +13843 -0
- package/recce-source/js/package.json +123 -0
- package/recce-source/js/pnpm-lock.yaml +9235 -0
- package/recce-source/js/pnpm-workspace.yaml +6 -0
- package/recce-source/js/postcss.config.js +5 -0
- package/recce-source/js/public/auth_callback.html +68 -0
- package/recce-source/js/public/imgs/feedback/thumbs-down.png +0 -0
- package/recce-source/js/public/imgs/feedback/thumbs-up.png +0 -0
- package/recce-source/js/public/imgs/reload-image.svg +4 -0
- package/recce-source/js/public/logo/recce-logo-white.png +0 -0
- package/recce-source/js/src/components/AuthModal/AuthModal.tsx +202 -0
- package/recce-source/js/src/components/app/AvatarDropdown.tsx +159 -0
- package/recce-source/js/src/components/app/EnvInfo.tsx +357 -0
- package/recce-source/js/src/components/app/Filename.tsx +388 -0
- package/recce-source/js/src/components/app/SetupConnectionPopover.tsx +91 -0
- package/recce-source/js/src/components/app/StateExporter.tsx +57 -0
- package/recce-source/js/src/components/app/StateImporter.tsx +198 -0
- package/recce-source/js/src/components/app/StateSharing.tsx +145 -0
- package/recce-source/js/src/components/app/StateSynchronizer.tsx +205 -0
- package/recce-source/js/src/components/charts/HistogramChart.tsx +291 -0
- package/recce-source/js/src/components/charts/SquareIcon.tsx +51 -0
- package/recce-source/js/src/components/charts/TopKSummaryList.tsx +457 -0
- package/recce-source/js/src/components/charts/chartTheme.ts +74 -0
- package/recce-source/js/src/components/check/CheckBreadcrumb.tsx +97 -0
- package/recce-source/js/src/components/check/CheckDescription.tsx +134 -0
- package/recce-source/js/src/components/check/CheckDetail.tsx +797 -0
- package/recce-source/js/src/components/check/CheckEmptyState.tsx +84 -0
- package/recce-source/js/src/components/check/CheckList.tsx +320 -0
- package/recce-source/js/src/components/check/LineageDiffView.tsx +32 -0
- package/recce-source/js/src/components/check/PresetCheckTemplateView.tsx +48 -0
- package/recce-source/js/src/components/check/SchemaDiffView.tsx +290 -0
- package/recce-source/js/src/components/check/check.ts +25 -0
- package/recce-source/js/src/components/check/timeline/CheckTimeline.tsx +163 -0
- package/recce-source/js/src/components/check/timeline/CommentInput.tsx +84 -0
- package/recce-source/js/src/components/check/timeline/TimelineEvent.tsx +468 -0
- package/recce-source/js/src/components/check/timeline/index.ts +12 -0
- package/recce-source/js/src/components/check/utils.ts +12 -0
- package/recce-source/js/src/components/data-grid/ScreenshotDataGrid.tsx +333 -0
- package/recce-source/js/src/components/data-grid/agGridStyles.css +55 -0
- package/recce-source/js/src/components/data-grid/agGridTheme.ts +43 -0
- package/recce-source/js/src/components/editor/CodeEditor.tsx +107 -0
- package/recce-source/js/src/components/editor/DiffEditor.tsx +162 -0
- package/recce-source/js/src/components/editor/index.ts +12 -0
- package/recce-source/js/src/components/errorboundary/ErrorBoundary.tsx +87 -0
- package/recce-source/js/src/components/histogram/HistogramDiffForm.tsx +147 -0
- package/recce-source/js/src/components/histogram/HistogramDiffResultView.tsx +63 -0
- package/recce-source/js/src/components/icons/index.tsx +142 -0
- package/recce-source/js/src/components/lineage/ActionControl.tsx +63 -0
- package/recce-source/js/src/components/lineage/ActionTag.tsx +141 -0
- package/recce-source/js/src/components/lineage/ChangeStatusLegend.tsx +46 -0
- package/recce-source/js/src/components/lineage/ColumnLevelLineageControl.tsx +327 -0
- package/recce-source/js/src/components/lineage/ColumnLevelLineageLegend.tsx +57 -0
- package/recce-source/js/src/components/lineage/GraphColumnNode.tsx +199 -0
- package/recce-source/js/src/components/lineage/GraphEdge.tsx +59 -0
- package/recce-source/js/src/components/lineage/GraphNode.tsx +555 -0
- package/recce-source/js/src/components/lineage/LineagePage.tsx +10 -0
- package/recce-source/js/src/components/lineage/LineageView.tsx +1384 -0
- package/recce-source/js/src/components/lineage/LineageViewContext.tsx +86 -0
- package/recce-source/js/src/components/lineage/LineageViewContextMenu.tsx +637 -0
- package/recce-source/js/src/components/lineage/LineageViewNotification.tsx +64 -0
- package/recce-source/js/src/components/lineage/LineageViewTopBar.tsx +596 -0
- package/recce-source/js/src/components/lineage/NodeSqlView.tsx +136 -0
- package/recce-source/js/src/components/lineage/NodeTag.tsx +278 -0
- package/recce-source/js/src/components/lineage/NodeView.tsx +642 -0
- package/recce-source/js/src/components/lineage/SandboxView.tsx +436 -0
- package/recce-source/js/src/components/lineage/ServerDisconnectedModalContent.tsx +105 -0
- package/recce-source/js/src/components/lineage/SetupConnectionBanner.tsx +52 -0
- package/recce-source/js/src/components/lineage/SingleEnvironmentQueryView.tsx +152 -0
- package/recce-source/js/src/components/lineage/graph.test.ts +31 -0
- package/recce-source/js/src/components/lineage/graph.ts +58 -0
- package/recce-source/js/src/components/lineage/lineage.test.ts +169 -0
- package/recce-source/js/src/components/lineage/lineage.ts +521 -0
- package/recce-source/js/src/components/lineage/styles.css +42 -0
- package/recce-source/js/src/components/lineage/styles.tsx +165 -0
- package/recce-source/js/src/components/lineage/useMultiNodesAction.ts +352 -0
- package/recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx +108 -0
- package/recce-source/js/src/components/onboarding-guide/Notification.tsx +62 -0
- package/recce-source/js/src/components/profile/ProfileDiffForm.tsx +134 -0
- package/recce-source/js/src/components/profile/ProfileDiffResultView.tsx +245 -0
- package/recce-source/js/src/components/query/ChangedOnlyCheckbox.tsx +29 -0
- package/recce-source/js/src/components/query/DiffText.tsx +120 -0
- package/recce-source/js/src/components/query/QueryDiffResultView.tsx +470 -0
- package/recce-source/js/src/components/query/QueryForm.tsx +80 -0
- package/recce-source/js/src/components/query/QueryPage.tsx +282 -0
- package/recce-source/js/src/components/query/QueryResultView.tsx +180 -0
- package/recce-source/js/src/components/query/SetupConnectionGuide.tsx +57 -0
- package/recce-source/js/src/components/query/SqlEditor.tsx +245 -0
- package/recce-source/js/src/components/query/ToggleSwitch.tsx +84 -0
- package/recce-source/js/src/components/query/styles.css +21 -0
- package/recce-source/js/src/components/routing/DirectUrlAccess.test.tsx +428 -0
- package/recce-source/js/src/components/routing/LineageStatePreservation.test.tsx +311 -0
- package/recce-source/js/src/components/routing/Navigation.test.tsx +256 -0
- package/recce-source/js/src/components/rowcount/RowCountDiffResultView.tsx +109 -0
- package/recce-source/js/src/components/rowcount/delta.ts +11 -0
- package/recce-source/js/src/components/run/RunList.tsx +303 -0
- package/recce-source/js/src/components/run/RunModal.tsx +191 -0
- package/recce-source/js/src/components/run/RunPage.tsx +26 -0
- package/recce-source/js/src/components/run/RunResultPane.tsx +454 -0
- package/recce-source/js/src/components/run/RunStatusAndDate.tsx +106 -0
- package/recce-source/js/src/components/run/RunToolbar.tsx +70 -0
- package/recce-source/js/src/components/run/RunView.tsx +196 -0
- package/recce-source/js/src/components/run/registry.ts +214 -0
- package/recce-source/js/src/components/run/types.ts +14 -0
- package/recce-source/js/src/components/schema/ColumnNameCell.test.tsx +169 -0
- package/recce-source/js/src/components/schema/ColumnNameCell.tsx +198 -0
- package/recce-source/js/src/components/schema/SchemaView.tsx +337 -0
- package/recce-source/js/src/components/schema/schemaDiff.ts +32 -0
- package/recce-source/js/src/components/schema/style.css +134 -0
- package/recce-source/js/src/components/screenshot/ScreenshotBox.tsx +39 -0
- package/recce-source/js/src/components/shared/HistoryToggle.tsx +35 -0
- package/recce-source/js/src/components/split/Split.tsx +40 -0
- package/recce-source/js/src/components/split/styles.css +24 -0
- package/recce-source/js/src/components/summary/ChangeSummary.tsx +264 -0
- package/recce-source/js/src/components/summary/SchemaSummary.tsx +123 -0
- package/recce-source/js/src/components/summary/SummaryView.tsx +29 -0
- package/recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx +48 -0
- package/recce-source/js/src/components/top-k/TopKDiffForm.tsx +58 -0
- package/recce-source/js/src/components/top-k/TopKDiffResultView.tsx +73 -0
- package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnGroupHeader.tsx +228 -0
- package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnHeader.tsx +113 -0
- package/recce-source/js/src/components/ui/dataGrid/defaultRenderCell.tsx +72 -0
- package/recce-source/js/src/components/ui/dataGrid/index.ts +23 -0
- package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.test.tsx +607 -0
- package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.tsx +211 -0
- package/recce-source/js/src/components/ui/dataGrid/schemaCells.test.tsx +452 -0
- package/recce-source/js/src/components/ui/dataGrid/schemaCells.tsx +142 -0
- package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.test.tsx +178 -0
- package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.tsx +275 -0
- package/recce-source/js/src/components/ui/markdown/ExternalLinkConfirmDialog.tsx +134 -0
- package/recce-source/js/src/components/ui/markdown/MarkdownContent.tsx +364 -0
- package/recce-source/js/src/components/ui/mui/index.ts +13 -0
- package/recce-source/js/src/components/ui/mui-provider.tsx +67 -0
- package/recce-source/js/src/components/ui/mui-theme.ts +1039 -0
- package/recce-source/js/src/components/ui/mui-utils.ts +113 -0
- package/recce-source/js/src/components/ui/toaster.tsx +288 -0
- package/recce-source/js/src/components/valuediff/ValueDiffDetailResultView.tsx +217 -0
- package/recce-source/js/src/components/valuediff/ValueDiffForm.tsx +246 -0
- package/recce-source/js/src/components/valuediff/ValueDiffResultView.tsx +82 -0
- package/recce-source/js/src/components/valuediff/shared.ts +33 -0
- package/recce-source/js/src/constants/tooltipMessage.ts +3 -0
- package/recce-source/js/src/constants/urls.ts +1 -0
- package/recce-source/js/src/lib/UrlHash.ts +12 -0
- package/recce-source/js/src/lib/api/adhocQuery.ts +70 -0
- package/recce-source/js/src/lib/api/axiosClient.ts +9 -0
- package/recce-source/js/src/lib/api/cacheKeys.ts +13 -0
- package/recce-source/js/src/lib/api/checkEvents.ts +252 -0
- package/recce-source/js/src/lib/api/checks.ts +129 -0
- package/recce-source/js/src/lib/api/cll.ts +53 -0
- package/recce-source/js/src/lib/api/connectToCloud.ts +13 -0
- package/recce-source/js/src/lib/api/flag.ts +37 -0
- package/recce-source/js/src/lib/api/info.ts +198 -0
- package/recce-source/js/src/lib/api/instanceInfo.ts +25 -0
- package/recce-source/js/src/lib/api/keepAlive.ts +108 -0
- package/recce-source/js/src/lib/api/lineagecheck.ts +35 -0
- package/recce-source/js/src/lib/api/localStorageKeys.ts +7 -0
- package/recce-source/js/src/lib/api/models.ts +59 -0
- package/recce-source/js/src/lib/api/profile.ts +65 -0
- package/recce-source/js/src/lib/api/rowcount.ts +19 -0
- package/recce-source/js/src/lib/api/runs.ts +174 -0
- package/recce-source/js/src/lib/api/schemacheck.ts +31 -0
- package/recce-source/js/src/lib/api/select.ts +25 -0
- package/recce-source/js/src/lib/api/sessionStorageKeys.ts +8 -0
- package/recce-source/js/src/lib/api/state.ts +117 -0
- package/recce-source/js/src/lib/api/track.ts +281 -0
- package/recce-source/js/src/lib/api/types.ts +284 -0
- package/recce-source/js/src/lib/api/user.ts +42 -0
- package/recce-source/js/src/lib/api/valuediff.ts +46 -0
- package/recce-source/js/src/lib/api/version.ts +40 -0
- package/recce-source/js/src/lib/const.ts +9 -0
- package/recce-source/js/src/lib/dataGrid/crossFunctionConsistency.test.ts +626 -0
- package/recce-source/js/src/lib/dataGrid/dataGridFactory.test.ts +2140 -0
- package/recce-source/js/src/lib/dataGrid/dataGridFactory.ts +397 -0
- package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.test.ts +132 -0
- package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.ts +126 -0
- package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.test.ts +1627 -0
- package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.ts +140 -0
- package/recce-source/js/src/lib/dataGrid/generators/toDataGrid.ts +67 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.test.ts +142 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.ts +71 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.test.ts +258 -0
- package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.ts +153 -0
- package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.test.ts +951 -0
- package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.ts +221 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.test.ts +395 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.ts +184 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.test.ts +884 -0
- package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.ts +113 -0
- package/recce-source/js/src/lib/dataGrid/index.ts +51 -0
- package/recce-source/js/src/lib/dataGrid/propertyBased.test.ts +858 -0
- package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.test.ts +482 -0
- package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.ts +345 -0
- package/recce-source/js/src/lib/dataGrid/shared/dataTypeEdgeCases.test.ts +698 -0
- package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.test.tsx +820 -0
- package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.tsx +277 -0
- package/recce-source/js/src/lib/dataGrid/shared/gridUtils.test.ts +785 -0
- package/recce-source/js/src/lib/dataGrid/shared/gridUtils.ts +370 -0
- package/recce-source/js/src/lib/dataGrid/shared/index.ts +81 -0
- package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.test.ts +909 -0
- package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.ts +325 -0
- package/recce-source/js/src/lib/dataGrid/shared/simpleColumnBuilder.tsx +240 -0
- package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.test.tsx +719 -0
- package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.tsx +231 -0
- package/recce-source/js/src/lib/dataGrid/shared/validation.test.ts +559 -0
- package/recce-source/js/src/lib/dataGrid/shared/validation.ts +367 -0
- package/recce-source/js/src/lib/dataGrid/warehouseNamingConventions.test.ts +1117 -0
- package/recce-source/js/src/lib/formatSelect.ts +50 -0
- package/recce-source/js/src/lib/hooks/ApiConfigContext.tsx +181 -0
- package/recce-source/js/src/lib/hooks/IdleTimeoutContext.tsx +177 -0
- package/recce-source/js/src/lib/hooks/LineageGraphContext.tsx +512 -0
- package/recce-source/js/src/lib/hooks/RecceActionContext.tsx +269 -0
- package/recce-source/js/src/lib/hooks/RecceCheckContext.tsx +33 -0
- package/recce-source/js/src/lib/hooks/RecceContextProvider.tsx +54 -0
- package/recce-source/js/src/lib/hooks/RecceInstanceContext.tsx +129 -0
- package/recce-source/js/src/lib/hooks/RecceQueryContext.tsx +98 -0
- package/recce-source/js/src/lib/hooks/RecceShareStateContext.tsx +59 -0
- package/recce-source/js/src/lib/hooks/ScreenShot.tsx +399 -0
- package/recce-source/js/src/lib/hooks/useAppRouter.test.ts +211 -0
- package/recce-source/js/src/lib/hooks/useAppRouter.ts +200 -0
- package/recce-source/js/src/lib/hooks/useCheckEvents.ts +99 -0
- package/recce-source/js/src/lib/hooks/useCheckToast.tsx +14 -0
- package/recce-source/js/src/lib/hooks/useClipBoardToast.tsx +27 -0
- package/recce-source/js/src/lib/hooks/useCountdownToast.tsx +102 -0
- package/recce-source/js/src/lib/hooks/useFeedbackCollectionToast.tsx +130 -0
- package/recce-source/js/src/lib/hooks/useGuideToast.tsx +45 -0
- package/recce-source/js/src/lib/hooks/useIdleDetection.tsx +185 -0
- package/recce-source/js/src/lib/hooks/useModelColumns.tsx +113 -0
- package/recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx +13 -0
- package/recce-source/js/src/lib/hooks/useRecceServerFlag.tsx +13 -0
- package/recce-source/js/src/lib/hooks/useRun.tsx +89 -0
- package/recce-source/js/src/lib/hooks/useThemeColors.ts +115 -0
- package/recce-source/js/src/lib/mergeKeys.test.ts +89 -0
- package/recce-source/js/src/lib/mergeKeys.ts +86 -0
- package/recce-source/js/src/lib/result/ResultErrorFallback.tsx +9 -0
- package/recce-source/js/src/lib/utils/formatTime.ts +84 -0
- package/recce-source/js/src/lib/utils/urls.ts +16 -0
- package/recce-source/js/src/utils/DropdownValuesInput.tsx +297 -0
- package/recce-source/js/src/utils/formatters.tsx +237 -0
- package/recce-source/js/src/utils/transforms.ts +81 -0
- package/recce-source/js/tsconfig.json +47 -0
- package/recce-source/macros/README.md +8 -0
- package/recce-source/macros/recce_athena.sql +73 -0
- package/recce-source/pyproject.toml +109 -0
- package/recce-source/recce/VERSION +1 -0
- package/recce-source/recce/__init__.py +84 -0
- package/recce-source/recce/adapter/__init__.py +0 -0
- package/recce-source/recce/adapter/base.py +109 -0
- package/recce-source/recce/adapter/dbt_adapter/__init__.py +1699 -0
- package/recce-source/recce/adapter/dbt_adapter/dbt_version.py +42 -0
- package/recce-source/recce/adapter/sqlmesh_adapter.py +141 -0
- package/recce-source/recce/apis/__init__.py +0 -0
- package/recce-source/recce/apis/check_api.py +203 -0
- package/recce-source/recce/apis/check_events_api.py +353 -0
- package/recce-source/recce/apis/check_func.py +130 -0
- package/recce-source/recce/apis/run_api.py +130 -0
- package/recce-source/recce/apis/run_func.py +258 -0
- package/recce-source/recce/artifact.py +266 -0
- package/recce-source/recce/cli.py +1846 -0
- package/recce-source/recce/config.py +127 -0
- package/recce-source/recce/connect_to_cloud.py +138 -0
- package/recce-source/recce/core.py +334 -0
- package/recce-source/recce/diff.py +26 -0
- package/recce-source/recce/event/CONFIG +1 -0
- package/recce-source/recce/event/SENTRY_DNS +1 -0
- package/recce-source/recce/event/__init__.py +304 -0
- package/recce-source/recce/event/collector.py +184 -0
- package/recce-source/recce/event/track.py +158 -0
- package/recce-source/recce/exceptions.py +21 -0
- package/recce-source/recce/git.py +77 -0
- package/recce-source/recce/github.py +222 -0
- package/recce-source/recce/mcp_server.py +861 -0
- package/recce-source/recce/models/__init__.py +6 -0
- package/recce-source/recce/models/check.py +473 -0
- package/recce-source/recce/models/run.py +46 -0
- package/recce-source/recce/models/types.py +218 -0
- package/recce-source/recce/pull_request.py +124 -0
- package/recce-source/recce/run.py +390 -0
- package/recce-source/recce/server.py +877 -0
- package/recce-source/recce/state/__init__.py +31 -0
- package/recce-source/recce/state/cloud.py +644 -0
- package/recce-source/recce/state/const.py +26 -0
- package/recce-source/recce/state/local.py +56 -0
- package/recce-source/recce/state/state.py +119 -0
- package/recce-source/recce/state/state_loader.py +174 -0
- package/recce-source/recce/summary.py +575 -0
- package/recce-source/recce/tasks/__init__.py +23 -0
- package/recce-source/recce/tasks/core.py +134 -0
- package/recce-source/recce/tasks/dataframe.py +170 -0
- package/recce-source/recce/tasks/histogram.py +433 -0
- package/recce-source/recce/tasks/lineage.py +19 -0
- package/recce-source/recce/tasks/profile.py +298 -0
- package/recce-source/recce/tasks/query.py +450 -0
- package/recce-source/recce/tasks/rowcount.py +277 -0
- package/recce-source/recce/tasks/schema.py +65 -0
- package/recce-source/recce/tasks/top_k.py +172 -0
- package/recce-source/recce/tasks/utils.py +147 -0
- package/recce-source/recce/tasks/valuediff.py +497 -0
- package/recce-source/recce/util/__init__.py +4 -0
- package/recce-source/recce/util/api_token.py +80 -0
- package/recce-source/recce/util/breaking.py +330 -0
- package/recce-source/recce/util/cache.py +25 -0
- package/recce-source/recce/util/cll.py +355 -0
- package/recce-source/recce/util/cloud/__init__.py +15 -0
- package/recce-source/recce/util/cloud/base.py +115 -0
- package/recce-source/recce/util/cloud/check_events.py +190 -0
- package/recce-source/recce/util/cloud/checks.py +242 -0
- package/recce-source/recce/util/io.py +120 -0
- package/recce-source/recce/util/lineage.py +83 -0
- package/recce-source/recce/util/logger.py +25 -0
- package/recce-source/recce/util/onboarding_state.py +45 -0
- package/recce-source/recce/util/perf_tracking.py +85 -0
- package/recce-source/recce/util/pydantic_model.py +22 -0
- package/recce-source/recce/util/recce_cloud.py +454 -0
- package/recce-source/recce/util/singleton.py +18 -0
- package/recce-source/recce/util/startup_perf.py +121 -0
- package/recce-source/recce/yaml/__init__.py +58 -0
- package/recce-source/recce_cloud/README.md +780 -0
- package/recce-source/recce_cloud/VERSION +1 -0
- package/recce-source/recce_cloud/__init__.py +24 -0
- package/recce-source/recce_cloud/api/__init__.py +17 -0
- package/recce-source/recce_cloud/api/base.py +132 -0
- package/recce-source/recce_cloud/api/client.py +186 -0
- package/recce-source/recce_cloud/api/exceptions.py +26 -0
- package/recce-source/recce_cloud/api/factory.py +63 -0
- package/recce-source/recce_cloud/api/github.py +106 -0
- package/recce-source/recce_cloud/api/gitlab.py +111 -0
- package/recce-source/recce_cloud/artifact.py +57 -0
- package/recce-source/recce_cloud/ci_providers/__init__.py +9 -0
- package/recce-source/recce_cloud/ci_providers/base.py +82 -0
- package/recce-source/recce_cloud/ci_providers/detector.py +147 -0
- package/recce-source/recce_cloud/ci_providers/github_actions.py +136 -0
- package/recce-source/recce_cloud/ci_providers/gitlab_ci.py +130 -0
- package/recce-source/recce_cloud/cli.py +434 -0
- package/recce-source/recce_cloud/download.py +230 -0
- package/recce-source/recce_cloud/hatch_build.py +20 -0
- package/recce-source/recce_cloud/pyproject.toml +49 -0
- package/recce-source/recce_cloud/upload.py +214 -0
- package/recce-source/test.py +0 -0
- package/recce-source/tests/__init__.py +0 -0
- package/recce-source/tests/adapter/__init__.py +0 -0
- package/recce-source/tests/adapter/dbt_adapter/__init__.py +0 -0
- package/recce-source/tests/adapter/dbt_adapter/conftest.py +17 -0
- package/recce-source/tests/adapter/dbt_adapter/dbt_test_helper.py +298 -0
- package/recce-source/tests/adapter/dbt_adapter/test_dbt_adapter.py +25 -0
- package/recce-source/tests/adapter/dbt_adapter/test_dbt_cll.py +717 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/dbt_project.yml +4 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/manifest.json +1 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/package-lock.yml +8 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/packages.yml +7 -0
- package/recce-source/tests/adapter/dbt_adapter/test_proj/profiles.yml +6 -0
- package/recce-source/tests/adapter/dbt_adapter/test_selector.py +205 -0
- package/recce-source/tests/apis/__init__.py +0 -0
- package/recce-source/tests/apis/row_count_diff.json +59 -0
- package/recce-source/tests/apis/test_check_events_api.py +615 -0
- package/recce-source/tests/apis/test_run_func.py +433 -0
- package/recce-source/tests/catalog.json +527 -0
- package/recce-source/tests/data/manifest/base/catalog.json +1 -0
- package/recce-source/tests/data/manifest/base/manifest.json +1 -0
- package/recce-source/tests/data/manifest/pr2/catalog.json +1 -0
- package/recce-source/tests/data/manifest/pr2/manifest.json +1 -0
- package/recce-source/tests/manifest.json +10655 -0
- package/recce-source/tests/models/__init__.py +0 -0
- package/recce-source/tests/models/test_check.py +731 -0
- package/recce-source/tests/models/test_run_models.py +295 -0
- package/recce-source/tests/recce_cloud/__init__.py +0 -0
- package/recce-source/tests/recce_cloud/test_ci_providers.py +351 -0
- package/recce-source/tests/recce_cloud/test_cli.py +735 -0
- package/recce-source/tests/recce_cloud/test_client.py +379 -0
- package/recce-source/tests/recce_cloud/test_platform_clients.py +483 -0
- package/recce-source/tests/recce_state.json +1 -0
- package/recce-source/tests/state/test_cloud.py +719 -0
- package/recce-source/tests/state/test_local.py +164 -0
- package/recce-source/tests/state/test_state_loader.py +211 -0
- package/recce-source/tests/tasks/__init__.py +0 -0
- package/recce-source/tests/tasks/conftest.py +4 -0
- package/recce-source/tests/tasks/test_histogram.py +129 -0
- package/recce-source/tests/tasks/test_lineage.py +55 -0
- package/recce-source/tests/tasks/test_preset_checks.py +64 -0
- package/recce-source/tests/tasks/test_profile.py +397 -0
- package/recce-source/tests/tasks/test_query.py +528 -0
- package/recce-source/tests/tasks/test_row_count.py +133 -0
- package/recce-source/tests/tasks/test_schema.py +122 -0
- package/recce-source/tests/tasks/test_top_k.py +77 -0
- package/recce-source/tests/tasks/test_utils.py +439 -0
- package/recce-source/tests/tasks/test_valuediff.py +361 -0
- package/recce-source/tests/test_cli.py +236 -0
- package/recce-source/tests/test_cli_mcp_optional.py +45 -0
- package/recce-source/tests/test_cloud_listing_cli.py +324 -0
- package/recce-source/tests/test_config.py +43 -0
- package/recce-source/tests/test_connect_to_cloud.py +82 -0
- package/recce-source/tests/test_core.py +174 -0
- package/recce-source/tests/test_dbt.py +36 -0
- package/recce-source/tests/test_mcp_server.py +505 -0
- package/recce-source/tests/test_pull_request.py +130 -0
- package/recce-source/tests/test_server.py +202 -0
- package/recce-source/tests/test_server_lifespan.py +138 -0
- package/recce-source/tests/test_summary.py +73 -0
- package/recce-source/tests/util/__init__.py +0 -0
- package/recce-source/tests/util/cloud/__init__.py +0 -0
- package/recce-source/tests/util/cloud/test_check_events.py +255 -0
- package/recce-source/tests/util/cloud/test_checks.py +204 -0
- package/recce-source/tests/util/test_api_token.py +119 -0
- package/recce-source/tests/util/test_breaking.py +1427 -0
- package/recce-source/tests/util/test_cll.py +706 -0
- package/recce-source/tests/util/test_lineage.py +122 -0
- package/recce-source/tests/util/test_onboarding_state.py +84 -0
- package/recce-source/tests/util/test_recce_cloud.py +231 -0
- package/recce-source/tox.ini +40 -0
- package/recce-source/uv.lock +3928 -0
- package/src/api/index.ts +32 -0
- package/src/components/index.ts +154 -0
- package/src/global.d.ts +14 -0
- package/src/hooks/index.ts +56 -0
- package/src/index.ts +17 -0
- package/src/lib/hooks/RouteConfigContext.ts +139 -0
- package/src/lib/hooks/useAppRouter.ts +240 -0
- package/src/mui-augmentation.d.ts +139 -0
- package/src/theme/index.ts +13 -0
- package/src/theme.ts +23 -0
- package/src/types/index.ts +23 -0
- package/dist/index-BNUP2V_N.d.ts.map +0 -1
- package/dist/index-DOPZuhD8.d.mts.map +0 -1
- package/dist/theme.d.mts.map +0 -1
- package/dist/theme.d.ts.map +0 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { formatInTimeZone } from "@jeromefitz/date-fns-tz";
|
|
2
|
+
import { TopKResult } from "@/lib/api/profile";
|
|
3
|
+
|
|
4
|
+
const NO_VALUE = "-";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* "Formatters" -- these are your data formatting that returns a formatted value for UI presentation (e.g. number, string, falsey)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Source: https://stackoverflow.com/questions/15900485/correct-way-to-convert-size-in-bytes-to-kb-mb-gb-in-javascript
|
|
12
|
+
* @param bytes
|
|
13
|
+
* @param decimals
|
|
14
|
+
* @returns a string that matches nearest byte unit (e.g. kb, mb, gb, etc)
|
|
15
|
+
*/
|
|
16
|
+
export function formatBytes(bytes?: number, decimals = 2) {
|
|
17
|
+
if (bytes === undefined) return;
|
|
18
|
+
if (!bytes) return "0 Bytes";
|
|
19
|
+
|
|
20
|
+
const k = 1024;
|
|
21
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
22
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
23
|
+
|
|
24
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
25
|
+
|
|
26
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @param dateStr ISO date string
|
|
30
|
+
* @returns a formatted date string in 'yyyy/MM/dd HH:mm:ss'
|
|
31
|
+
*/
|
|
32
|
+
export function formatReportTime(dateStr?: string) {
|
|
33
|
+
if (!dateStr) return;
|
|
34
|
+
const date = new Date(dateStr);
|
|
35
|
+
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
36
|
+
|
|
37
|
+
return formatInTimeZone(date, userTimezone, "yyyy-MM-dd HH:mm:ss zzz");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
* @param num number type input
|
|
43
|
+
* @param locales locale string
|
|
44
|
+
* @param options
|
|
45
|
+
* @returns a formatted string number, based on locale & options
|
|
46
|
+
*/
|
|
47
|
+
export function formatNumber(
|
|
48
|
+
num: number | string | undefined,
|
|
49
|
+
locales = "en-US",
|
|
50
|
+
options?: Intl.NumberFormatOptions,
|
|
51
|
+
) {
|
|
52
|
+
if (typeof num !== "number") return num;
|
|
53
|
+
return new Intl.NumberFormat(locales, options).format(num);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @param num fractional number type input
|
|
58
|
+
* @returns a formatted percentage string, based on its percentage proximity to either ends (<0.1% and >99.9%)
|
|
59
|
+
*/
|
|
60
|
+
export function formatIntervalMinMax(num: number) {
|
|
61
|
+
// * should show <0.1 % if the value is between (0%, 0.1%]
|
|
62
|
+
const isLowerBound = num > 0 && num <= 0.001;
|
|
63
|
+
// * should show >99.9% if the value is between [99.9%, 100%) .
|
|
64
|
+
const isUpperBound = num < 1 && num >= 0.999;
|
|
65
|
+
|
|
66
|
+
const formatter = (newArg = num) =>
|
|
67
|
+
formatNumber(newArg, "en-US", {
|
|
68
|
+
style: "percent",
|
|
69
|
+
minimumFractionDigits: 1,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (isLowerBound) {
|
|
73
|
+
const result = formatter(0.001);
|
|
74
|
+
return `<${result}`;
|
|
75
|
+
} else if (isUpperBound) {
|
|
76
|
+
const result = formatter(0.999);
|
|
77
|
+
return `>${result}`;
|
|
78
|
+
}
|
|
79
|
+
return formatter();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// SR side: No need for object record handling
|
|
83
|
+
// CR side: needs record handling
|
|
84
|
+
export function formatTestExpectedOrActual(value?: unknown): unknown {
|
|
85
|
+
if (!value) {
|
|
86
|
+
return NO_VALUE;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Needed due to comparison's get assertions DS
|
|
90
|
+
if (typeof value === "object") {
|
|
91
|
+
return JSON.stringify(value);
|
|
92
|
+
// return Object.keys(value).map((key) =>
|
|
93
|
+
// typeof value[key] === 'string' ? value[key] : JSON.stringify(value[key]),
|
|
94
|
+
// );
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
show the most common values (aka Mode)
|
|
102
|
+
* give null if type invalids
|
|
103
|
+
* skip null value
|
|
104
|
+
* show top 2 if the values share the same counting, examples:
|
|
105
|
+
(more than 2) a:100, b:100, c:100 => a, b, ...
|
|
106
|
+
(2) a:100, b:100 => a
|
|
107
|
+
(2) null:100, a:100, b:100 => a, b
|
|
108
|
+
(2) null:101, a:100, b:100 => a, b
|
|
109
|
+
(2) a:100, b:100 => a, b
|
|
110
|
+
(1) a:100 => a
|
|
111
|
+
(1) a:100, b:99, c:99 => a
|
|
112
|
+
*/
|
|
113
|
+
export function formatTopKMetrics(topK?: TopKResult): {
|
|
114
|
+
topValues?: string;
|
|
115
|
+
topCounts?: string;
|
|
116
|
+
} {
|
|
117
|
+
if (!topK) return {};
|
|
118
|
+
const { counts, values } = topK;
|
|
119
|
+
const topValues = `${values[0]}`;
|
|
120
|
+
const topCounts = `${counts[0]}`;
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
topValues,
|
|
124
|
+
topCounts,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* A method to handle falsey non-numbers (relevant for comparison reports with column shifts, where base/target values can be undefined)
|
|
130
|
+
* @param value {string | number} any value that will be checked as number
|
|
131
|
+
* @param fn {function} any function to format the valid number
|
|
132
|
+
* @param emptyLabel {string} the return value if falsey value
|
|
133
|
+
*/
|
|
134
|
+
export function formatColumnValueWith(
|
|
135
|
+
value: string | number,
|
|
136
|
+
fn: (input: number) => string,
|
|
137
|
+
emptyLabel: string = NO_VALUE,
|
|
138
|
+
): string {
|
|
139
|
+
if (typeof value === "string") return value;
|
|
140
|
+
return isNaN(value) ? emptyLabel : fn(value);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
*
|
|
145
|
+
* @param input string to check for truncation with '...'
|
|
146
|
+
* @param end position at which to truncate
|
|
147
|
+
* @returns original or tooltip-wrapped truncated string
|
|
148
|
+
*/
|
|
149
|
+
export function formatTruncateString(input: string, end: number) {
|
|
150
|
+
const shouldTruncate = input.length >= end;
|
|
151
|
+
return shouldTruncate ? input.slice(0, end) + "..." : input;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* base < -2 => 2dp, scientific (small decimals)
|
|
155
|
+
* base < 0 => 3dp (big decimals)
|
|
156
|
+
* base < 3 => 2dp (ones, tens, hundreds)
|
|
157
|
+
* base < 6 => 1dp, K (thousands)
|
|
158
|
+
* base < 9 => 1dp, M (millions)
|
|
159
|
+
* base < 12 => 1dp, T (trillions)
|
|
160
|
+
* base < 15 => 1dp, B (billions)
|
|
161
|
+
* base >= 15 => 0dp, B (billions)
|
|
162
|
+
* @param input
|
|
163
|
+
* @returns a formatted number by abbreviation, based on its order of magnitude
|
|
164
|
+
*/
|
|
165
|
+
export function formatAsAbbreviatedNumber(input: number | string) {
|
|
166
|
+
// type guard for numbers (e.g. datetime strings)
|
|
167
|
+
if (typeof input !== "number") return input;
|
|
168
|
+
else {
|
|
169
|
+
// convert negatives
|
|
170
|
+
const inputAsPositive = Math.abs(input);
|
|
171
|
+
|
|
172
|
+
const twoDecimal = 10 ** -2;
|
|
173
|
+
const thousand = 10 ** 3;
|
|
174
|
+
const million = 10 ** 6;
|
|
175
|
+
const billion = 10 ** 9;
|
|
176
|
+
const trillion = 10 ** 12;
|
|
177
|
+
const trillionPlus = 10 ** 15;
|
|
178
|
+
|
|
179
|
+
const isLargeFractionals = inputAsPositive >= twoDecimal;
|
|
180
|
+
const isOnesTensHundreds = inputAsPositive >= 1;
|
|
181
|
+
const isThousands = inputAsPositive >= thousand;
|
|
182
|
+
const isMillions = inputAsPositive >= million;
|
|
183
|
+
const isBillions = inputAsPositive >= billion;
|
|
184
|
+
const isSmallTrillions = inputAsPositive >= trillion;
|
|
185
|
+
const isLargeTrillions = inputAsPositive >= trillionPlus;
|
|
186
|
+
|
|
187
|
+
// format as 'T' and beyond (trillions+)
|
|
188
|
+
if (isLargeTrillions || isSmallTrillions)
|
|
189
|
+
return new Intl.NumberFormat("en-US", {
|
|
190
|
+
style: "unit",
|
|
191
|
+
unit: "liter", //just a placeholder
|
|
192
|
+
unitDisplay: "narrow",
|
|
193
|
+
maximumFractionDigits: isLargeTrillions ? 0 : 2,
|
|
194
|
+
})
|
|
195
|
+
.format(input / 1.0e12)
|
|
196
|
+
.replace("L", "T");
|
|
197
|
+
// format as 'B', 'M', 'K' (billions to thousands)
|
|
198
|
+
else if (isBillions || isMillions || isThousands) {
|
|
199
|
+
const lookup = {
|
|
200
|
+
base: isBillions ? billion : isMillions ? million : thousand,
|
|
201
|
+
unit: isBillions ? "B" : isMillions ? "M" : "K",
|
|
202
|
+
};
|
|
203
|
+
return new Intl.NumberFormat("en-US", {
|
|
204
|
+
style: "unit",
|
|
205
|
+
unit: "liter", //just a placeholder
|
|
206
|
+
unitDisplay: "narrow",
|
|
207
|
+
maximumFractionDigits: 1,
|
|
208
|
+
})
|
|
209
|
+
.format(input / lookup.base)
|
|
210
|
+
.replace("L", lookup.unit);
|
|
211
|
+
}
|
|
212
|
+
// format as unlabeled (1 to 999)
|
|
213
|
+
else if (isOnesTensHundreds)
|
|
214
|
+
return new Intl.NumberFormat("en-US", {
|
|
215
|
+
maximumFractionDigits: 2,
|
|
216
|
+
}).format(input);
|
|
217
|
+
// format as fractionals (< 1)
|
|
218
|
+
else
|
|
219
|
+
return new Intl.NumberFormat("en-US", {
|
|
220
|
+
maximumFractionDigits: isLargeFractionals ? 3 : 2,
|
|
221
|
+
notation:
|
|
222
|
+
isLargeFractionals || inputAsPositive === 0
|
|
223
|
+
? "standard"
|
|
224
|
+
: "scientific",
|
|
225
|
+
}).format(input);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* formats as 'Category' instead of 'category' or 'CATEGORY'
|
|
231
|
+
*/
|
|
232
|
+
export function formatTitleCase(input?: string) {
|
|
233
|
+
if (!input) return NO_VALUE;
|
|
234
|
+
const start = input.slice(0, 1).toUpperCase();
|
|
235
|
+
const rest = input.slice(1).toLowerCase();
|
|
236
|
+
return `${start}${rest}`;
|
|
237
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { DataFrame, RowDataTypes, RowObjectType } from "@/lib/api/types";
|
|
2
|
+
|
|
3
|
+
export function dataFrameToRowObjects(dataFrame: DataFrame): RowObjectType[] {
|
|
4
|
+
return dataFrame.data.map((row, index) => ({
|
|
5
|
+
...dataFrame.columns.reduce<Record<string, RowDataTypes>>(
|
|
6
|
+
(obj, column, colIndex) => {
|
|
7
|
+
obj[column.key] = row[colIndex];
|
|
8
|
+
return obj;
|
|
9
|
+
},
|
|
10
|
+
{},
|
|
11
|
+
),
|
|
12
|
+
__status: undefined,
|
|
13
|
+
_index: index + 1,
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function keyToNumber(key: string): number {
|
|
18
|
+
// Try to parse as a number first
|
|
19
|
+
const parsed = Number(key);
|
|
20
|
+
|
|
21
|
+
// Check if it's a valid number (not NaN, not Infinity)
|
|
22
|
+
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
23
|
+
return parsed;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// If not a number, hash the string to a stable numeric value
|
|
27
|
+
return hashStringToNumber(key);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Hashes a string to a stable numeric value using a simple hash algorithm
|
|
32
|
+
* Based on the Java String.hashCode() implementation
|
|
33
|
+
*/
|
|
34
|
+
export function hashStringToNumber(str: string): number {
|
|
35
|
+
let hash = 0;
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < str.length; i++) {
|
|
38
|
+
const char = str.charCodeAt(i);
|
|
39
|
+
hash = (hash << 5) - hash + char;
|
|
40
|
+
hash = hash & hash; // Convert to 32-bit integer
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Return absolute value to ensure positive numbers
|
|
44
|
+
return Math.abs(hash);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getCaseInsensitive<T extends RowObjectType>(
|
|
48
|
+
obj: T,
|
|
49
|
+
key: string,
|
|
50
|
+
): T[keyof T] | undefined {
|
|
51
|
+
const lowerKey = key.toLowerCase();
|
|
52
|
+
|
|
53
|
+
// First try lowercase
|
|
54
|
+
if (lowerKey in obj) {
|
|
55
|
+
return obj[lowerKey as keyof T];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Fall back to case-insensitive search
|
|
59
|
+
const foundKey = Object.keys(obj).find((k) => k.toLowerCase() === lowerKey) as
|
|
60
|
+
| keyof T
|
|
61
|
+
| undefined;
|
|
62
|
+
|
|
63
|
+
return foundKey ? obj[foundKey] : undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Get the value of an object at a given path, case-insensitively
|
|
67
|
+
export function getValueAtPath<T = RowDataTypes>(
|
|
68
|
+
obj: Record<string, T | undefined>,
|
|
69
|
+
path: string,
|
|
70
|
+
): T | undefined {
|
|
71
|
+
let col = obj[path.toLowerCase()];
|
|
72
|
+
if (!col) {
|
|
73
|
+
// try upper-case match
|
|
74
|
+
col = obj[path.toUpperCase()];
|
|
75
|
+
}
|
|
76
|
+
if (!col) {
|
|
77
|
+
// try fallback with strict casing match
|
|
78
|
+
col = obj[path];
|
|
79
|
+
}
|
|
80
|
+
return col;
|
|
81
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"lib": ["DOM", "DOM.iterable", "ESNext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "react-jsx",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [
|
|
17
|
+
{
|
|
18
|
+
"name": "next"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"baseUrl": ".",
|
|
22
|
+
"paths": {
|
|
23
|
+
"@/*": ["./src/*"],
|
|
24
|
+
"@theme/*": ["./theme/*"]
|
|
25
|
+
},
|
|
26
|
+
"downlevelIteration": true
|
|
27
|
+
},
|
|
28
|
+
"types": [
|
|
29
|
+
"node",
|
|
30
|
+
"jest",
|
|
31
|
+
"react/next",
|
|
32
|
+
"react-dom/next",
|
|
33
|
+
"jest",
|
|
34
|
+
"@testing-library/jest-dom"
|
|
35
|
+
],
|
|
36
|
+
"include": [
|
|
37
|
+
"next-env.d.ts",
|
|
38
|
+
"jest.globals.d.ts",
|
|
39
|
+
"**/*.ts",
|
|
40
|
+
"**/*.tsx",
|
|
41
|
+
".next/types/**/*.ts",
|
|
42
|
+
"eslint.config.mjs",
|
|
43
|
+
".next/dev/types/**/*.ts",
|
|
44
|
+
"./jest.setup.ts"
|
|
45
|
+
],
|
|
46
|
+
"exclude": ["node_modules"]
|
|
47
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## Adapter Macros
|
|
2
|
+
|
|
3
|
+
Recce use dbt package `audit-hepler` and `dbt_profiler` for value diff and profile diff. However, it encounters some SQL compatibility issues in some warehouse. The folder is to provide adapter-specific macro by mean of the dbt [macro dispatch](https://docs.getdbt.com/reference/dbt-jinja-functions/dispatch) mechanism.
|
|
4
|
+
|
|
5
|
+
## How to use
|
|
6
|
+
|
|
7
|
+
1. Copy `recce_<adapter>.sql` to your dbt project `macros/` folder.
|
|
8
|
+
2. Rerun any `dbt` command (e.g. `dbt run`) to make macros available in the `target/manifest.json`
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{% macro athena__compare_column_values(a_query, b_query, primary_key, column_to_compare, emojis, a_relation_name, b_relation_name) -%}
|
|
2
|
+
with a_query as (
|
|
3
|
+
{{ a_query }}
|
|
4
|
+
),
|
|
5
|
+
|
|
6
|
+
b_query as (
|
|
7
|
+
{{ b_query }}
|
|
8
|
+
),
|
|
9
|
+
|
|
10
|
+
joined as (
|
|
11
|
+
select
|
|
12
|
+
coalesce(a_query.{{ primary_key }}, b_query.{{ primary_key }}) as {{ primary_key }},
|
|
13
|
+
a_query.{{ column_to_compare }} as a_query_value,
|
|
14
|
+
b_query.{{ column_to_compare }} as b_query_value,
|
|
15
|
+
case
|
|
16
|
+
when a_query.{{ column_to_compare }} = b_query.{{ column_to_compare }} then '{% if emojis %}✅: {% endif %}perfect match'
|
|
17
|
+
when a_query.{{ column_to_compare }} is null and b_query.{{ column_to_compare }} is null then '{% if emojis %}✅: {% endif %}both are null'
|
|
18
|
+
when a_query.{{ primary_key }} is null then '{% if emojis %}🤷: {% endif %}missing from {{ a_relation_name }}'
|
|
19
|
+
when b_query.{{ primary_key }} is null then '{% if emojis %}🤷: {% endif %}missing from {{ b_relation_name }}'
|
|
20
|
+
when a_query.{{ column_to_compare }} is null then '{% if emojis %}🤷: {% endif %}value is null in {{ a_relation_name }} only'
|
|
21
|
+
when b_query.{{ column_to_compare }} is null then '{% if emojis %}🤷: {% endif %}value is null in {{ b_relation_name }} only'
|
|
22
|
+
when a_query.{{ column_to_compare }} != b_query.{{ column_to_compare }} then '{% if emojis %}❌: {% endif %}values do not match'
|
|
23
|
+
else 'unknown' -- this should never happen
|
|
24
|
+
end as match_status,
|
|
25
|
+
case
|
|
26
|
+
when a_query.{{ column_to_compare }} = b_query.{{ column_to_compare }} then 0
|
|
27
|
+
when a_query.{{ column_to_compare }} is null and b_query.{{ column_to_compare }} is null then 1
|
|
28
|
+
when a_query.{{ primary_key }} is null then 2
|
|
29
|
+
when b_query.{{ primary_key }} is null then 3
|
|
30
|
+
when a_query.{{ column_to_compare }} is null then 4
|
|
31
|
+
when b_query.{{ column_to_compare }} is null then 5
|
|
32
|
+
when a_query.{{ column_to_compare }} != b_query.{{ column_to_compare }} then 6
|
|
33
|
+
else 7 -- this should never happen
|
|
34
|
+
end as match_order
|
|
35
|
+
|
|
36
|
+
from a_query
|
|
37
|
+
|
|
38
|
+
full outer join b_query on a_query.{{ primary_key }} = b_query.{{ primary_key }}
|
|
39
|
+
),
|
|
40
|
+
|
|
41
|
+
aggregated as (
|
|
42
|
+
select
|
|
43
|
+
'{{ column_to_compare }}' as column_name,
|
|
44
|
+
match_status,
|
|
45
|
+
match_order,
|
|
46
|
+
count(*) as count_records
|
|
47
|
+
from joined
|
|
48
|
+
|
|
49
|
+
group by '{{ column_to_compare }}', match_status, match_order
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
select
|
|
53
|
+
column_name,
|
|
54
|
+
match_status,
|
|
55
|
+
count_records,
|
|
56
|
+
round(100.0 * count_records / sum(count_records) over (), 2) as percent_of_total
|
|
57
|
+
|
|
58
|
+
from aggregated
|
|
59
|
+
|
|
60
|
+
order by match_order
|
|
61
|
+
|
|
62
|
+
{% endmacro %}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
{%- macro athena__measure_median(column_name, data_type, cte_name) -%}
|
|
66
|
+
|
|
67
|
+
{%- if dbt_profiler.is_numeric_dtype(data_type) and not dbt_profiler.is_struct_dtype(data_type) -%}
|
|
68
|
+
approx_percentile( {{ adapter.quote(column_name) }}, 0.5)
|
|
69
|
+
{%- else -%}
|
|
70
|
+
cast(null as {{ dbt.type_numeric() }})
|
|
71
|
+
{%- endif -%}
|
|
72
|
+
|
|
73
|
+
{%- endmacro -%}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "recce"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "Environment diff tool for dbt"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{name = "InfuseAI Dev Team", email = "dev@infuseai.io"}]
|
|
7
|
+
requires-python = ">=3.9"
|
|
8
|
+
license = {text = "Apache-2.0"}
|
|
9
|
+
|
|
10
|
+
dependencies = [
|
|
11
|
+
"boto3",
|
|
12
|
+
"requests>=2.28.1",
|
|
13
|
+
"ruamel.yaml>=0.18.6",
|
|
14
|
+
"click>=7.1",
|
|
15
|
+
"deepdiff>=7.0,<9.0",
|
|
16
|
+
"portalocker",
|
|
17
|
+
"fastapi",
|
|
18
|
+
"itsdangerous",
|
|
19
|
+
"uvicorn",
|
|
20
|
+
"pydantic",
|
|
21
|
+
"jinja2",
|
|
22
|
+
"rich>=12.0.0",
|
|
23
|
+
"sentry-sdk",
|
|
24
|
+
"watchdog",
|
|
25
|
+
"websockets",
|
|
26
|
+
"py-markdown-table",
|
|
27
|
+
"python-dateutil",
|
|
28
|
+
"python-multipart",
|
|
29
|
+
"GitPython",
|
|
30
|
+
"PyGithub",
|
|
31
|
+
"sqlglot>=27.29.0,<28.0",
|
|
32
|
+
"pytz",
|
|
33
|
+
"packaging",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
classifiers = [
|
|
37
|
+
"Programming Language :: Python :: 3.9",
|
|
38
|
+
"Programming Language :: Python :: 3.10",
|
|
39
|
+
"Programming Language :: Python :: 3.11",
|
|
40
|
+
"Programming Language :: Python :: 3.12",
|
|
41
|
+
"Programming Language :: Python :: 3.13",
|
|
42
|
+
"License :: OSI Approved :: Apache Software License",
|
|
43
|
+
"Operating System :: OS Independent",
|
|
44
|
+
"Development Status :: 4 - Beta",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.optional-dependencies]
|
|
48
|
+
mcp = ["mcp>=1.0.0; python_version >= '3.10'"]
|
|
49
|
+
dev = [
|
|
50
|
+
"pytest>=4.6",
|
|
51
|
+
"pytest-asyncio>=0.23,<1.0",
|
|
52
|
+
"pytest-flake8",
|
|
53
|
+
"black>=25.1.0",
|
|
54
|
+
"isort>=6.0.1",
|
|
55
|
+
"flake8>=7.2.0",
|
|
56
|
+
"pre-commit>=4.2.0",
|
|
57
|
+
"pytest-mypy",
|
|
58
|
+
"pytest-cov",
|
|
59
|
+
"twine",
|
|
60
|
+
"tox",
|
|
61
|
+
"tox-uv",
|
|
62
|
+
"pandas",
|
|
63
|
+
"httpx",
|
|
64
|
+
"dbt-duckdb",
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
[project.scripts]
|
|
68
|
+
recce = "recce.cli:cli"
|
|
69
|
+
|
|
70
|
+
[project.urls]
|
|
71
|
+
"Bug Tracker" = "https://github.com/InfuseAI/recce/issues"
|
|
72
|
+
"Homepage" = "https://github.com/InfuseAI/recce"
|
|
73
|
+
|
|
74
|
+
[build-system]
|
|
75
|
+
requires = ["hatchling"]
|
|
76
|
+
build-backend = "hatchling.build"
|
|
77
|
+
|
|
78
|
+
[tool.hatch.version]
|
|
79
|
+
path = "recce/VERSION"
|
|
80
|
+
pattern = "(?P<version>.+)"
|
|
81
|
+
|
|
82
|
+
[tool.hatch.build.targets.sdist]
|
|
83
|
+
include = [
|
|
84
|
+
"/recce",
|
|
85
|
+
]
|
|
86
|
+
artifacts = [
|
|
87
|
+
"/recce/data",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[tool.hatch.build.targets.wheel]
|
|
91
|
+
packages = ["recce"]
|
|
92
|
+
artifacts = [
|
|
93
|
+
"/recce/data",
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.uv.workspace]
|
|
97
|
+
members = ["recce_cloud"]
|
|
98
|
+
|
|
99
|
+
[tool.black]
|
|
100
|
+
line-length = 120
|
|
101
|
+
|
|
102
|
+
[tool.isort]
|
|
103
|
+
profile = "black"
|
|
104
|
+
|
|
105
|
+
[tool.pytest.ini_options]
|
|
106
|
+
markers = [
|
|
107
|
+
"asyncio: mark test as an async test (used by pytest-asyncio)",
|
|
108
|
+
]
|
|
109
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.31.0.dev0
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
from packaging.version import Version
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def is_ci_env():
|
|
8
|
+
# List of CI environment variables and their expected values
|
|
9
|
+
ci_environments = {
|
|
10
|
+
"CI": "true", # Generic CI indicator
|
|
11
|
+
"CIRCLECI": "true", # CircleCI
|
|
12
|
+
"GITHUB_ACTIONS": "true", # GitHub Actions
|
|
13
|
+
"GITLAB_CI": "true", # GitLab CI
|
|
14
|
+
"JENKINS_URL": None, # Jenkins (just needs to exist)
|
|
15
|
+
"TRAVIS": "true", # Travis CI
|
|
16
|
+
"APPVEYOR": "true", # AppVeyor
|
|
17
|
+
"DRONE": "true", # Drone CI
|
|
18
|
+
"TEAMCITY_VERSION": None, # TeamCity
|
|
19
|
+
"BITBUCKET_COMMIT": None, # Bitbucket Pipelines
|
|
20
|
+
"BUILDKITE": "true", # Buildkite
|
|
21
|
+
"CODEBUILD_BUILD_ID": None, # AWS CodeBuild
|
|
22
|
+
"AZURE_PIPELINES": "true", # Azure Pipelines
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for env_var, expected_value in ci_environments.items():
|
|
26
|
+
env_value = os.environ.get(env_var)
|
|
27
|
+
if env_value is not None:
|
|
28
|
+
# If we just need the variable to exist
|
|
29
|
+
if expected_value is None:
|
|
30
|
+
return True
|
|
31
|
+
# If we need to match a specific value (case-insensitive)
|
|
32
|
+
if env_value.lower() == expected_value.lower():
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def is_recce_cloud_instance():
|
|
39
|
+
"""Check if running in Recce Cloud instance."""
|
|
40
|
+
return os.environ.get("RECCE_CLOUD_INSTANCE", "false").lower() == "true"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_runner():
|
|
44
|
+
# GitHub Action
|
|
45
|
+
if os.environ.get("GITHUB_ACTIONS", "false") == "true":
|
|
46
|
+
return "github actions"
|
|
47
|
+
|
|
48
|
+
# GitHub Codespace
|
|
49
|
+
if os.environ.get("CODESPACES", "false") == "true":
|
|
50
|
+
return "github codespaces"
|
|
51
|
+
|
|
52
|
+
# CircleCI
|
|
53
|
+
if os.environ.get("CIRCLECI", "false") == "true":
|
|
54
|
+
return "circleci"
|
|
55
|
+
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_version():
|
|
60
|
+
version_file = os.path.normpath(os.path.join(os.path.dirname(__file__), "VERSION"))
|
|
61
|
+
with open(version_file) as fh:
|
|
62
|
+
version = fh.read().strip()
|
|
63
|
+
return version
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def fetch_latest_version():
|
|
67
|
+
current_version = get_version()
|
|
68
|
+
if "dev" in current_version:
|
|
69
|
+
# Skip fetching latest version if it's a dev version
|
|
70
|
+
return current_version
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
url = "https://pypi.org/pypi/recce/json"
|
|
74
|
+
response = requests.get(url, timeout=3)
|
|
75
|
+
response.raise_for_status()
|
|
76
|
+
data = response.json()
|
|
77
|
+
return data["info"]["version"]
|
|
78
|
+
except Exception:
|
|
79
|
+
return current_version
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
__version__ = get_version()
|
|
83
|
+
__latest_version__ = fetch_latest_version()
|
|
84
|
+
__is_recce_outdated__ = Version(__version__) < Version(__latest_version__)
|
|
File without changes
|