@malloy-publisher/sdk 0.0.41 → 0.0.43

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 (34) hide show
  1. package/dist/{RenderedResult-BX2zW03q.cjs → RenderedResult-qA34vdbd.cjs} +1 -1
  2. package/dist/{RenderedResult-gQPXZIVQ.js → RenderedResult-wM3HaFcq.js} +2 -2
  3. package/dist/components/MutableNotebook/MutableCell.d.ts +3 -1
  4. package/dist/components/Notebook/Notebook.d.ts +4 -3
  5. package/dist/hooks/useQueryWithApiError.d.ts +10 -0
  6. package/dist/{index-DCLrfHfE.js → index-ClVlSQMk.js} +27933 -27929
  7. package/dist/{index-xo1oaGoD.cjs → index-nsXS-gBw.cjs} +598 -598
  8. package/dist/index.cjs.js +1 -1
  9. package/dist/index.es.js +16 -15
  10. package/dist/{vendor-BCM56_2K.js → vendor-BKsYdkmG.js} +5456 -5458
  11. package/dist/{vendor-Bg9-K32d.cjs → vendor-hHfbZ4ZT.cjs} +30 -30
  12. package/openapitools.json +1 -1
  13. package/package.json +2 -2
  14. package/src/components/ApiErrorDisplay.tsx +12 -12
  15. package/src/components/Home/Home.tsx +9 -14
  16. package/src/components/Model/Model.tsx +18 -45
  17. package/src/components/Model/NamedQueries.tsx +38 -42
  18. package/src/components/Model/SourcesExplorer.tsx +47 -51
  19. package/src/components/MutableNotebook/ModelPicker.tsx +12 -18
  20. package/src/components/MutableNotebook/MutableCell.tsx +120 -62
  21. package/src/components/MutableNotebook/MutableNotebook.tsx +45 -27
  22. package/src/components/Notebook/Notebook.tsx +37 -60
  23. package/src/components/Package/Config.tsx +28 -34
  24. package/src/components/Package/Connections.tsx +12 -18
  25. package/src/components/Package/Databases.tsx +12 -18
  26. package/src/components/Package/Models.tsx +12 -20
  27. package/src/components/Package/Notebooks.tsx +13 -12
  28. package/src/components/Package/Schedules.tsx +12 -18
  29. package/src/components/Project/About.tsx +12 -18
  30. package/src/components/Project/ConnectionExplorer.tsx +49 -65
  31. package/src/components/Project/Packages.tsx +12 -18
  32. package/src/components/QueryResult/QueryResult.tsx +24 -30
  33. package/src/hooks/useQueryWithApiError.ts +114 -0
  34. package/src/index.ts +5 -0
@@ -12,16 +12,15 @@ import {
12
12
  TableRow,
13
13
  Typography,
14
14
  } from "@mui/material";
15
- import { QueryClient, useQuery } from "@tanstack/react-query";
16
15
  import React from "react";
17
16
  import { Configuration, Database, DatabasesApi } from "../../client";
18
17
  import { StyledCard, StyledCardContent } from "../styles";
19
18
  import { usePackage } from "./PackageProvider";
20
19
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
21
20
  import { Loading } from "../Loading";
21
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
22
22
 
23
23
  const databasesApi = new DatabasesApi(new Configuration());
24
- const queryClient = new QueryClient();
25
24
 
