@malloy-publisher/sdk 0.0.118 → 0.0.120

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 (32) hide show
  1. package/dist/ServerProvider-49yj-aFb.cjs.js +1 -0
  2. package/dist/{ServerProvider-v0TajMUn.es.js → ServerProvider-BDgL8SVP.es.js} +355 -429
  3. package/dist/client/api.d.ts +285 -276
  4. package/dist/client/configuration.d.ts +1 -1
  5. package/dist/client/index.cjs.js +1 -1
  6. package/dist/client/index.d.ts +1 -1
  7. package/dist/client/index.es.js +43 -46
  8. package/dist/components/ServerProvider.d.ts +1 -3
  9. package/dist/index.cjs.js +111 -111
  10. package/dist/index.es.js +33143 -30265
  11. package/package.json +1 -1
  12. package/src/components/Connections/common.ts +2 -0
  13. package/src/components/Home/DeleteProjectDialog.tsx +10 -0
  14. package/src/components/Home/Home.tsx +1 -1
  15. package/src/components/Model/Model.tsx +19 -13
  16. package/src/components/Model/ModelCell.tsx +10 -8
  17. package/src/components/Model/ModelExplorer.tsx +91 -56
  18. package/src/components/Model/SourcesExplorer.tsx +7 -6
  19. package/src/components/Notebook/NotebookCell.tsx +4 -4
  20. package/src/components/Package/FileTreeView.tsx +3 -3
  21. package/src/components/Package/Package.tsx +7 -11
  22. package/src/components/Project/About.tsx +63 -8
  23. package/src/components/Project/ConnectionExplorer.tsx +123 -160
  24. package/src/components/Project/DeletePackageDialog.tsx +10 -0
  25. package/src/components/QueryResult/QueryResult.tsx +9 -7
  26. package/src/components/ServerProvider.tsx +0 -4
  27. package/src/hooks/useRawQueryData.ts +8 -6
  28. package/src/utils/formatting.ts +2 -1
  29. package/src/utils/parsing.ts +1 -1
  30. package/dist/ServerProvider-Bx3fsDOb.cjs.js +0 -1
  31. package/dist/components/Package/Schedules.d.ts +0 -5
  32. package/src/components/Package/Schedules.tsx +0 -114
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@malloy-publisher/sdk",
3
3
  "description": "Malloy Publisher SDK",
4
- "version": "0.0.118",
4
+ "version": "0.0.120",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.es.js",
@@ -188,6 +188,7 @@ export const connectionFieldsByType: Record<
188
188
  type: "text",
189
189
  },
190
190
  ],
191
+ duckdb: [],
191
192
  };
192
193
 
