@datarecce/ui 0.1.0
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/README.md +224 -0
- package/dist/api.js +496 -0
- package/dist/api.js.map +1 -0
- package/dist/api.mjs +437 -0
- package/dist/api.mjs.map +1 -0
- package/dist/components.js +15199 -0
- package/dist/components.js.map +1 -0
- package/dist/components.mjs +15103 -0
- package/dist/components.mjs.map +1 -0
- package/dist/hooks.js +199 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hooks.mjs +189 -0
- package/dist/hooks.mjs.map +1 -0
- package/dist/index.js +15496 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +15337 -0
- package/dist/index.mjs.map +1 -0
- package/dist/reload-image-PGVLW7NX.svg +4 -0
- package/dist/styles-LEL5RGUW.css +67 -0
- package/dist/styles-PJUYW64Y.css +19 -0
- package/dist/styles-VXS6KNFS.css +9 -0
- package/dist/types.js +24 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +19 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +138 -0
package/README.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# @datarecce/ui
|
|
2
|
+
|
|
3
|
+
React component library for building data validation and review interfaces. This library provides the UI components used in [Recce](https://github.com/DataRecce/recce), a data validation tool for dbt projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @datarecce/ui
|
|
9
|
+
# or
|
|
10
|
+
yarn add @datarecce/ui
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @datarecce/ui
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Peer Dependencies
|
|
16
|
+
|
|
17
|
+
This library requires the following peer dependencies:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"@chakra-ui/react": "^3.0.0",
|
|
22
|
+
"@emotion/react": "^11.0.0",
|
|
23
|
+
"@tanstack/react-query": "^5.0.0",
|
|
24
|
+
"@xyflow/react": "^12.0.0",
|
|
25
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
26
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
### Basic Setup
|
|
33
|
+
|
|
34
|
+
Wrap your application with the Recce UI Provider:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { Provider } from "@datarecce/ui";
|
|
38
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
39
|
+
|
|
40
|
+
const queryClient = new QueryClient();
|
|
41
|
+
|
|
42
|
+
function App() {
|
|
43
|
+
return (
|
|
44
|
+
<QueryClientProvider client={queryClient}>
|
|
45
|
+
<Provider>{/* Your app components */}</Provider>
|
|
46
|
+
</QueryClientProvider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Using Components
|
|
52
|
+
|
|
53
|
+
Import and use individual components:
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import {
|
|
57
|
+
LineageView,
|
|
58
|
+
QueryForm,
|
|
59
|
+
ProfileDiffForm,
|
|
60
|
+
SchemaView,
|
|
61
|
+
} from "@datarecce/ui";
|
|
62
|
+
|
|
63
|
+
function MyComponent() {
|
|
64
|
+
return (
|
|
65
|
+
<div>
|
|
66
|
+
<LineageView />
|
|
67
|
+
<QueryForm />
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Available Exports
|
|
74
|
+
|
|
75
|
+
The library provides multiple entry points for different features:
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
// Main components
|
|
79
|
+
import { LineageView, QueryForm } from "@datarecce/ui/components";
|
|
80
|
+
|
|
81
|
+
// API utilities
|
|
82
|
+
import { axiosClient, fetchChecks } from "@datarecce/ui/api";
|
|
83
|
+
|
|
84
|
+
// Custom hooks
|
|
85
|
+
import { useLineageViewContext, useCheckToast } from "@datarecce/ui/hooks";
|
|
86
|
+
|
|
87
|
+
// TypeScript types
|
|
88
|
+
import type { DataFrame, Check, Run } from "@datarecce/ui/types";
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Component Categories
|
|
92
|
+
|
|
93
|
+
### Lineage Components
|
|
94
|
+
|
|
95
|
+
- `LineageView` - Interactive lineage graph visualization
|
|
96
|
+
- `LineagePage` - Full lineage page with controls
|
|
97
|
+
- `GraphNode`, `GraphEdge` - Graph building blocks
|
|
98
|
+
- `NodeView` - Detailed node information display
|
|
99
|
+
|
|
100
|
+
### Query Components
|
|
101
|
+
|
|
102
|
+
- `QueryForm` - SQL query input form
|
|
103
|
+
- `QueryPage` - Complete query interface
|
|
104
|
+
- `SqlEditor` - Monaco-based SQL editor
|
|
105
|
+
- `QueryResultView` - Query results display
|
|
106
|
+
|
|
107
|
+
### Profile Components
|
|
108
|
+
|
|
109
|
+
- `ProfileDiffForm` - Data profiling comparison form
|
|
110
|
+
- `ProfileDiffResultView` - Profile diff results display
|
|
111
|
+
|
|
112
|
+
### Chart Components
|
|
113
|
+
|
|
114
|
+
- `HistogramChart` - Histogram visualization
|
|
115
|
+
- `TopKSummaryList` - Top-K value summary
|
|
116
|
+
- `HistogramDiffForm` - Histogram comparison interface
|
|
117
|
+
|
|
118
|
+
### Schema Components
|
|
119
|
+
|
|
120
|
+
- `SchemaView` - Schema structure display
|
|
121
|
+
- `SchemaDiffView` - Schema comparison view
|
|
122
|
+
- `ColumnNameCell` - Schema column renderer
|
|
123
|
+
|
|
124
|
+
### Check Components
|
|
125
|
+
|
|
126
|
+
- `CheckList` - List of validation checks
|
|
127
|
+
- `CheckDetail` - Detailed check view
|
|
128
|
+
- `LineageDiffView` - Lineage difference visualization
|
|
129
|
+
|
|
130
|
+
### Run Components
|
|
131
|
+
|
|
132
|
+
- `RunPage` - Run execution interface
|
|
133
|
+
- `RunList` - List of execution runs
|
|
134
|
+
- `RunView` - Individual run details
|
|
135
|
+
|
|
136
|
+
## API Client Configuration
|
|
137
|
+
|
|
138
|
+
The library includes API client utilities that need to be configured with your backend URL:
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import { axiosClient } from "@datarecce/ui/api";
|
|
142
|
+
|
|
143
|
+
// Configure the API client
|
|
144
|
+
axiosClient.defaults.baseURL = "http://localhost:8000";
|
|
145
|
+
axiosClient.defaults.headers.common["Authorization"] = "Bearer token";
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Development
|
|
149
|
+
|
|
150
|
+
### Building from Source
|
|
151
|
+
|
|
152
|
+
This package uses a git submodule to reference the main Recce repository:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Clone with submodules
|
|
156
|
+
git clone --recursive https://github.com/DataRecce/recce-ui.git
|
|
157
|
+
|
|
158
|
+
# Or if already cloned, initialize submodules
|
|
159
|
+
git submodule init
|
|
160
|
+
git submodule update
|
|
161
|
+
|
|
162
|
+
# Install dependencies
|
|
163
|
+
pnpm install
|
|
164
|
+
|
|
165
|
+
# The postinstall script will automatically apply TypeScript patches
|
|
166
|
+
# If you need to reapply patches manually:
|
|
167
|
+
npm run patch:apply
|
|
168
|
+
|
|
169
|
+
# Build the library
|
|
170
|
+
pnpm build
|
|
171
|
+
|
|
172
|
+
# Run in development mode
|
|
173
|
+
pnpm dev
|
|
174
|
+
|
|
175
|
+
# Type checking
|
|
176
|
+
pnpm type:check # Run with known issues handled
|
|
177
|
+
pnpm type:check:strict # Run strict type checking
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### TypeScript Patches
|
|
181
|
+
|
|
182
|
+
This package includes automatic patches to fix TypeScript strict mode issues in the source code. These patches are applied automatically during `npm install` and fix:
|
|
183
|
+
|
|
184
|
+
1. Type assertion issues in CheckDetail.tsx
|
|
185
|
+
2. Boolean type issues in CheckList.tsx
|
|
186
|
+
3. Type conversion issues in LineageViewContextMenu.tsx
|
|
187
|
+
4. Type inference issues in toaster.tsx
|
|
188
|
+
|
|
189
|
+
The patches are temporary fixes until the main Recce repository is updated.
|
|
190
|
+
|
|
191
|
+
### Updating the Submodule
|
|
192
|
+
|
|
193
|
+
To update the Recce source code:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
pnpm run submodule:update
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Running Storybook
|
|
200
|
+
|
|
201
|
+
View component documentation and examples:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
pnpm storybook
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## TypeScript Support
|
|
208
|
+
|
|
209
|
+
This library is written in TypeScript and provides full type definitions. All exports include proper TypeScript types for enhanced development experience.
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
Apache-2.0
|
|
214
|
+
|
|
215
|
+
## Contributing
|
|
216
|
+
|
|
217
|
+
Contributions are welcome! Please check the main [Recce repository](https://github.com/DataRecce/recce) for contribution guidelines.
|
|
218
|
+
|
|
219
|
+
## Links
|
|
220
|
+
|
|
221
|
+
- [Recce Documentation](https://datarecce.io/docs)
|
|
222
|
+
- [GitHub Repository](https://github.com/DataRecce/recce-ui)
|
|
223
|
+
- [Main Recce Project](https://github.com/DataRecce/recce)
|
|
224
|
+
- [Issue Tracker](https://github.com/DataRecce/recce/issues)
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var reactQuery = require('@tanstack/react-query');
|
|
4
|
+
var axios = require('axios');
|
|
5
|
+
require('@amplitude/unified');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
11
|
+
|
|
12
|
+
// recce-source/js/src/lib/const.ts
|
|
13
|
+
var apiUrl = process.env.NEXT_PUBLIC_API_URL;
|
|
14
|
+
apiUrl ??= typeof window !== "undefined" ? window.location.origin : "";
|
|
15
|
+
var PUBLIC_API_URL = apiUrl;
|
|
16
|
+
process.env.NEXT_PUBLIC_CLOUD_WEB_URL;
|
|
17
|
+
|
|
18
|
+
// recce-source/js/src/lib/api/axiosClient.ts
|
|
19
|
+
var axiosClient = axios__default.default.create({
|
|
20
|
+
baseURL: PUBLIC_API_URL
|
|
21
|
+
});
|
|
22
|
+
var reactQueryClient = new reactQuery.QueryClient();
|
|
23
|
+
|
|
24
|
+
// recce-source/js/src/lib/api/types.ts
|
|
25
|
+
function isQueryRun(run) {
|
|
26
|
+
return run.type === "query";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// recce-source/js/src/lib/api/runs.ts
|
|
30
|
+
function mutateAddKey(run) {
|
|
31
|
+
if (run.result == null) {
|
|
32
|
+
return run;
|
|
33
|
+
}
|
|
34
|
+
if (isQueryRun(run)) {
|
|
35
|
+
run.result.columns = run.result.columns.map((c) => {
|
|
36
|
+
if (c.key) {
|
|
37
|
+
return c;
|
|
38
|
+
}
|
|
39
|
+
c.key = c.name;
|
|
40
|
+
return c;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return run;
|
|
44
|
+
}
|
|
45
|
+
async function submitRun(type, params, options) {
|
|
46
|
+
const track_props = options?.trackProps ? { ...options.trackProps } : {};
|
|
47
|
+
const response = await axiosClient.post("/api/runs", {
|
|
48
|
+
type,
|
|
49
|
+
params,
|
|
50
|
+
nowait: options?.nowait,
|
|
51
|
+
track_props
|
|
52
|
+
});
|
|
53
|
+
return response.data;
|
|
54
|
+
}
|
|
55
|
+
async function getRun(runId) {
|
|
56
|
+
const response = await axiosClient.get(
|
|
57
|
+
`/api/runs/${runId}`
|
|
58
|
+
);
|
|
59
|
+
return response.data;
|
|
60
|
+
}
|
|
61
|
+
async function waitRun(runId, timeout) {
|
|
62
|
+
const response = await axiosClient.get(
|
|
63
|
+
`/api/runs/${runId}/wait`,
|
|
64
|
+
{
|
|
65
|
+
params: {
|
|
66
|
+
timeout
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
return mutateAddKey(response.data);
|
|
71
|
+
}
|
|
72
|
+
async function cancelRun(runId) {
|
|
73
|
+
return await axiosClient.post(
|
|
74
|
+
`/api/runs/${runId}/cancel`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
async function submitRunFromCheck(checkId, options) {
|
|
78
|
+
const response = await axiosClient.post(`/api/checks/${checkId}/run`, {
|
|
79
|
+
nowait: options?.nowait
|
|
80
|
+
});
|
|
81
|
+
return response.data;
|
|
82
|
+
}
|
|
83
|
+
async function searchRuns(type, params, limit) {
|
|
84
|
+
const response = await axiosClient.post(
|
|
85
|
+
`/api/runs/search`,
|
|
86
|
+
{
|
|
87
|
+
type,
|
|
88
|
+
params,
|
|
89
|
+
limit
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
return response.data;
|
|
93
|
+
}
|
|
94
|
+
async function listRuns() {
|
|
95
|
+
const response = await axiosClient.get(
|
|
96
|
+
"/api/runs"
|
|
97
|
+
);
|
|
98
|
+
return response.data;
|
|
99
|
+
}
|
|
100
|
+
async function aggregateRuns() {
|
|
101
|
+
const response = await axiosClient.post(`/api/runs/aggregate`, {});
|
|
102
|
+
return response.data;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// recce-source/js/src/lib/api/adhocQuery.ts
|
|
106
|
+
async function submitQuery(params, options) {
|
|
107
|
+
return await submitRun("query", params, options);
|
|
108
|
+
}
|
|
109
|
+
async function submitQueryBase(params, options) {
|
|
110
|
+
return await submitRun("query_base", params, options);
|
|
111
|
+
}
|
|
112
|
+
async function submitQueryDiff(params, options) {
|
|
113
|
+
return await submitRun("query_diff", params, options);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// recce-source/js/src/lib/api/cacheKeys.ts
|
|
117
|
+
var cacheKeys = {
|
|
118
|
+
rowCount: (model) => ["row_count", model],
|
|
119
|
+
lineage: () => ["lineage"],
|
|
120
|
+
checks: () => ["checks", "list"],
|
|
121
|
+
check: (checkId) => ["checks", checkId],
|
|
122
|
+
checkEvents: (checkId) => ["checks", checkId, "events"],
|
|
123
|
+
runs: () => ["runs"],
|
|
124
|
+
run: (runId) => ["runs", runId],
|
|
125
|
+
runsAggregated: () => ["runs_aggregated"],
|
|
126
|
+
flag: () => ["flag"],
|
|
127
|
+
instanceInfo: () => ["instance_info"],
|
|
128
|
+
user: () => ["user"]
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// recce-source/js/src/lib/api/checks.ts
|
|
132
|
+
async function createSimpleCheck() {
|
|
133
|
+
const response = await axiosClient.post("/api/checks", {
|
|
134
|
+
type: "simple"
|
|
135
|
+
});
|
|
136
|
+
return response.data;
|
|
137
|
+
}
|
|
138
|
+
async function createCheckByRun(runId, viewOptions) {
|
|
139
|
+
const track_props = {};
|
|
140
|
+
const response = await axiosClient.post("/api/checks", {
|
|
141
|
+
run_id: runId,
|
|
142
|
+
view_options: viewOptions,
|
|
143
|
+
track_props
|
|
144
|
+
});
|
|
145
|
+
return response.data;
|
|
146
|
+
}
|
|
147
|
+
async function listChecks() {
|
|
148
|
+
return (await axiosClient.get("/api/checks")).data;
|
|
149
|
+
}
|
|
150
|
+
function useChecks(enabled) {
|
|
151
|
+
return reactQuery.useQuery({
|
|
152
|
+
queryKey: cacheKeys.checks(),
|
|
153
|
+
queryFn: listChecks,
|
|
154
|
+
enabled
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
async function getCheck(checkId) {
|
|
158
|
+
const response = await axiosClient.get(`/api/checks/${checkId}`);
|
|
159
|
+
return response.data;
|
|
160
|
+
}
|
|
161
|
+
async function updateCheck(checkId, payload) {
|
|
162
|
+
const response = await axiosClient.patch(`/api/checks/${checkId}`, payload);
|
|
163
|
+
return response.data;
|
|
164
|
+
}
|
|
165
|
+
async function deleteCheck(checkId) {
|
|
166
|
+
const response = await axiosClient.delete(`/api/checks/${checkId}`);
|
|
167
|
+
return response.data;
|
|
168
|
+
}
|
|
169
|
+
async function reorderChecks(order) {
|
|
170
|
+
return await axiosClient.post("/api/checks/reorder", order);
|
|
171
|
+
}
|
|
172
|
+
async function markAsPresetCheck(checkId) {
|
|
173
|
+
await axiosClient.post(`/api/checks/${checkId}/mark-as-preset`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// recce-source/js/src/lib/api/cll.ts
|
|
177
|
+
async function getCll(input) {
|
|
178
|
+
const response = await axiosClient.post("/api/cll", input);
|
|
179
|
+
return response.data;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// recce-source/js/src/lib/api/connectToCloud.ts
|
|
183
|
+
async function connectToCloud() {
|
|
184
|
+
const data = await axiosClient.post("/api/connect");
|
|
185
|
+
return data.data;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// recce-source/js/src/lib/api/flag.ts
|
|
189
|
+
async function getServerFlag() {
|
|
190
|
+
return (await axiosClient.get("/api/flag")).data;
|
|
191
|
+
}
|
|
192
|
+
async function markOnboardingCompleted() {
|
|
193
|
+
try {
|
|
194
|
+
await axiosClient.post(
|
|
195
|
+
"/api/onboarding/completed"
|
|
196
|
+
);
|
|
197
|
+
} catch (_error) {
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function markRelaunchHintCompleted() {
|
|
201
|
+
try {
|
|
202
|
+
await axiosClient.post(
|
|
203
|
+
"/api/relaunch-hint/completed"
|
|
204
|
+
);
|
|
205
|
+
} catch (_error) {
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async function getLineage(base = false) {
|
|
209
|
+
const response = await axiosClient.get(
|
|
210
|
+
`/api/lineage?base=${base}`
|
|
211
|
+
);
|
|
212
|
+
return response.data;
|
|
213
|
+
}
|
|
214
|
+
async function getLineageWithError(base = false) {
|
|
215
|
+
try {
|
|
216
|
+
const data = await getLineage(base);
|
|
217
|
+
return { data };
|
|
218
|
+
} catch (err) {
|
|
219
|
+
if (err instanceof axios.AxiosError) {
|
|
220
|
+
const data = err.response?.data;
|
|
221
|
+
const detail = data?.detail;
|
|
222
|
+
if (detail) {
|
|
223
|
+
return { error: detail };
|
|
224
|
+
} else {
|
|
225
|
+
return { error: err.message };
|
|
226
|
+
}
|
|
227
|
+
} else if (err instanceof Error) {
|
|
228
|
+
return { error: err.message };
|
|
229
|
+
} else {
|
|
230
|
+
return { error: "An unknown error occurred" };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async function getLineageDiff() {
|
|
235
|
+
const [base, current] = await Promise.all([
|
|
236
|
+
getLineageWithError(true),
|
|
237
|
+
getLineageWithError(false)
|
|
238
|
+
]);
|
|
239
|
+
return {
|
|
240
|
+
base: base.data,
|
|
241
|
+
current: current.data,
|
|
242
|
+
base_error: base.error,
|
|
243
|
+
current_error: current.error
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
async function getServerInfo() {
|
|
247
|
+
return (await axiosClient.get(`/api/info`)).data;
|
|
248
|
+
}
|
|
249
|
+
async function getModelInfo(model) {
|
|
250
|
+
return (await axiosClient.get(
|
|
251
|
+
`/api/model/${model}`
|
|
252
|
+
)).data;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// recce-source/js/src/lib/api/lineagecheck.ts
|
|
256
|
+
async function createLineageDiffCheck(viewOptions) {
|
|
257
|
+
const response = await axiosClient.post("/api/checks", {
|
|
258
|
+
type: "lineage_diff",
|
|
259
|
+
params: {},
|
|
260
|
+
view_options: viewOptions
|
|
261
|
+
});
|
|
262
|
+
return response.data;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// recce-source/js/src/lib/api/rowcount.ts
|
|
266
|
+
async function submitRowCountDiff(params, options) {
|
|
267
|
+
return await submitRun("row_count_diff", params, options);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// recce-source/js/src/lib/api/models.ts
|
|
271
|
+
async function fetchModelRowCount(modelName) {
|
|
272
|
+
const response = await axiosClient.get(
|
|
273
|
+
`/api/models/${modelName}/row_count`
|
|
274
|
+
);
|
|
275
|
+
return response.data;
|
|
276
|
+
}
|
|
277
|
+
async function queryModelRowCount(modelName) {
|
|
278
|
+
const { result } = await queryRowCount([modelName]);
|
|
279
|
+
return result[modelName];
|
|
280
|
+
}
|
|
281
|
+
async function queryRowCount(modelNames) {
|
|
282
|
+
if (modelNames.length === 0) {
|
|
283
|
+
throw new Error("No model names provided");
|
|
284
|
+
}
|
|
285
|
+
const { run_id } = await submitRowCountDiff(
|
|
286
|
+
{ node_names: modelNames },
|
|
287
|
+
{ nowait: true }
|
|
288
|
+
);
|
|
289
|
+
const run = await waitRun(run_id);
|
|
290
|
+
return {
|
|
291
|
+
runId: run_id,
|
|
292
|
+
result: run.result
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// recce-source/js/src/lib/api/profile.ts
|
|
297
|
+
async function submitProfileDiff(params, options) {
|
|
298
|
+
return await submitRun("profile_diff", params, options);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// recce-source/js/src/lib/api/schemacheck.ts
|
|
302
|
+
async function createSchemaDiffCheck(params) {
|
|
303
|
+
const response = await axiosClient.post("/api/checks", {
|
|
304
|
+
type: "schema_diff",
|
|
305
|
+
params
|
|
306
|
+
});
|
|
307
|
+
return response.data;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// recce-source/js/src/lib/api/select.ts
|
|
311
|
+
async function select(input) {
|
|
312
|
+
return (await axiosClient.post(
|
|
313
|
+
`/api/select`,
|
|
314
|
+
input
|
|
315
|
+
)).data;
|
|
316
|
+
}
|
|
317
|
+
async function saveAs(input) {
|
|
318
|
+
return (await axiosClient.post(
|
|
319
|
+
"/api/save-as",
|
|
320
|
+
input
|
|
321
|
+
)).data;
|
|
322
|
+
}
|
|
323
|
+
async function rename(input) {
|
|
324
|
+
return (await axiosClient.post(
|
|
325
|
+
"/api/rename",
|
|
326
|
+
input
|
|
327
|
+
)).data;
|
|
328
|
+
}
|
|
329
|
+
async function exportState() {
|
|
330
|
+
return (await axiosClient.post("/api/export")).data;
|
|
331
|
+
}
|
|
332
|
+
async function importState(file, checksOnly) {
|
|
333
|
+
const formData = new FormData();
|
|
334
|
+
formData.append("file", file);
|
|
335
|
+
formData.append("checks_only", (!!checksOnly).toString());
|
|
336
|
+
return (await axiosClient.post(
|
|
337
|
+
"/api/import",
|
|
338
|
+
formData
|
|
339
|
+
)).data;
|
|
340
|
+
}
|
|
341
|
+
async function isStateSyncing() {
|
|
342
|
+
const response = await axiosClient.get(
|
|
343
|
+
"/api/sync"
|
|
344
|
+
);
|
|
345
|
+
return response.status === 208;
|
|
346
|
+
}
|
|
347
|
+
async function syncState(input) {
|
|
348
|
+
try {
|
|
349
|
+
const response = await axiosClient.post("/api/sync", input);
|
|
350
|
+
if (response.status === 202) {
|
|
351
|
+
return {
|
|
352
|
+
status: "accepted"
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
if (response.status === 208) {
|
|
356
|
+
return {
|
|
357
|
+
status: "syncing"
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
} catch (error) {
|
|
361
|
+
if (axios.isAxiosError(error)) {
|
|
362
|
+
if (error.response?.status === 409) {
|
|
363
|
+
return { status: "conflict" };
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
throw new Error("Failed to sync state");
|
|
368
|
+
}
|
|
369
|
+
async function shareState() {
|
|
370
|
+
return (await axiosClient.post(
|
|
371
|
+
"/api/share"
|
|
372
|
+
)).data;
|
|
373
|
+
}
|
|
374
|
+
async function fetchUser() {
|
|
375
|
+
try {
|
|
376
|
+
const response = await axiosClient.get(
|
|
377
|
+
"/api/users"
|
|
378
|
+
);
|
|
379
|
+
return response.data;
|
|
380
|
+
} catch (error) {
|
|
381
|
+
console.error("Error fetching user data:", error);
|
|
382
|
+
throw error;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
async function fetchGitHubAvatar(userId) {
|
|
386
|
+
try {
|
|
387
|
+
const response = await axios__default.default.get(
|
|
388
|
+
`https://api.github.com/user/${userId}`
|
|
389
|
+
);
|
|
390
|
+
return response.data.avatar_url;
|
|
391
|
+
} catch (error) {
|
|
392
|
+
console.warn("Failed to fetch GitHub avatar:", error);
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// recce-source/js/src/lib/api/valuediff.ts
|
|
398
|
+
async function submitValueDiff(params, options) {
|
|
399
|
+
return await submitRun("value_diff", params, options);
|
|
400
|
+
}
|
|
401
|
+
async function submitValueDiffDetail(params, options) {
|
|
402
|
+
return await submitRun("value_diff_detail", params, options);
|
|
403
|
+
}
|
|
404
|
+
function useVersionNumber() {
|
|
405
|
+
const [version, setVersion] = react.useState("");
|
|
406
|
+
const [latestVersion, setLatestVersion] = react.useState("");
|
|
407
|
+
react.useEffect(() => {
|
|
408
|
+
async function fetchVersion() {
|
|
409
|
+
try {
|
|
410
|
+
const { version: version2, latestVersion: latestVersion2 } = (await axiosClient.get(
|
|
411
|
+
"/api/version"
|
|
412
|
+
)).data;
|
|
413
|
+
setVersion(version2);
|
|
414
|
+
setLatestVersion(latestVersion2);
|
|
415
|
+
} catch (error) {
|
|
416
|
+
console.error("Error fetching version number:", error);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
void fetchVersion();
|
|
420
|
+
}, []);
|
|
421
|
+
return { version, latestVersion };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// recce-source/js/src/lib/api/localStorageKeys.ts
|
|
425
|
+
var prefix = "recce-";
|
|
426
|
+
var localStorageKeys = {
|
|
427
|
+
bypassSaveOverwrite: `${prefix}-bypass-save-overwrite`,
|
|
428
|
+
previewChangeFeedbackID: `${prefix}-preview-change-feedback`,
|
|
429
|
+
prepareEnvGuideID: `${prefix}-prepare-env`
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
// recce-source/js/src/lib/api/sessionStorageKeys.ts
|
|
433
|
+
var prefix2 = "recce";
|
|
434
|
+
var sessionStorageKeys = {
|
|
435
|
+
recommendationIgnored: `${prefix2}-recommendation-ignored`,
|
|
436
|
+
recommendationShowed: `${prefix2}-recommendation-showed`,
|
|
437
|
+
prevRefreshTimeStamp: `${prefix2}-prev-refresh-timestamp`,
|
|
438
|
+
lineageNotificationDismissed: `${prefix2}-lineage-notification-dismissed`
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
exports.aggregateRuns = aggregateRuns;
|
|
442
|
+
exports.axiosClient = axiosClient;
|
|
443
|
+
exports.cancelRun = cancelRun;
|
|
444
|
+
exports.connectToCloud = connectToCloud;
|
|
445
|
+
exports.createCheckByRun = createCheckByRun;
|
|
446
|
+
exports.createLineageDiffCheck = createLineageDiffCheck;
|
|
447
|
+
exports.createSchemaDiffCheck = createSchemaDiffCheck;
|
|
448
|
+
exports.createSimpleCheck = createSimpleCheck;
|
|
449
|
+
exports.deleteCheck = deleteCheck;
|
|
450
|
+
exports.exportState = exportState;
|
|
451
|
+
exports.fetchGitHubAvatar = fetchGitHubAvatar;
|
|
452
|
+
exports.fetchModelRowCount = fetchModelRowCount;
|
|
453
|
+
exports.fetchUser = fetchUser;
|
|
454
|
+
exports.getCheck = getCheck;
|
|
455
|
+
exports.getCll = getCll;
|
|
456
|
+
exports.getLineage = getLineage;
|
|
457
|
+
exports.getLineageDiff = getLineageDiff;
|
|
458
|
+
exports.getLineageWithError = getLineageWithError;
|
|
459
|
+
exports.getModelInfo = getModelInfo;
|
|
460
|
+
exports.getRun = getRun;
|
|
461
|
+
exports.getServerFlag = getServerFlag;
|
|
462
|
+
exports.getServerInfo = getServerInfo;
|
|
463
|
+
exports.importState = importState;
|
|
464
|
+
exports.isStateSyncing = isStateSyncing;
|
|
465
|
+
exports.listChecks = listChecks;
|
|
466
|
+
exports.listRuns = listRuns;
|
|
467
|
+
exports.localStorageKeys = localStorageKeys;
|
|
468
|
+
exports.markAsPresetCheck = markAsPresetCheck;
|
|
469
|
+
exports.markOnboardingCompleted = markOnboardingCompleted;
|
|
470
|
+
exports.markRelaunchHintCompleted = markRelaunchHintCompleted;
|
|
471
|
+
exports.queryModelRowCount = queryModelRowCount;
|
|
472
|
+
exports.queryRowCount = queryRowCount;
|
|
473
|
+
exports.reactQueryClient = reactQueryClient;
|
|
474
|
+
exports.rename = rename;
|
|
475
|
+
exports.reorderChecks = reorderChecks;
|
|
476
|
+
exports.saveAs = saveAs;
|
|
477
|
+
exports.searchRuns = searchRuns;
|
|
478
|
+
exports.select = select;
|
|
479
|
+
exports.sessionStorageKeys = sessionStorageKeys;
|
|
480
|
+
exports.shareState = shareState;
|
|
481
|
+
exports.submitProfileDiff = submitProfileDiff;
|
|
482
|
+
exports.submitQuery = submitQuery;
|
|
483
|
+
exports.submitQueryBase = submitQueryBase;
|
|
484
|
+
exports.submitQueryDiff = submitQueryDiff;
|
|
485
|
+
exports.submitRowCountDiff = submitRowCountDiff;
|
|
486
|
+
exports.submitRun = submitRun;
|
|
487
|
+
exports.submitRunFromCheck = submitRunFromCheck;
|
|
488
|
+
exports.submitValueDiff = submitValueDiff;
|
|
489
|
+
exports.submitValueDiffDetail = submitValueDiffDetail;
|
|
490
|
+
exports.syncState = syncState;
|
|
491
|
+
exports.updateCheck = updateCheck;
|
|
492
|
+
exports.useChecks = useChecks;
|
|
493
|
+
exports.useVersionNumber = useVersionNumber;
|
|
494
|
+
exports.waitRun = waitRun;
|
|
495
|
+
//# sourceMappingURL=api.js.map
|
|
496
|
+
//# sourceMappingURL=api.js.map
|