@malloy-publisher/sdk 0.0.65 → 0.0.67

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/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.65",
4
+ "version": "0.0.67",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.es.js",
@@ -1,8 +1,26 @@
1
- import { Grid, Typography } from "@mui/material";
2
- import { ProjectsApi, Configuration } from "../../client";
1
+ import AnalyticsRoundedIcon from "@mui/icons-material/AnalyticsRounded";
2
+ import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded";
3
+ import AutoAwesomeRoundedIcon from "@mui/icons-material/AutoAwesomeRounded";
4
+ import CodeRoundedIcon from "@mui/icons-material/CodeRounded";
5
+ import ExploreRoundedIcon from "@mui/icons-material/ExploreRounded";
6
+ import PsychologyRoundedIcon from "@mui/icons-material/PsychologyRounded";
7
+ import StorageRoundedIcon from "@mui/icons-material/StorageRounded";
8
+ import {
9
+ Box,
10
+ Button,
11
+ Card,
12
+ CardContent,
13
+ Chip,
14
+ Container,
15
+ Divider,
16
+ Grid,
17
+ Stack,
18
+ Typography,
19
+ } from "@mui/material";
20
+ import { Configuration, ProjectsApi } from "../../client";
21
+ import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
3
22
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
4
23
  import { Loading } from "../Loading";
5
- import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
6
24
 
7
25
  const projectsApi = new ProjectsApi(new Configuration());
8
26
 
@@ -10,6 +28,36 @@ interface HomeProps {
10
28
  navigate?: (to: string, event?: React.MouseEvent) => void;
11
29
  }
12
30
 