26
25
  export default function Databases() {
27
26
  const { server, projectName, packageName, versionId, accessToken } =
@@ -41,22 +40,17 @@ export default function Databases() {
41
40
  setSelectedDatabase(null);
42
41
  };
43
42
 
44
- const { data, isError, error, isSuccess } = useQuery(
45
- {
46
- queryKey: ["databases", server, projectName, packageName, versionId],
47
- queryFn: () =>
48
- databasesApi.listDatabases(projectName, packageName, versionId, {
49
- baseURL: server,
50
- withCredentials: !accessToken,
51
- headers: {
52
- Authorization: accessToken && `Bearer ${accessToken}`,
53
- },
54
- }),
55
- retry: false,
56
- throwOnError: false,
57
- },
58
- queryClient,
59
- );
43
+ const { data, isError, error, isSuccess } = useQueryWithApiError({
44
+ queryKey: ["databases", server, projectName, packageName, versionId],
45
+ queryFn: () =>
46
+ databasesApi.listDatabases(projectName, packageName, versionId, {
47
+ baseURL: server,
48
+ withCredentials: !accessToken,
49
+ headers: {
50
+ Authorization: accessToken && `Bearer ${accessToken}`,
51
+ },
52
+ }),
53
+ });
60
54
  const formatRowSize = (size: number) => {
61
55
  if (size >= 1024 * 1024 * 1024 * 1024) {
62
56
  return `${(size / (1024 * 1024 * 1024)).toFixed(2)} T`;
@@ -1,16 +1,13 @@
1
1
  import { Box, Divider, Typography } from "@mui/material";
2
- import { QueryClient, useQuery } from "@tanstack/react-query";
3
- import axios from "axios";
4
2
  import { Configuration, ModelsApi } from "../../client";
5
3
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
6
4
  import { Loading } from "../Loading";
7
5
  import { StyledCard, StyledCardContent } from "../styles";
8
6
  import { FileTreeView } from "./FileTreeView";
9
7
  import { usePackage } from "./PackageProvider";
8
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
10
9
 
11
- axios.defaults.baseURL = "http://localhost:4000";
12
10
  const modelsApi = new ModelsApi(new Configuration());
13
- const queryClient = new QueryClient();
14
11
 
15
12
  const DEFAULT_EXPANDED_FOLDERS = ["notebooks/", "models/"];
16
13
 
@@ -22,22 +19,17 @@ export default function Models({ navigate }: ModelsProps) {
22
19
  const { server, projectName, packageName, versionId, accessToken } =
23
20
  usePackage();
24
21
 
25
- const { data, isError, error, isSuccess } = useQuery(
26
- {
27
- queryKey: ["models", server, projectName, packageName, versionId],
28
- queryFn: () =>
29
- modelsApi.listModels(projectName, packageName, versionId, {
30
- baseURL: server,
31
- withCredentials: !accessToken,
32
- headers: {
33
- Authorization: accessToken && `Bearer ${accessToken}`,
34
- },
35
- }),
36
- throwOnError: false,
37
- retry: false,
38
- },
39
- queryClient,
40
- );
22
+ const { data, isError, error, isSuccess } = useQueryWithApiError({
23
+ queryKey: ["models", server, projectName, packageName, versionId],
24
+ queryFn: () =>
25
+ modelsApi.listModels(projectName, packageName, versionId, {
26
+ baseURL: server,
27
+ withCredentials: !accessToken,
28
+ headers: {
29
+ Authorization: accessToken && `Bearer ${accessToken}`,
30
+ },
31
+ }),
32
+ });
41
33
 
42
34
  return (
43
35
  <StyledCard variant="outlined" sx={{ padding: "10px", width: "100%" }}>
@@ -1,14 +1,13 @@
1
1
  import { Box, Divider, Typography } from "@mui/material";
2
- import { QueryClient, useQuery } from "@tanstack/react-query";
3
2
  import { Configuration, NotebooksApi } from "../../client";
4
3
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
5
4
  import { Loading } from "../Loading";
6
5
  import { StyledCard, StyledCardContent } from "../styles";
7
6
  import { FileTreeView } from "./FileTreeView";
8
7
  import { usePackage } from "./PackageProvider";
8
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
9
9
 
10
10
  const notebooksApi = new NotebooksApi(new Configuration());
11
- const queryClient = new QueryClient();
12
11
 
13
12
  const DEFAULT_EXPANDED_FOLDERS = ["notebooks/"];
14
13
 
@@ -20,22 +19,24 @@ export default function Notebooks({ navigate }: NotebooksProps) {
20
19
  const { server, projectName, packageName, versionId, accessToken } =
21
20
  usePackage();
22
21
 
23
- const { data, isError, error, isSuccess } = useQuery(
24
- {
25
- queryKey: ["notebooks", server, projectName, packageName, versionId],
26
- queryFn: () =>
27
- notebooksApi.listNotebooks(projectName, packageName, versionId, {
22
+ const { data, isError, error, isSuccess } = useQueryWithApiError({
23
+ queryKey: ["notebooks", server, projectName, packageName, versionId],
24
+ queryFn: async () => {
25
+ const response = await notebooksApi.listNotebooks(
26
+ projectName,
27
+ packageName,
28
+ versionId,
29
+ {
28
30
  baseURL: server,
29
31
  withCredentials: !accessToken,
30
32
  headers: {
31
33
  Authorization: accessToken && `Bearer ${accessToken}`,
32
34
  },
33
- }),
34
- throwOnError: false,
35
- retry: false,
35
+ },
36
+ );
37
+ return response;
36
38
  },
37
- queryClient,
38
- );
39
+ });
39
40
 
40
41
  return (
41
42
  <StyledCard variant="outlined" sx={{ padding: "10px", width: "100%" }}>
@@ -10,36 +10,30 @@ import {
10
10
  TableRow,
11
11
  Typography,
12
12
  } from "@mui/material";
13
- import { QueryClient, useQuery } from "@tanstack/react-query";
14
13
  import { Configuration, SchedulesApi } from "../../client";
15
14
  import { StyledCard, StyledCardContent } from "../styles";
16
15
  import { usePackage } from "./PackageProvider";
17
16
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
18
17
  import { Loading } from "../Loading";
18
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
19
19
 
20
20
  const schedulesApi = new SchedulesApi(new Configuration());
21
- const queryClient = new QueryClient();
22
21
 
23
22
  export default function Schedules() {
24
23
  const { server, projectName, packageName, versionId, accessToken } =
25
24
  usePackage();
26
25
 
27
- const { data, isError, isLoading, error } = useQuery(
28
- {
29
- queryKey: ["schedules", server, projectName, packageName, versionId],
30
- queryFn: () =>
31
- schedulesApi.listSchedules(projectName, packageName, versionId, {
32
- baseURL: server,
33
- withCredentials: !accessToken,
34
- headers: {
35
- Authorization: accessToken && `Bearer ${accessToken}`,
36
- },
37
- }),
38
- retry: false,
39
- throwOnError: false,
40
- },
41
- queryClient,
42
- );
26
+ const { data, isError, isLoading, error } = useQueryWithApiError({
27
+ queryKey: ["schedules", server, projectName, packageName, versionId],
28
+ queryFn: () =>
29
+ schedulesApi.listSchedules(projectName, packageName, versionId, {
30
+ baseURL: server,
31
+ withCredentials: !accessToken,
32
+ headers: {
33
+ Authorization: accessToken && `Bearer ${accessToken}`,
34
+ },
35
+ }),
36
+ });
43
37
 
44
38
  if (isLoading) {
45
39
  return <Loading text="Fetching Schedules..." />;
@@ -2,33 +2,27 @@ import { Divider, Typography } from "@mui/material";
2
2
  import { Configuration, ProjectsApi } from "../../client";
3
3
  import Markdown from "markdown-to-jsx";
4
4
  import { StyledCard, StyledCardContent, StyledCardMedia } from "../styles";
5
- import { QueryClient, useQuery } from "@tanstack/react-query";
6
5
  import { useProject } from "./Project";
7
6
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
8
7
  import { Loading } from "../Loading";
8
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
9
9
 
10
10
  const projectsApi = new ProjectsApi(new Configuration());
11
- const queryClient = new QueryClient();
12
11
 
13
12
  export default function About() {
14
13
  const { server, projectName, accessToken } = useProject();
15
14
 
16
- const { data, isSuccess, isError, error } = useQuery(
17
- {
18
- queryKey: ["about", server, projectName],
19
- queryFn: () =>
20
- projectsApi.getProject(projectName, false, {
21
- baseURL: server,
22
- withCredentials: true,
23
- headers: {
24
- Authorization: accessToken && `Bearer ${accessToken}`,
25
- },
26
- }),
27
- retry: false,
28
- throwOnError: false,
29
- },
30
- queryClient,
31
- );
15
+ const { data, isSuccess, isError, error } = useQueryWithApiError({
16
+ queryKey: ["about", server, projectName],
17
+ queryFn: () =>
18
+ projectsApi.getProject(projectName, false, {
19
+ baseURL: server,
20
+ withCredentials: true,
21
+ headers: {
22
+ Authorization: accessToken && `Bearer ${accessToken}`,
23
+ },
24
+ }),
25
+ });
32
26
 
33
27
  return (
34
28
  <>
@@ -21,15 +21,14 @@ import {
21
21
  TableHead,
22
22
  TableRow,
23
23
  } from "@mui/material";
24
- import { QueryClient, useQuery } from "@tanstack/react-query";
25
24
  import { ConnectionsApi } from "../../client/api";
26
25
  import { Configuration } from "../../client/configuration";
27
26
  import { useProject } from "./Project";
28
27
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
29
28
  import { Loading } from "../Loading";
29
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
30
30
 
31
31
  const connectionsApi = new ConnectionsApi(new Configuration());
32
- const queryClient = new QueryClient();
33
32
 
34
33
  interface ConnectionExplorerProps {
35
34
  connectionName: string;
@@ -47,22 +46,17 @@ export default function ConnectionExplorer({
47
46
  null,
48
47
  );
49
48
  const [showHiddenSchemas, setShowHiddenSchemas] = React.useState(false);
50
- const { data, isSuccess, isError, error, isLoading } = useQuery(
51
- {
52
- queryKey: ["tablePath", server, projectName, connectionName],
53
- queryFn: () =>
54
- connectionsApi.listSchemas(projectName, connectionName, {
55
- baseURL: server,
56
- withCredentials: !accessToken,
57
- headers: {
58
- Authorization: accessToken && `Bearer ${accessToken}`,
59
- },
60
- }),
61
- retry: false,
62
- throwOnError: false,
63
- },
64
- queryClient,
65
- );
49
+ const { data, isSuccess, isError, error, isLoading } = useQueryWithApiError({
50
+ queryKey: ["tablePath", server, projectName, connectionName],
51
+ queryFn: () =>
52
+ connectionsApi.listSchemas(projectName, connectionName, {
53
+ baseURL: server,
54
+ withCredentials: !accessToken,
55
+ headers: {
56
+ Authorization: accessToken && `Bearer ${accessToken}`,
57
+ },
58
+ }),
59
+ });
66
60
 
67
61
  return (
68
62
  <Grid container spacing={2}>
@@ -174,35 +168,30 @@ function TableViewer({
174
168
  }: TableViewerProps) {
175
169
  const { server, projectName, accessToken } = useProject();
176
170
 
177
- const { data, isSuccess, isError, error, isLoading } = useQuery(
178
- {
179
- queryKey: [
180
- "tablePathSchema",
181
- server,
171
+ const { data, isSuccess, isError, error, isLoading } = useQueryWithApiError({
172
+ queryKey: [
173
+ "tablePathSchema",
174
+ server,
175
+ projectName,
176
+ connectionName,
177
+ schemaName,
178
+ tableName,
179
+ ],
180
+ queryFn: () =>
181
+ connectionsApi.getTablesource(
182
182
  projectName,
183
183
  connectionName,
184
- schemaName,
185
184
  tableName,
186
- ],
187
- queryFn: () =>
188
- connectionsApi.getTablesource(
189
- projectName,
190
- connectionName,
191
- tableName,
192
- `${schemaName}.${tableName}`,
193
- {
194
- baseURL: server,
195
- withCredentials: !accessToken,
196
- headers: {
197
- Authorization: accessToken && `Bearer ${accessToken}`,
198
- },
185
+ `${schemaName}.${tableName}`,
186
+ {
187
+ baseURL: server,
188
+ withCredentials: !accessToken,
189
+ headers: {
190
+ Authorization: accessToken && `Bearer ${accessToken}`,
199
191
  },
200
- ),
201
- retry: false,
202
- throwOnError: false,
203
- },
204
- queryClient,
205
- );
192
+ },
193
+ ),
194
+ });
206
195
 
207
196
  if (isSuccess && data) {
208
197
  console.log(data);
@@ -289,28 +278,23 @@ function TablesInSchema({
289
278
  }: TablesInSchemaProps) {
290
279
  const { server, projectName, accessToken } = useProject();
291
280
 
292
- const { data, isSuccess, isError, error, isLoading } = useQuery(
293
- {
294
- queryKey: [
295
- "tablesInSchema",
296
- server,
297
- projectName,
298
- connectionName,
299
- schemaName,
300
- ],
301
- queryFn: () =>
302
- connectionsApi.listTables(projectName, connectionName, schemaName, {
303
- baseURL: server,
304
- withCredentials: !accessToken,
305
- headers: {
306
- Authorization: accessToken && `Bearer ${accessToken}`,
307
- },
308
- }),
309
- retry: false,
310
- throwOnError: false,
311
- },
312
- queryClient,
313
- );
281
+ const { data, isSuccess, isError, error, isLoading } = useQueryWithApiError({
282
+ queryKey: [
283
+ "tablesInSchema",
284
+ server,
285
+ projectName,
286
+ connectionName,
287
+ schemaName,
288
+ ],
289
+ queryFn: () =>
290
+ connectionsApi.listTables(projectName, connectionName, schemaName, {
291
+ baseURL: server,
292
+ withCredentials: !accessToken,
293
+ headers: {
294
+ Authorization: accessToken && `Bearer ${accessToken}`,
295
+ },
296
+ }),
297
+ });
314
298
 
315
299
  return (
316
300
  <>
@@ -1,13 +1,12 @@
1
1
  import { Box, Divider, Grid, Typography } from "@mui/material";
2
2
  import { Configuration, PackagesApi } from "../../client";
3
3
  import { StyledCard, StyledCardContent, StyledCardMedia } from "../styles";
4
- import { QueryClient, useQuery } from "@tanstack/react-query";
5
4
  import { useProject } from "./Project";
6
5
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
7
6
  import { Loading } from "../Loading";
7
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
8
8
 
9
9
  const packagesApi = new PackagesApi(new Configuration());
10
- const queryClient = new QueryClient();
11
10
 
12
11
  interface PackagesProps {
13
12
  navigate: (to: string, event?: React.MouseEvent) => void;
@@ -16,22 +15,17 @@ interface PackagesProps {
16
15
  export default function Packages({ navigate }: PackagesProps) {
17
16
  const { server, projectName, accessToken } = useProject();
18
17
 
19
- const { data, isSuccess, isError, error } = useQuery(
20
- {
21
- queryKey: ["packages", server, projectName],
22
- queryFn: () =>
23
- packagesApi.listPackages(projectName, {
24
- baseURL: server,
25
- withCredentials: !accessToken,
26
- headers: {
27
- Authorization: accessToken && `Bearer ${accessToken}`,
28
- },
29
- }),
30
- retry: false,
31
- throwOnError: false,
32
- },
33
- queryClient,
34
- );
18
+ const { data, isSuccess, isError, error } = useQueryWithApiError({
19
+ queryKey: ["packages", server, projectName],
20
+ queryFn: () =>
21
+ packagesApi.listPackages(projectName, {
22
+ baseURL: server,
23
+ withCredentials: !accessToken,
24
+ headers: {
25
+ Authorization: accessToken && `Bearer ${accessToken}`,
26
+ },
27
+ }),
28
+ });
35
29
 
36
30
  return (
37
31
  <>
@@ -1,14 +1,13 @@
1
1
  import { Suspense, lazy } from "react";
2
2
  import { Configuration, QueryresultsApi } from "../../client";
3
- import { QueryClient, useQuery } from "@tanstack/react-query";
4
3
  import { usePackage } from "../Package/PackageProvider";
5
4
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
6
5
  import { Loading } from "../Loading";
6
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
7
7
 
8
8
  const RenderedResult = lazy(() => import("../RenderedResult/RenderedResult"));
9
9
 
10
10
  const queryResultsApi = new QueryresultsApi(new Configuration());
11
- const queryClient = new QueryClient();
12
11
 
13
12
  interface QueryResultProps {
14
13
  modelPath: string;
@@ -26,41 +25,36 @@ export default function QueryResult({
26
25
  const { server, projectName, packageName, versionId, accessToken } =
27
26
  usePackage();
28
27
 
29
- const { data, isSuccess, isError, error } = useQuery(
30
- {
31
- queryKey: [
32
- "queryResult",
33
- server,
28
+ const { data, isSuccess, isError, error } = useQueryWithApiError({
29
+ queryKey: [
30
+ "queryResult",
31
+ server,
32
+ projectName,
33
+ packageName,
34
+ modelPath,
35
+ versionId,
36
+ query,
37
+ sourceName,
38
+ queryName,
39
+ ],
40
+ queryFn: () =>
41
+ queryResultsApi.executeQuery(
34
42
  projectName,
35
43
  packageName,
36
44
  modelPath,
37
- versionId,
38
45
  query,
39
46
  sourceName,
40
47
  queryName,
41
- ],
42
- queryFn: () =>
43
- queryResultsApi.executeQuery(
44
- projectName,
45
- packageName,
46
- modelPath,
47
- query,
48
- sourceName,
49
- queryName,
50
- versionId,
51
- {
52
- baseURL: server,
53
- withCredentials: !accessToken,
54
- headers: {
55
- Authorization: accessToken && `Bearer ${accessToken}`,
56
- },
48
+ versionId,
49
+ {
50
+ baseURL: server,
51
+ withCredentials: !accessToken,
52
+ headers: {
53
+ Authorization: accessToken && `Bearer ${accessToken}`,
57
54
  },
58
- ),
59
- retry: false,
60
- throwOnError: false,
61
- },
62
- queryClient,
63
- );
55
+ },
56
+ ),
57
+ });
64
58
 
65
59
  return (
66
60
  <>
@@ -0,0 +1,114 @@
1
+ import {
2
+ useQuery,
3
+ useMutation,
4
+ QueryClient,
5
+ UseQueryOptions,
6
+ UseQueryResult,
7
+ UseMutationOptions,
8
+ UseMutationResult,
9
+ } from "@tanstack/react-query";
10
+ import { ApiError } from "../components/ApiErrorDisplay";
11
+
12
+ // Global QueryClient instance
13
+ const globalQueryClient = new QueryClient({
14
+ defaultOptions: {
15
+ queries: {
16
+ retry: false,
17
+ throwOnError: false,
18
+ },
19
+ mutations: {
20
+ retry: false,
21
+ throwOnError: false,
22
+ },
23
+ },
24
+ });
25
+
26
+ export function useQueryWithApiError<TData = unknown, TError = ApiError>(
27
+ options: Omit<UseQueryOptions<TData, TError>, "throwOnError" | "retry"> & {
28
+ queryFn: () => Promise<TData>;
29
+ },
30
+ ): UseQueryResult<TData, TError> {
31
+ const enhancedOptions: UseQueryOptions<TData, TError> = {
32
+ ...options,
33
+ queryFn: async () => {
34
+ try {
35
+ return await options.queryFn();
36
+ } catch (err) {
37
+ // Standardized error handling for axios errors
38
+ if (err && typeof err === "object" && "response" in err) {
39
+ const axiosError = err as {
40
+ response?: {
41
+ status: number;
42
+ data: { code: number; message: string };
43
+ };
44
+ message: string;
45
+ };
46
+ if (axiosError.response?.data) {
47
+ const apiError: ApiError = new Error(
48
+ axiosError.response.data.message || axiosError.message,
49
+ );
50
+ apiError.status = axiosError.response.status;
51
+ apiError.data = axiosError.response.data;
52
+ throw apiError;
53
+ }
54
+ }
55
+ // For other errors, throw as is
56
+ throw err;
57
+ }
58
+ },
59
+ retry: false,
60
+ throwOnError: false,
61
+ };
62
+
63
+ return useQuery(enhancedOptions, globalQueryClient);
64
+ }
65
+
66
+ export function useMutationWithApiError<
67
+ TData = unknown,
68
+ TError = ApiError,
69
+ TVariables = void,
70
+ >(
71
+ options: Omit<
72
+ UseMutationOptions<TData, TError, TVariables>,
73
+ "throwOnError" | "retry"
74
+ > & {
75
+ mutationFn: (variables: TVariables) => Promise<TData>;
76
+ },
77
+ ): UseMutationResult<TData, TError, TVariables> {
78
+ const enhancedOptions: UseMutationOptions<TData, TError, TVariables> = {
79
+ ...options,
80
+ mutationFn: async (variables: TVariables) => {
81
+ try {
82
+ return await options.mutationFn(variables);
83
+ } catch (err) {
84
+ // Standardized error handling for axios errors
85
+ if (err && typeof err === "object" && "response" in err) {
86
+ const axiosError = err as {
87
+ response?: {
88
+ status: number;
89
+ data: { code: number; message: string };
90
+ };
91
+ message: string;
92
+ };
93
+ if (axiosError.response?.data) {
94
+ const apiError: ApiError = new Error(
95
+ axiosError.response.data.message || axiosError.message,
96
+ );
97
+ apiError.status = axiosError.response.status;
98
+ apiError.data = axiosError.response.data;
99
+ throw apiError;
100
+ }
101
+ }
102
+ // For other errors, throw as is
103
+ throw err;
104
+ }
105
+ },
106
+ retry: false,
107
+ throwOnError: false,
108
+ };
109
+
110
+ return useMutation(enhancedOptions, globalQueryClient);
111
+ }
112
+
113
+ // Export the global query client for direct access if needed
114
+ export { globalQueryClient };
package/src/index.ts CHANGED
@@ -1,2 +1,7 @@
1
1
  export * from "./components";
2
2
  export { default as ConnectionExplorer } from "./components/Project/ConnectionExplorer";
3
+ import axios from "axios";
4
+
5
+ // There's a bug in the OpenAPI generator that causes it to ignore baseURL in the
6
+ // axios request if defaults.baseURL is not set.
7
+ axios.defaults.baseURL = "IfYouAreSeeingThis_baseURL_IsNotSet";