193
194
  export const attributesFieldName: Record<ConnectionTypeEnum, string> = {
@@ -196,4 +197,5 @@ export const attributesFieldName: Record<ConnectionTypeEnum, string> = {
196
197
  snowflake: "snowflakeConnection",
197
198
  trino: "trinoConnection",
198
199
  mysql: "mysqlConnection",
200
+ duckdb: "duckdbConnection",
199
201
  };
@@ -84,6 +84,16 @@ export default function DeleteProjectDialog({
84
84
  </Typography>
85
85
  </DialogContent>
86
86
  <DialogActions>
87
+ <Button
88
+ variant="outlined"
89
+ onClick={handleClose}
90
+ style={{
91
+ borderColor: "#14b3cb",
92
+ color: "#14b3cb",
93
+ }}
94
+ >
95
+ Cancel
96
+ </Button>
87
97
  <Button
88
98
  loading={deleteProject.isPending}
89
99
  variant="contained"
@@ -441,7 +441,7 @@ function ProjectCard({
441
441
  <Typography
442
442
  variant="body2"
443
443
  color="text.secondary"
444
- sx={{ mb: 2 }}
444
+ sx={{ mb: 2, minHeight: "60px" }}
445
445
  >
446
446
  {getProjectDescription(project.readme)}
447
447
  </Typography>
@@ -1,4 +1,6 @@
1
- import { ApiErrorDisplay } from "../ApiErrorDisplay";
1
+ import "@malloydata/malloy-explorer/styles.css";
2
+ import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
3
+ import ZoomOutMapIcon from "@mui/icons-material/ZoomOutMap";
2
4
  import {
3
5
  Box,
4
6
  IconButton,
@@ -7,17 +9,15 @@ import {
7
9
  Tooltip,
8
10
  Typography,
9
11
  } from "@mui/material";
10
- import SearchIcon from "@mui/icons-material/Search";
11
- import ShareIcon from "@mui/icons-material/Share";
12
- import "@malloydata/malloy-explorer/styles.css";
13
- import { QueryExplorerResult } from "./SourcesExplorer";
12
+ import React, { useState } from "react";
13
+ import { parseResourceUri } from "../../utils/formatting";
14
+ import { ApiErrorDisplay } from "../ApiErrorDisplay";
14
15
  import { Loading } from "../Loading";
16
+ import { ModelCell } from "./ModelCell";
15
17
  import { ModelExplorer } from "./ModelExplorer";
16
18
  import { ModelExplorerDialog } from "./ModelExplorerDialog";
17
- import { ModelCell } from "./ModelCell";
19
+ import { QueryExplorerResult } from "./SourcesExplorer";
18
20
  import { useModelData } from "./useModelData";
19
- import React, { useState } from "react";
20
- import { parseResourceUri } from "../../utils/formatting";
21
21
 
22
22
  interface ModelProps {
23
23
  onChange?: (query: QueryExplorerResult) => void;
@@ -103,8 +103,8 @@ export default function Model({ onChange, resourceUri }: ModelProps) {
103
103
  >
104
104
  Sources
105
105
  </Typography>
106
- <Tooltip title="Click to copy and share">
107
- <ShareIcon
106
+ <Tooltip title="Click to copy link">
107
+ <LinkOutlinedIcon
108
108
  sx={{
109
109
  fontSize: "24px",
110
110
  color: "#666666",
@@ -140,9 +140,15 @@ export default function Model({ onChange, resourceUri }: ModelProps) {
140
140
  }}
141
141
  onClick={() => setDialogOpen(true)}
142
142
  >
143
- <SearchIcon
144
- sx={{ fontSize: "18px", color: "#666666" }}
145
- />
143
+ <Tooltip title="Expanded view">
144
+ <ZoomOutMapIcon
145
+ sx={{
146
+ fontSize: "18px",
147
+ color: "#666666",
148
+ marginBottom: "5px",
149
+ }}
150
+ />
151
+ </Tooltip>
146
152
  </IconButton>
147
153
  </Stack>
148
154
  )}
@@ -1,13 +1,13 @@
1
- import { Box, Typography, IconButton } from "@mui/material";
2
1
  import SearchIcon from "@mui/icons-material/Search";
2
+ import { Box, IconButton, Typography } from "@mui/material";
3
3
  import React, { useEffect } from "react";
4
4
  import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
5
+ import { parseResourceUri } from "../../utils/formatting";
5
6
  import { highlight } from "../highlighter";
6
7
  import ResultContainer from "../RenderedResult/ResultContainer";
7
8
  import ResultsDialog from "../ResultsDialog";
8
- import { CleanMetricCard, CleanNotebookCell } from "../styles";
9
- import { parseResourceUri } from "../../utils/formatting";
10
9
  import { useServer } from "../ServerProvider";
10
+ import { CleanMetricCard, CleanNotebookCell } from "../styles";
11
11
 
12
12
  interface ModelCellProps {
13
13
  sourceName?: string;
@@ -37,14 +37,16 @@ export function ModelCell({
37
37
  } = useQueryWithApiError({
38
38
  queryKey: ["namedQueryResult", resourceUri, queryName],
39
39
  queryFn: () =>
40
- apiClients.queryResults.executeQuery(
40
+ apiClients.models.executeQueryModel(
41
41
  projectName,
42
42
  packageName,
43
43
  modelPath,
44
- undefined, // query
45
- undefined, // sourceName
46
- queryName, // queryName
47
- versionId, // versionId
44
+ {
45
+ query: undefined,
46
+ sourceName: undefined,
47
+ queryName: queryName,
48
+ versionId: versionId,
49
+ },
48
50
  ),
49
51
  enabled: true, // Always execute
50
52
  });
@@ -1,5 +1,6 @@
1
- import { Box, Button, Stack } from "@mui/material";
2
- import { styled } from "@mui/material/styles";
1
+ import { Box, Stack } from "@mui/material";
2
+ import Autocomplete from "@mui/material/Autocomplete";
3
+ import TextField from "@mui/material/TextField";
3
4
  import React from "react";
4
5
  import { CompiledModel } from "../../client";
5
6
  import { parseResourceUri } from "../../utils/formatting";
@@ -10,33 +11,33 @@ import { QueryExplorerResult, SourcesExplorer } from "./SourcesExplorer";
10
11
  import { useModelData } from "./useModelData";
11
12
 
12
13
  // Add a styled component for the multi-row tab bar
13
- const MultiRowTabBar = styled(Box)(({ theme }) => ({
14
- display: "flex",
15
- flexWrap: "wrap",
16
- gap: theme.spacing(1),
17
- borderBottom: "1px solid #f0f0f0",
18
- minHeight: 48,
19
- paddingBottom: "8px",
20
- }));
14
+ // const MultiRowTabBar = styled(Box)(({ theme }) => ({
15
+ // display: "flex",
16
+ // flexWrap: "wrap",
17
+ // gap: theme.spacing(1),
18
+ // borderBottom: "1px solid #f0f0f0",
19
+ // minHeight: 48,
20
+ // paddingBottom: "8px",
21
+ // }));
21
22
 
22
- const MultiRowTab = styled(Button)<{ selected?: boolean }>(
23
- ({ theme, selected }) => ({
24
- minHeight: 32,
25
- padding: theme.spacing(0.75, 2),
26
- borderRadius: "6px",
27
- background: selected ? "#f8f9fa" : "transparent",
28
- color: selected ? "#495057" : "#666666",
29
- fontWeight: selected ? 600 : 500,
30
- border: selected ? "1px solid #e9ecef" : "1px solid transparent",
31
- boxShadow: "none",
32
- textTransform: "none",
33
- fontSize: "15px",
34
- "&:hover": {
35
- background: selected ? "#f8f9fa" : "#fafafa",
36
- border: selected ? "1px solid #e9ecef" : "1px solid #f0f0f0",
37
- },
38
- }),
39
- );
23
+ // const MultiRowTab = styled(Button)<{ selected?: boolean }>(
24
+ // ({ theme, selected }) => ({
25
+ // minHeight: 32,
26
+ // padding: theme.spacing(0.75, 2),
27
+ // borderRadius: "6px",
28
+ // background: selected ? "#f8f9fa" : "transparent",
29
+ // color: selected ? "#495057" : "#666666",
30
+ // fontWeight: selected ? 600 : 500,
31
+ // border: selected ? "1px solid #e9ecef" : "1px solid transparent",
32
+ // boxShadow: "none",
33
+ // textTransform: "none",
34
+ // fontSize: "15px",
35
+ // "&:hover": {
36
+ // background: selected ? "#f8f9fa" : "#fafafa",
37
+ // border: selected ? "1px solid #e9ecef" : "1px solid #f0f0f0",
38
+ // },
39
+ // }),
40
+ // );
40
41
 
41
42
  export interface ModelExplorerProps {
42
43
  data?: CompiledModel;
@@ -103,43 +104,77 @@ export function ModelExplorer({
103
104
  return <Loading text="Loading..." />;
104
105
  }
105
106
 
107
+ const sourceOptions = (effectiveData?.sourceInfos || []).map(
108
+ (source, idx) => {
109
+ try {
110
+ const parsed = JSON.parse(source);
111
+ return parsed?.name || `Source ${idx + 1}`;
112
+ } catch {
113
+ return `Source ${idx + 1}`;
114
+ }
115
+ },
116
+ );
117
+ const selectedName = sourceOptions[selectedTab] || "";
118
+
106
119
  return (
107
120
  <StyledCard variant="outlined">
108
121
  <StyledCardContent>
109
122
  <Stack
110
123
  sx={{
111
124
  flexDirection: "row",
112
- justifyContent: "space-between",
113
125
  }}
114
126
  >
115
127
  {/* Render the tabs for source selection */}
116
- {Array.isArray(effectiveData.sourceInfos) &&
117
- effectiveData.sourceInfos.length > 0 && (
118
- <MultiRowTabBar>
119
- {effectiveData.sourceInfos.map((source, idx) => {
120
- let sourceInfo;
121
- try {
122
- sourceInfo = JSON.parse(source);
123
- } catch {
124
- sourceInfo = { name: String(idx) };
125
- }
126
- return (
127
- <MultiRowTab
128
- key={sourceInfo.name || idx}
129
- selected={selectedTab === idx}
130
- onClick={() => {
131
- setSelectedTab(idx);
132
- if (onSourceChange) {
133
- onSourceChange(idx);
134
- }
135
- }}
136
- >
137
- {sourceInfo.name || `Source ${idx + 1}`}
138
- </MultiRowTab>
139
- );
140
- })}
141
- </MultiRowTabBar>
142
- )}
128
+ {/* {Array.isArray(effectiveData.sourceInfos) &&
129
+ effectiveData.sourceInfos.length > 0 && (
130
+ <MultiRowTabBar>
131
+ {effectiveData.sourceInfos.map((source, idx) => {
132
+ let sourceInfo;
133
+ try {
134
+ sourceInfo = JSON.parse(source);
135
+ } catch {
136
+ sourceInfo = { name: String(idx) };
137
+ }
138
+ return (
139
+ <MultiRowTab
140
+ key={sourceInfo.name || idx}
141
+ selected={selectedTab === idx}
142
+ onClick={() => {
143
+ setSelectedTab(idx);
144
+ if (onSourceChange) {
145
+ onSourceChange(idx);
146
+ }
147
+ }}
148
+ >
149
+ {sourceInfo.name || `Source ${idx + 1}`}
150
+ </MultiRowTab>
151
+ );
152
+ })}
153
+ </MultiRowTabBar>
154
+ )} */}
155
+ <Autocomplete
156
+ size="small"
157
+ id="size-small-standard"
158
+ disablePortal
159
+ options={sourceOptions}
160
+ value={selectedName}
161
+ onChange={(_e, newValue) => {
162
+ if (!newValue) return;
163
+
164
+ const idx = sourceOptions.indexOf(newValue);
165
+ if (idx >= 0) {
166
+ setSelectedTab(idx);
167
+ onSourceChange?.(idx);
168
+ }
169
+ }}
170
+ renderInput={(params) => <TextField {...params} />}
171
+ style={{
172
+ width: 350,
173
+ marginTop: "3px",
174
+ marginLeft: "6px",
175
+ marginBottom: "8px",
176
+ }}
177
+ />
143
178
  </Stack>
144
179
  </StyledCardContent>
145
180
  <StyledCardMedia>
@@ -173,15 +173,16 @@ function SourceExplorerComponentInner({
173
173
  ...query,
174
174
  query: malloy,
175
175
  });
176
- return apiClients.queryResults.executeQuery(
176
+ return apiClients.models.executeQueryModel(
177
177
  projectName,
178
178
  packageName,
179
179
  sourceAndPath.modelPath,
180
- malloy,
181
- undefined,
182
- // sourceInfo.name,
183
- undefined,
184
- versionId,
180
+ {
181
+ query: malloy,
182
+ sourceName: undefined,
183
+ queryName: undefined,
184
+ versionId: versionId,
185
+ },
185
186
  );
186
187
  },
187
188
  onSuccess: (data) => {
@@ -1,18 +1,18 @@
1
1
  import CloseIcon from "@mui/icons-material/Close";
2
2
  import CodeIcon from "@mui/icons-material/Code";
3
3
  import ContentCopyIcon from "@mui/icons-material/ContentCopy";
4
+ import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
4
5
  import SearchIcon from "@mui/icons-material/Search";
5
- import ShareIcon from "@mui/icons-material/Share";
6
6
  import {
7
7
  Box,
8
8
  Dialog,
9
9
  DialogContent,
10
10
  DialogTitle,
11
11
  IconButton,
12
+ Snackbar,
12
13
  Stack,
13
14
  Tooltip,
14
15
  Typography,
15
- Snackbar,
16
16
  } from "@mui/material";
17
17
  import Markdown from "markdown-to-jsx";
18
18
  import React, { useEffect, useState } from "react";
@@ -176,8 +176,8 @@ export function NotebookCell({
176
176
  justifyContent="space-between"
177
177
  >
178
178
  <Markdown>{cell.text}</Markdown>
179
- <Tooltip title="Click to copy and share">
180
- <ShareIcon
179
+ <Tooltip title="Click to copy link">
180
+ <LinkOutlinedIcon
181
181
  sx={{
182
182
  fontSize: "24px",
183
183
  color: "#666666",
@@ -222,16 +222,16 @@ function getTreeViewRecursive(
222
222
  });
223
223
  } else {
224
224
  // This is a directory.
225
- path += `${key}/`;
225
+ const childPath = path + key + "/";
226
226
  treeViewItems.push({
227
- id: path,
227
+ id: childPath,
228
228
  label: key,
229
229
  fileType: "directory",
230
230
  selectable: true,
231
231
  link: undefined,
232
232
  children: getTreeViewRecursive(
233
233
  value as Map<string, unknown>,
234
- path,
234
+ childPath,
235
235
  onClickNode,
236
236
  ),
237
237
  });
@@ -1,17 +1,16 @@
1
- import { Grid, Box } from "@mui/material";
1
+ import { Box, Grid } from "@mui/material";
2
+ import { encodeResourceUri, parseResourceUri } from "../../utils/formatting";
2
3
  import { Notebook } from "../Notebook";
3
- import Config from "./Config";
4
- import Connections from "./Connections";
5
- import Databases from "./Databases";
6
- import Models from "./Models";
7
- import Notebooks from "./Notebooks";
8
- import Schedules from "./Schedules";
9
4
  import {
10
5
  PackageCard,
11
6
  PackageCardContent,
12
7
  PackageSectionTitle,
13
8
  } from "../styles";
14
- import { encodeResourceUri, parseResourceUri } from "../../utils/formatting";
9
+ import Config from "./Config";
10
+ import Connections from "./Connections";
11
+ import Databases from "./Databases";
12
+ import Models from "./Models";
13
+ import Notebooks from "./Notebooks";
15
14
 
16
15
  const README_NOTEBOOK = "README.malloynb";
17
16
 
@@ -59,9 +58,6 @@ export default function Package({
59
58
  <Grid size={{ xs: 12, md: 6 }}>
60
59
  <Connections resourceUri={resourceUri} />
61
60
  </Grid>
62
- <Grid size={{ xs: 12, md: 12 }}>
63
- <Schedules resourceUri={resourceUri} />
64
- </Grid>
65
61
  <Grid size={{ xs: 12, md: 12 }}>
66
62
  <PackageCard>
67
63
  <PackageCardContent>
@@ -1,38 +1,93 @@
1
- import { Box } from "@mui/material";
1
+ import { Box, Button } from "@mui/material";
2
2
  import Markdown from "markdown-to-jsx";
3
+ import { useState } from "react";
3
4
  import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
5
+ import { parseResourceUri } from "../../utils/formatting";
4
6
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
5
7
  import { Loading } from "../Loading";
8
+ import { useServer } from "../ServerProvider";
6
9
  import {
7
10
  PackageCard,
8
11
  PackageCardContent,
9
12
  PackageSectionTitle,
10
13
  } from "../styles";
11
- import { parseResourceUri } from "../../utils/formatting";
12
- import { useServer } from "../ServerProvider";
13
-
14
14
  interface AboutProps {
15
15
  resourceUri: string;
16
16
  }
17
17
 
18
18
  export default function About({ resourceUri }: AboutProps) {
19
- const { projectName: projectName } = parseResourceUri(resourceUri);
19
+ const { projectName } = parseResourceUri(resourceUri);
20
20
  const { apiClients } = useServer();
21
+ const [expanded, setExpanded] = useState(false);
22
+ const wordLimit = 90;
21
23
 
22
24
  const { data, isSuccess, isError, error } = useQueryWithApiError({
23
25
  queryKey: ["about", projectName],
24
26
  queryFn: () => apiClients.projects.getProject(projectName, false),
25
27
  });
26
28
 
29
+ const readmeContent = data?.data?.readme || "";
30
+ const words = readmeContent.split(/\s+/);
31
+ const shouldTruncate = words.length > wordLimit;
32
+ const preview = words.slice(0, wordLimit).join(" ");
33
+
27
34
  return (
28
35
  <>
29
36
  {!isSuccess && !isError && <Loading text="Fetching About..." />}
30
- {isSuccess && data.data?.readme && (
37
+ {isSuccess && readmeContent && (
31
38
  <PackageCard>
32
39
  <PackageCardContent>
33
40
  <PackageSectionTitle>Readme</PackageSectionTitle>
34
- <Box sx={{ mt: 1 }}>
35
- <Markdown>{data.data.readme}</Markdown>
41
+ <Box sx={{ mt: 1, fontSize: "0.875rem", lineHeight: 1.6 }}>
42
+ <Markdown
43
+ options={{
44
+ overrides: {
45
+ h1: {
46
+ component: "p",
47
+ props: {
48
+ style: {
49
+ fontSize: "inherit",
50
+ fontWeight: "italic",
51
+ },
52
+ },
53
+ },
54
+ h2: {
55
+ component: "p",
56
+ props: {
57
+ style: {
58
+ fontSize: "inherit",
59
+ fontWeight: "italic",
60
+ },
61
+ },
62
+ },
63
+ h3: {
64
+ component: "p",
65
+ props: {
66
+ style: {
67
+ fontSize: "inherit",
68
+ fontWeight: "italic",
69
+ },
70
+ },
71
+ },
72
+ },
73
+ }}
74
+ >
75
+ {expanded || !shouldTruncate ? readmeContent : preview}
76
+ </Markdown>
77
+
78
+ {shouldTruncate && (
79
+ <Box sx={{ mt: 1 }}>
80
+ {" "}
81
+ {/* separate line */}
82
+ <Button
83
+ variant="text"
84
+ size="small"
85
+ onClick={() => setExpanded(!expanded)}
86
+ >
87
+ {expanded ? "Read less" : "Read more"}
88
+ </Button>
89
+ </Box>
90
+ )}
36
91
  </Box>
37
92
  </PackageCardContent>
38
93
  </PackageCard>