31
+ // Helper function to extract a brief description from README content
32
+ const getProjectDescription = (readme: string | undefined): string => {
33
+ if (!readme) {
34
+ return "Explore semantic models, run queries, and build dashboards";
35
+ }
36
+
37
+ // Remove markdown formatting and get first paragraph
38
+ const cleanText = readme
39
+ .replace(/^#+\s+/gm, "") // Remove headers
40
+ .replace(/\*\*(.*?)\*\*/g, "$1") // Remove bold
41
+ .replace(/\*(.*?)\*/g, "$1") // Remove italic
42
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") // Remove links
43
+ .replace(/`([^`]+)`/g, "$1") // Remove code
44
+ .trim();
45
+
46
+ // Get first paragraph (split by double newlines)
47
+ const paragraphs = cleanText.split(/\n\s*\n/);
48
+ const firstParagraph = paragraphs[0] || cleanText;
49
+
50
+ // Limit to ~120 characters
51
+ if (firstParagraph.length <= 120) {
52
+ return firstParagraph;
53
+ }
54
+
55
+ // Truncate at word boundary
56
+ const truncated = firstParagraph.substring(0, 120).split(" ");
57
+ truncated.pop(); // Remove last partial word
58
+ return truncated.join(" ") + "...";
59
+ };
60
+
13
61
  export default function Home({ navigate }: HomeProps) {
14
62
  const { data, isSuccess, isError, error } = useQueryWithApiError({
15
63
  queryKey: ["projects"],
@@ -21,34 +69,355 @@ export default function Home({ navigate }: HomeProps) {
21
69
  }
22
70
 
23
71
  if (isSuccess) {
24
- if (data.data.length === 0) {
25
- return <Typography variant="h4">No projects found</Typography>;
26
- } else if (data.data.length === 1) {
27
- navigate(`/${data.data[0].name}/`);
28
- return <></>;
29
- } else {
30
- return (
31
- <Grid
32
- container
33
- spacing={2}
34
- columns={12}
35
- sx={{ mb: (theme) => theme.spacing(2) }}
36
- >
37
- {data.data.map((project) => (
38
- <Grid key={project.name}>
39
- <Typography
40
- variant="h1"
41
- onClick={(event) =>
42
- navigate(`/${project.name}/`, event)
43
- }
72
+ return (
73
+ <Container maxWidth="lg" sx={{ py: 4 }}>
74
+ {/* Hero Section */}
75
+ <Box sx={{ textAlign: "center", mb: 6 }}>
76
+ <Stack
77
+ direction="row"
78
+ justifyContent="center"
79
+ alignItems="center"
80
+ spacing={1}
81
+ sx={{ mb: 2 }}
82
+ >
83
+ <AutoAwesomeRoundedIcon
84
+ sx={{ fontSize: 32, color: "primary.main" }}
85
+ />
86
+ <Typography variant="h3" component="h1" fontWeight={700}>
87
+ Publisher
88
+ </Typography>
89
+ </Stack>
90
+ <Typography
91
+ variant="h5"
92
+ color="text.secondary"
93
+ sx={{ mb: 3, maxWidth: 600, mx: "auto" }}
94
+ >
95
+ The open-source semantic model server for the Malloy data
96
+ language
97
+ </Typography>
98
+ <Typography
99
+ variant="body1"
100
+ color="text.secondary"
101
+ sx={{ maxWidth: 800, mx: "auto" }}
102
+ >
103
+ Define semantic models once — and use them everywhere.
104
+ Publisher serves Malloy models through clean APIs, enabling
105
+ consistent, interpretable, and AI-ready data access for tools,
106
+ applications, and agents.
107
+ </Typography>
108
+ </Box>
109
+
110
+ {/* Feature Cards */}
111
+ <Grid container spacing={3} sx={{ mb: 6 }}>
112
+ <Grid size={{ xs: 12, md: 4 }}>
113
+ <Card
114
+ variant="outlined"
115
+ onClick={() => {
116
+ window.open(
117
+ "https://github.com/malloydata/publisher/blob/main/README.md#ad-hoc-data-analysis",
118
+ "_blank",
119
+ );
120
+ }}
121
+ sx={{
122
+ height: "100%",
123
+ cursor: "pointer",
124
+ transition: "all 0.2s ease",
125
+ "&:hover": {
126
+ transform: "translateY(-2px)",
127
+ boxShadow: 2,
128
+ },
129
+ }}
130
+ >
131
+ <CardContent sx={{ p: 3 }}>
132
+ <Stack
133
+ direction="row"
134
+ alignItems="center"
135
+ spacing={1}
136
+ sx={{ mb: 2 }}
137
+ >
138
+ <AnalyticsRoundedIcon
139
+ sx={{ color: "info.main", fontSize: 28 }}
140
+ />
141
+ <Typography variant="h6" fontWeight={600}>
142
+ Ad Hoc Analysis
143
+ </Typography>
144
+ </Stack>
145
+ <Typography
146
+ variant="body2"
147
+ color="text.secondary"
148
+ sx={{ mb: 2 }}
149
+ >
150
+ Use Explorer, a visual query builder that allows
151
+ analysts to browse semantic sources, build queries,
152
+ and run nested logic — all without writing code.
153
+ </Typography>
154
+ <Chip
155
+ label="No-code"
156
+ size="small"
157
+ color="primary"
158
+ variant="outlined"
159
+ />
160
+ </CardContent>
161
+ </Card>
162
+ </Grid>
163
+
164
+ <Grid size={{ xs: 12, md: 4 }}>
165
+ <Card
166
+ variant="outlined"
167
+ onClick={() => {
168
+ window.open(
169
+ "https://github.com/malloydata/publisher/blob/main/README.md#notebook-based-dashboards",
170
+ "_blank",
171
+ );
172
+ }}
173
+ sx={{
174
+ height: "100%",
175
+ cursor: "pointer",
176
+ transition: "all 0.2s ease",
177
+ "&:hover": {
178
+ transform: "translateY(-2px)",
179
+ boxShadow: 2,
180
+ },
181
+ }}
182
+ >
183
+ <CardContent sx={{ p: 3 }}>
184
+ <Stack
185
+ direction="row"
186
+ alignItems="center"
187
+ spacing={1}
188
+ sx={{ mb: 2 }}
189
+ >
190
+ <CodeRoundedIcon
191
+ sx={{ color: "warning.main", fontSize: 28 }}
192
+ />
193
+ <Typography variant="h6" fontWeight={600}>
194
+ Notebook Dashboards
195
+ </Typography>
196
+ </Stack>
197
+ <Typography
198
+ variant="body2"
199
+ color="text.secondary"
200
+ sx={{ mb: 2 }}
201
+ >
202
+ Create shareable, code-first dashboards using Malloy
203
+ notebooks. Include text, charts, and reusable views —
204
+ all versioned alongside your models.
205
+ </Typography>
206
+ <Chip
207
+ label="Versioned"
208
+ size="small"
209
+ color="warning"
210
+ variant="outlined"
211
+ />
212
+ </CardContent>
213
+ </Card>
214
+ </Grid>
215
+
216
+ <Grid size={{ xs: 12, md: 4 }}>
217
+ <Card
218
+ variant="outlined"
219
+ onClick={() => {
220
+ window.open(
221
+ "https://github.com/malloydata/publisher/blob/main/README.md#mcp-based-ai-data-agents",
222
+ "_blank",
223
+ );
224
+ }}
225
+ sx={{
226
+ height: "100%",
227
+ cursor: "pointer",
228
+ transition: "all 0.2s ease",
229
+ "&:hover": {
230
+ transform: "translateY(-2px)",
231
+ boxShadow: 2,
232
+ },
233
+ }}
234
+ >
235
+ <CardContent sx={{ p: 3 }}>
236
+ <Stack
237
+ direction="row"
238
+ alignItems="center"
239
+ spacing={1}
240
+ sx={{ mb: 2 }}
241
+ >
242
+ <PsychologyRoundedIcon
243
+ sx={{ color: "success.main", fontSize: 28 }}
244
+ />
245
+ <Typography variant="h6" fontWeight={600}>
246
+ AI Data Agents
247
+ </Typography>
248
+ </Stack>
249
+ <Typography
250
+ variant="body2"
251
+ color="text.secondary"
252
+ sx={{ mb: 2 }}
253
+ >
254
+ Expose your semantic models via the Model Context
255
+ Protocol (MCP), enabling AI agents to discover
256
+ sources and ask well-formed questions.
257
+ </Typography>
258
+ <Chip
259
+ label="AI-Ready"
260
+ size="small"
261
+ color="success"
262
+ variant="outlined"
263
+ />
264
+ </CardContent>
265
+ </Card>
266
+ </Grid>
267
+ </Grid>
268
+
269
+ <Divider sx={{ my: 4 }} />
270
+
271
+ {/* Project Selection Section */}
272
+ {data.data.length > 0 ? (
273
+ <>
274
+ <Box sx={{ textAlign: "center", mb: 4 }}>
275
+ <Stack
276
+ direction="row"
277
+ justifyContent="center"
278
+ alignItems="center"
279
+ spacing={1}
280
+ sx={{ mb: 2 }}
44
281
  >
45
- {project.name}
282
+ <StorageRoundedIcon
283
+ sx={{ color: "primary.main", fontSize: 24 }}
284
+ />
285
+ <Typography variant="h4" fontWeight={600}>
286
+ Select a Project
287
+ </Typography>
288
+ </Stack>
289
+ <Typography variant="body1" color="text.secondary">
290
+ Choose a project to explore its semantic models and
291
+ start analyzing your data
46
292
  </Typography>
293
+ </Box>
294
+ <Grid container spacing={3} justifyContent="center">
295
+ {data.data.map((project) => (
296
+ <Grid
297
+ size={{ xs: 12, sm: 6, md: 4 }}
298
+ key={project.name}
299
+ >
300
+ <Card
301
+ variant="outlined"
302
+ sx={{
303
+ height: "100%",
304
+ cursor: "pointer",
305
+ transition: "all 0.2s ease",
306
+ "&:hover": {
307
+ transform: "translateY(-2px)",
308
+ boxShadow: 2,
309
+ borderColor: "primary.main",
310
+ },
311
+ }}
312
+ onClick={(event) =>
313
+ navigate(`/${project.name}/`, event)
314
+ }
315
+ >
316
+ <CardContent sx={{ p: 3, textAlign: "center" }}>
317
+ <ExploreRoundedIcon
318
+ sx={{
319
+ fontSize: 48,
320
+ color: "primary.main",
321
+ mb: 2,
322
+ }}
323
+ />
324
+ <Typography
325
+ variant="h6"
326
+ fontWeight={600}
327
+ gutterBottom
328
+ >
329
+ {project.name}
330
+ </Typography>
331
+ <Typography
332
+ variant="body2"
333
+ color="text.secondary"
334
+ sx={{ mb: 2 }}
335
+ >
336
+ {getProjectDescription(project.readme)}
337
+ </Typography>
338
+ <Button
339
+ variant="contained"
340
+ color="secondary"
341
+ endIcon={<ArrowForwardRoundedIcon />}
342
+ fullWidth
343
+ >
344
+ Open Project
345
+ </Button>
346
+ </CardContent>
347
+ </Card>
348
+ </Grid>
349
+ ))}
47
350
  </Grid>
48
- ))}
49
- </Grid>
50
- );
51
- }
351
+ </>
352
+ ) : (
353
+ <Box sx={{ textAlign: "center", mb: 4 }}>
354
+ <Stack
355
+ direction="row"
356
+ justifyContent="center"
357
+ alignItems="center"
358
+ spacing={1}
359
+ sx={{ mb: 2 }}
360
+ >
361
+ <StorageRoundedIcon
362
+ sx={{ color: "primary.main", fontSize: 24 }}
363
+ />
364
+ <Typography variant="h4" fontWeight={600}>
365
+ Get Started
366
+ </Typography>
367
+ </Stack>
368
+ <Typography
369
+ variant="body1"
370
+ color="text.secondary"
371
+ sx={{ mb: 3 }}
372
+ >
373
+ No projects found. Create your first Malloy project to
374
+ start exploring semantic models and building data
375
+ experiences.
376
+ </Typography>
377
+ <Button
378
+ variant="contained"
379
+ size="large"
380
+ color="primary"
381
+ startIcon={<AutoAwesomeRoundedIcon />}
382
+ href="https://github.com/malloydata/publisher/blob/main/README.md#server-configuration"
383
+ target="_blank"
384
+ rel="noopener noreferrer"
385
+ >
386
+ Learn How to Create Models
387
+ </Button>
388
+ </Box>
389
+ )}
390
+
391
+ {/* Footer Section */}
392
+ <Box
393
+ sx={{
394
+ textAlign: "center",
395
+ mt: 6,
396
+ pt: 4,
397
+ borderTop: 1,
398
+ borderColor: "divider",
399
+ }}
400
+ >
401
+ <Typography variant="body2" color="text.secondary">
402
+ Publisher is built on fully open infrastructure and designed
403
+ for the AI era. Join the{" "}
404
+ <a
405
+ href="https://join.slack.com/t/malloy-community/shared_invite/zt-1kgfwgi5g-CrsdaRqs81QY67QW0~t_uw"
406
+ target="_blank"
407
+ rel="noopener noreferrer"
408
+ style={{
409
+ color: "primary.main",
410
+ textDecoration: "underline",
411
+ }}
412
+ >
413
+ Malloy Slack community
414
+ </a>{" "}
415
+ to ask questions, share ideas, and contribute to the future of
416
+ data modeling.
417
+ </Typography>
418
+ </Box>
419
+ </Container>
420
+ );
52
421
  } else {
53
422
  return <Loading text="Loading projects..." />;
54
423
  }