@malloy-publisher/server 0.0.196-dev → 0.0.197-dev

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 (99) hide show
  1. package/dist/app/api-doc.yaml +213 -214
  2. package/dist/app/assets/EnvironmentPage-1j6QDWAy.js +1 -0
  3. package/dist/app/assets/HomePage-DMop21VG.js +1 -0
  4. package/dist/app/assets/MainPage-BbE8ETz1.js +2 -0
  5. package/dist/app/assets/ModelPage-D2jvfe3t.js +1 -0
  6. package/dist/app/assets/PackagePage-BbnhGoD3.js +1 -0
  7. package/dist/app/assets/{RouteError-DefbDO7F.js → RouteError-D3LGEZ3i.js} +1 -1
  8. package/dist/app/assets/WorkbookPage-DttVIj4u.js +1 -0
  9. package/dist/app/assets/{core-BrfQApxh.es-DnvCX4oH.js → core-w79IMXAG.es-Bd0UlzOL.js} +1 -1
  10. package/dist/app/assets/{index-Bu0ub036.js → index-5K9YjIxF.js} +117 -117
  11. package/dist/app/assets/{index-CkzK3JIl.js → index-C513UodQ.js} +1 -1
  12. package/dist/app/assets/{index-CoA6HIGS.js → index-DIgzgp69.js} +1 -1
  13. package/dist/app/assets/{index.umd-B6Ms2PpL.js → index.umd-BMeMPq_9.js} +1 -1
  14. package/dist/app/index.html +1 -1
  15. package/dist/server.mjs +1328 -1304
  16. package/package.json +1 -1
  17. package/publisher.config.json +2 -2
  18. package/src/config.spec.ts +74 -66
  19. package/src/config.ts +50 -47
  20. package/src/controller/compile.controller.ts +10 -7
  21. package/src/controller/connection.controller.ts +79 -58
  22. package/src/controller/database.controller.ts +10 -7
  23. package/src/controller/manifest.controller.ts +23 -14
  24. package/src/controller/materialization.controller.ts +14 -14
  25. package/src/controller/model.controller.ts +35 -20
  26. package/src/controller/package.controller.ts +83 -49
  27. package/src/controller/query.controller.ts +11 -8
  28. package/src/controller/watch-mode.controller.ts +35 -29
  29. package/src/errors.ts +2 -2
  30. package/src/mcp/error_messages.ts +2 -2
  31. package/src/mcp/handler_utils.ts +23 -20
  32. package/src/mcp/mcp_constants.ts +1 -1
  33. package/src/mcp/prompts/handlers.ts +3 -3
  34. package/src/mcp/prompts/prompt_service.ts +5 -5
  35. package/src/mcp/prompts/utils.ts +12 -12
  36. package/src/mcp/resource_metadata.ts +3 -3
  37. package/src/mcp/resources/environment_resource.ts +187 -0
  38. package/src/mcp/resources/model_resource.ts +19 -17
  39. package/src/mcp/resources/notebook_resource.ts +13 -13
  40. package/src/mcp/resources/package_resource.ts +30 -27
  41. package/src/mcp/resources/query_resource.ts +15 -10
  42. package/src/mcp/resources/source_resource.ts +10 -10
  43. package/src/mcp/resources/view_resource.ts +11 -11
  44. package/src/mcp/server.ts +16 -14
  45. package/src/mcp/tools/discovery_tools.ts +67 -49
  46. package/src/mcp/tools/execute_query_tool.ts +14 -14
  47. package/src/server.ts +175 -159
  48. package/src/service/connection.spec.ts +158 -133
  49. package/src/service/connection.ts +42 -39
  50. package/src/service/connection_config.spec.ts +13 -11
  51. package/src/service/connection_config.ts +28 -19
  52. package/src/service/connection_service.spec.ts +63 -43
  53. package/src/service/connection_service.ts +106 -89
  54. package/src/service/{project.ts → environment.ts} +92 -77
  55. package/src/service/{project_compile.spec.ts → environment_compile.spec.ts} +1 -1
  56. package/src/service/{project_store.spec.ts → environment_store.spec.ts} +99 -85
  57. package/src/service/{project_store.ts → environment_store.ts} +368 -326
  58. package/src/service/manifest_service.spec.ts +15 -15
  59. package/src/service/manifest_service.ts +26 -21
  60. package/src/service/materialization_service.spec.ts +93 -59
  61. package/src/service/materialization_service.ts +71 -62
  62. package/src/service/materialized_table_gc.spec.ts +15 -15
  63. package/src/service/materialized_table_gc.ts +3 -3
  64. package/src/service/model.ts +2 -2
  65. package/src/service/package.spec.ts +2 -2
  66. package/src/service/package.ts +23 -21
  67. package/src/service/resolve_environment.ts +15 -0
  68. package/src/storage/DatabaseInterface.ts +34 -25
  69. package/src/storage/StorageManager.mock.ts +3 -3
  70. package/src/storage/StorageManager.ts +24 -23
  71. package/src/storage/duckdb/ConnectionRepository.ts +13 -11
  72. package/src/storage/duckdb/DuckDBConnection.ts +1 -1
  73. package/src/storage/duckdb/DuckDBManifestStore.ts +6 -6
  74. package/src/storage/duckdb/DuckDBRepository.ts +47 -47
  75. package/src/storage/duckdb/{ProjectRepository.ts → EnvironmentRepository.ts} +35 -35
  76. package/src/storage/duckdb/ManifestRepository.ts +21 -20
  77. package/src/storage/duckdb/MaterializationRepository.ts +31 -28
  78. package/src/storage/duckdb/PackageRepository.ts +11 -11
  79. package/src/storage/duckdb/manifest_store.spec.ts +2 -2
  80. package/src/storage/duckdb/schema.ts +20 -20
  81. package/src/storage/ducklake/DuckLakeManifestStore.ts +14 -14
  82. package/tests/fixtures/publisher.config.json +1 -1
  83. package/tests/harness/e2e.ts +1 -1
  84. package/tests/harness/mcp_test_setup.ts +1 -1
  85. package/tests/harness/mocks.ts +10 -8
  86. package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +4 -4
  87. package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +27 -48
  88. package/tests/integration/mcp/mcp_resource.integration.spec.ts +26 -35
  89. package/tests/unit/duckdb/attached_databases.test.ts +51 -33
  90. package/tests/unit/ducklake/ducklake.test.ts +24 -22
  91. package/tests/unit/mcp/prompt_happy.test.ts +8 -8
  92. package/dist/app/assets/HomePage-DbZS0N7G.js +0 -1
  93. package/dist/app/assets/MainPage-CBuWkbmr.js +0 -2
  94. package/dist/app/assets/ModelPage-Bt37smot.js +0 -1
  95. package/dist/app/assets/PackagePage-DLZe50WG.js +0 -1
  96. package/dist/app/assets/ProjectPage-FQTEPXP4.js +0 -1
  97. package/dist/app/assets/WorkbookPage-CkAo16ar.js +0 -1
  98. package/src/mcp/resources/project_resource.ts +0 -184
  99. package/src/service/resolve_project.ts +0 -13
@@ -1,2 +0,0 @@
1
- import{u as V,g as F,r as g,R as _,a as X,b as S,c as M,e as A,j as e,s as m,f as w,h as v,k as I,P as Y,m as R,l as J,n as z,B as K,o as N,p as Z,T as U,q,t as oo,d as ro,v as f,C as j,w as eo,x as to,I as ao,M as so,y as $,S as no,z as lo,A as io,O as co,D as po}from"./index-Bu0ub036.js";function uo(o,r,t,a,n){const[s,i]=g.useState(()=>n&&t?t(o).matches:a?a(o).matches:r);return X(()=>{if(!t)return;const p=t(o),u=()=>{i(p.matches)};return u(),p.addEventListener("change",u),()=>{p.removeEventListener("change",u)}},[o,t]),s}const go={..._},L=go.useSyncExternalStore;function xo(o,r,t,a,n){const s=g.useCallback(()=>r,[r]),i=g.useMemo(()=>{if(n&&t)return()=>t(o).matches;if(a!==null){const{matches:c}=a(o);return()=>c}return s},[s,o,a,n,t]),[p,u]=g.useMemo(()=>{if(t===null)return[s,()=>()=>{}];const c=t(o);return[()=>c.matches,l=>(c.addEventListener("change",l),()=>{c.removeEventListener("change",l)})]},[s,t,o]);return L(u,p,i)}function O(o={}){const{themeId:r}=o;return function(a,n={}){let s=V();s&&r&&(s=s[r]||s);const i=typeof window<"u"&&typeof window.matchMedia<"u",{defaultMatches:p=!1,matchMedia:u=i?window.matchMedia:null,ssrMatchMedia:d=null,noSsr:c=!1}=F({name:"MuiUseMediaQuery",props:n,theme:s});let l=typeof a=="function"?a(s):a;return l=l.replace(/^@media( ?)/m,""),l.includes("print")&&console.warn(["MUI: You have provided a `print` query to the `useMediaQuery` hook.","Using the print media query to modify print styles can lead to unexpected results.","Consider using the `displayPrint` field in the `sx` prop instead.","More information about `displayPrint` on our docs: https://mui.com/system/display/#display-in-print."].join(`
2
- `)),(L!==void 0?xo:uo)(l,p,u,d,c)}}O();function mo(o){return S("MuiAppBar",o)}M("MuiAppBar",["root","positionFixed","positionAbsolute","positionSticky","positionStatic","positionRelative","colorDefault","colorPrimary","colorSecondary","colorInherit","colorTransparent","colorError","colorInfo","colorSuccess","colorWarning"]);const fo=o=>{const{color:r,position:t,classes:a}=o,n={root:["root",`color${v(r)}`,`position${v(t)}`]};return I(n,mo,a)},D=(o,r)=>o?`${o?.replace(")","")}, ${r})`:r,bo=m(Y,{name:"MuiAppBar",slot:"Root",overridesResolver:(o,r)=>{const{ownerState:t}=o;return[r.root,r[`position${v(t.position)}`],r[`color${v(t.color)}`]]}})(R(({theme:o})=>({display:"flex",flexDirection:"column",width:"100%",boxSizing:"border-box",flexShrink:0,variants:[{props:{position:"fixed"},style:{position:"fixed",zIndex:(o.vars||o).zIndex.appBar,top:0,left:"auto",right:0,"@media print":{position:"absolute"}}},{props:{position:"absolute"},style:{position:"absolute",zIndex:(o.vars||o).zIndex.appBar,top:0,left:"auto",right:0}},{props:{position:"sticky"},style:{position:"sticky",zIndex:(o.vars||o).zIndex.appBar,top:0,left:"auto",right:0}},{props:{position:"static"},style:{position:"static"}},{props:{position:"relative"},style:{position:"relative"}},{props:{color:"inherit"},style:{"--AppBar-color":"inherit"}},{props:{color:"default"},style:{"--AppBar-background":o.vars?o.vars.palette.AppBar.defaultBg:o.palette.grey[100],"--AppBar-color":o.vars?o.vars.palette.text.primary:o.palette.getContrastText(o.palette.grey[100]),...o.applyStyles("dark",{"--AppBar-background":o.vars?o.vars.palette.AppBar.defaultBg:o.palette.grey[900],"--AppBar-color":o.vars?o.vars.palette.text.primary:o.palette.getContrastText(o.palette.grey[900])})}},...Object.entries(o.palette).filter(J(["contrastText"])).map(([r])=>({props:{color:r},style:{"--AppBar-background":(o.vars??o).palette[r].main,"--AppBar-color":(o.vars??o).palette[r].contrastText}})),{props:r=>r.enableColorOnDark===!0&&!["inherit","transparent"].includes(r.color),style:{backgroundColor:"var(--AppBar-background)",color:"var(--AppBar-color)"}},{props:r=>r.enableColorOnDark===!1&&!["inherit","transparent"].includes(r.color),style:{backgroundColor:"var(--AppBar-background)",color:"var(--AppBar-color)",...o.applyStyles("dark",{backgroundColor:o.vars?D(o.vars.palette.AppBar.darkBg,"var(--AppBar-background)"):null,color:o.vars?D(o.vars.palette.AppBar.darkColor,"var(--AppBar-color)"):null})}},{props:{color:"transparent"},style:{"--AppBar-background":"transparent","--AppBar-color":"inherit",backgroundColor:"var(--AppBar-background)",color:"var(--AppBar-color)",...o.applyStyles("dark",{backgroundImage:"none"})}}]}))),ho=g.forwardRef(function(r,t){const a=A({props:r,name:"MuiAppBar"}),{className:n,color:s="primary",enableColorOnDark:i=!1,position:p="fixed",...u}=a,d={...a,color:s,position:p,enableColorOnDark:i},c=fo(d);return e.jsx(bo,{square:!0,component:"header",ownerState:d,elevation:4,className:w(c.root,n,p==="fixed"&&"mui-fixed"),ref:t,...u})}),yo=z(e.jsx("path",{d:"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"})),vo=m(K,{name:"MuiBreadcrumbCollapsed"})(R(({theme:o})=>({display:"flex",marginLeft:`calc(${o.spacing(1)} * 0.5)`,marginRight:`calc(${o.spacing(1)} * 0.5)`,...o.palette.mode==="light"?{backgroundColor:o.palette.grey[100],color:o.palette.grey[700]}:{backgroundColor:o.palette.grey[700],color:o.palette.grey[100]},borderRadius:2,"&:hover, &:focus":{...o.palette.mode==="light"?{backgroundColor:o.palette.grey[200]}:{backgroundColor:o.palette.grey[600]}},"&:active":{boxShadow:o.shadows[0],...o.palette.mode==="light"?{backgroundColor:N(o.palette.grey[200],.12)}:{backgroundColor:N(o.palette.grey[600],.12)}}}))),ko=m(yo)({width:24,height:16});function Bo(o){const{slots:r={},slotProps:t={},...a}=o,n=o;return e.jsx("li",{children:e.jsx(vo,{focusRipple:!0,...a,ownerState:n,children:e.jsx(ko,{as:r.CollapsedIcon,ownerState:n,...t.collapsedIcon})})})}function Co(o){return S("MuiBreadcrumbs",o)}const jo=M("MuiBreadcrumbs",["root","ol","li","separator"]),So=o=>{const{classes:r}=o;return I({root:["root"],li:["li"],ol:["ol"],separator:["separator"]},Co,r)},Mo=m(U,{name:"MuiBreadcrumbs",slot:"Root",overridesResolver:(o,r)=>[{[`& .${jo.li}`]:r.li},r.root]})({}),Ao=m("ol",{name:"MuiBreadcrumbs",slot:"Ol"})({display:"flex",flexWrap:"wrap",alignItems:"center",padding:0,margin:0,listStyle:"none"}),wo=m("li",{name:"MuiBreadcrumbs",slot:"Separator"})({display:"flex",userSelect:"none",marginLeft:8,marginRight:8});function Io(o,r,t,a){return o.reduce((n,s,i)=>(i<o.length-1?n=n.concat(s,e.jsx(wo,{"aria-hidden":!0,className:r,ownerState:a,children:t},`separator-${i}`)):n.push(s),n),[])}const Ro=g.forwardRef(function(r,t){const a=A({props:r,name:"MuiBreadcrumbs"}),{children:n,className:s,component:i="nav",slots:p={},slotProps:u={},expandText:d="Show path",itemsAfterCollapse:c=1,itemsBeforeCollapse:l=1,maxItems:h=8,separator:k="/",...Q}=a,[T,W]=g.useState(!1),b={...a,component:i,expanded:T,expandText:d,itemsAfterCollapse:c,itemsBeforeCollapse:l,maxItems:h,separator:k},y=So(b),H=Z({elementType:p.CollapsedIcon,externalSlotProps:u.collapsedIcon,ownerState:b}),P=g.useRef(null),G=x=>{const C=()=>{W(!0);const E=P.current.querySelector("a[href],button,[tabindex]");E&&E.focus()};return l+c>=x.length?x:[...x.slice(0,l),e.jsx(Bo,{"aria-label":d,slots:{CollapsedIcon:p.CollapsedIcon},slotProps:{collapsedIcon:H},onClick:C},"ellipsis"),...x.slice(x.length-c,x.length)]},B=g.Children.toArray(n).filter(x=>g.isValidElement(x)).map((x,C)=>e.jsx("li",{className:y.li,children:x},`child-${C}`));return e.jsx(Mo,{ref:t,component:i,color:"textSecondary",className:w(y.root,s),ownerState:b,...Q,children:e.jsx(Ao,{className:y.ol,ref:P,ownerState:b,children:Io(T||h&&B.length<=h?B:G(B),y.separator,k,b)})})});function zo(o){return S("MuiToolbar",o)}M("MuiToolbar",["root","gutters","regular","dense"]);const To=o=>{const{classes:r,disableGutters:t,variant:a}=o;return I({root:["root",!t&&"gutters",a]},zo,r)},Po=m("div",{name:"MuiToolbar",slot:"Root",overridesResolver:(o,r)=>{const{ownerState:t}=o;return[r.root,!t.disableGutters&&r.gutters,r[t.variant]]}})(R(({theme:o})=>({position:"relative",display:"flex",alignItems:"center",variants:[{props:({ownerState:r})=>!r.disableGutters,style:{paddingLeft:o.spacing(2),paddingRight:o.spacing(2),[o.breakpoints.up("sm")]:{paddingLeft:o.spacing(3),paddingRight:o.spacing(3)}}},{props:{variant:"dense"},style:{minHeight:48}},{props:{variant:"regular"},style:o.mixins.toolbar}]}))),Eo=g.forwardRef(function(r,t){const a=A({props:r,name:"MuiToolbar"}),{className:n,component:s="div",disableGutters:i=!1,variant:p="regular",...u}=a,d={...a,component:s,disableGutters:i,variant:p},c=To(d);return e.jsx(Po,{as:s,className:w(c.root,n),ref:t,ownerState:d,...u})}),No=O({themeId:q}),$o=z(e.jsx("path",{d:"M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})),Do=z(e.jsx("path",{d:"M3 18h18v-2H3zm0-5h18v-2H3zm0-7v2h18V6z"}));function Uo(){const o=oo(),r=o["*"],t=ro();return e.jsx(f,{sx:{display:"flex",alignItems:"center"},children:e.jsxs(Ro,{"aria-label":"breadcrumb",separator:e.jsx($o,{sx:{fontSize:14,color:"text.secondary"}}),sx:{"& .MuiBreadcrumbs-separator":{margin:"0 6px"}},children:[o.projectName&&e.jsx(j,{onClick:a=>t(`/${o.projectName}/`,a),label:o.projectName,size:"medium",sx:{backgroundColor:"background.paper",color:"primary.main",fontWeight:500,height:"32px",fontSize:"1rem",cursor:"pointer","&:hover":{backgroundColor:"primary.100"}}}),o.packageName&&e.jsx(j,{onClick:a=>t(`/${o.projectName}/${o.packageName}/`,a),label:o.packageName,size:"medium",sx:{backgroundColor:"background.paper",color:"primary.main",fontWeight:500,height:"32px",fontSize:"1rem",cursor:"pointer","&:hover":{backgroundColor:"secondary.100"}}}),r&&e.jsx(j,{onClick:a=>t(`/${o.projectName}/${o.packageName}/${r}`,a),label:r,size:"medium",sx:{backgroundColor:"background.paper",color:"primary.main",fontWeight:500,height:"32px",fontSize:"1rem",cursor:"pointer","&:hover":{backgroundColor:"grey.200"}}})]})})}function Lo({logoHeader:o,endCap:r}){const t=eo(),a=to(),n=No(a.breakpoints.down("sm")),[s,i]=g.useState(null),p=!!s,u=l=>{i(l.currentTarget)},d=()=>i(null),c=[{label:"Malloy Docs",link:"https://docs.malloydata.dev/documentation/",sx:{color:"primary.main"}},{label:"Publisher Docs",link:"https://github.com/malloydata/publisher/blob/main/README.md",sx:{color:"primary.main"}},{label:"Publisher API",link:"/api-doc.html",sx:{color:"primary.main"}}];return e.jsxs(ho,{position:"sticky",elevation:0,sx:{backgroundColor:"background.paper",borderBottom:"1px solid",borderColor:"divider"},children:[e.jsxs(Eo,{sx:{justifyContent:"space-between",flexWrap:"nowrap",minHeight:44},children:[o||e.jsxs(f,{sx:{display:"flex",alignItems:"center",gap:1,cursor:"pointer"},onClick:()=>t("/"),children:[e.jsx(f,{component:"img",src:"/logo.svg",alt:"Malloy",sx:{width:28,height:28}}),e.jsx(U,{variant:"h6",sx:{color:"text.primary",fontWeight:700,letterSpacing:"-0.025em",fontSize:{xs:"1.1rem",sm:"1.25rem"}},children:"Malloy Publisher"})]}),n?e.jsxs(e.Fragment,{children:[e.jsx(ao,{color:"inherit",onClick:u,children:e.jsx(Do,{})}),e.jsxs(so,{anchorEl:s,open:p,onClose:d,anchorOrigin:{vertical:"bottom",horizontal:"right"},children:[c.map(l=>e.jsx($,{onClick:()=>{d(),window.location.href=l.link},sx:l.sx,children:l.label},l.label)),r&&e.jsx($,{children:r})]})]}):e.jsxs(no,{direction:"row",spacing:2,alignItems:"center",children:[c.map(l=>e.jsx(lo,{href:l.link,sx:l.sx,children:l.label},l.label)),r]})]}),e.jsx(f,{sx:{borderTop:"1px solid white",paddingLeft:"16px",paddingRight:"16px",marginBottom:"1px",overflowX:"auto"},children:e.jsx(Uo,{})})]})}function Qo({headerProps:o}){return e.jsxs(f,{sx:{display:"flex",flexDirection:"column",minHeight:"100vh"},children:[e.jsx(Lo,{...o}),e.jsx(io,{maxWidth:"xl",component:"main",sx:{flex:1,display:"flex",flexDirection:"column",py:2,gap:2},children:e.jsx(f,{sx:{flex:1},children:e.jsx(g.Suspense,{fallback:e.jsx(po,{}),children:e.jsx(co,{})})})})]})}export{Qo as default};
@@ -1 +0,0 @@
1
- import{t as n,j as e,E as i,F as t,G as c}from"./index-Bu0ub036.js";function o(){const a=n(),r=a["*"];if(!a.projectName)return e.jsx("div",{children:e.jsx("h2",{children:"Missing project name"})});if(!a.packageName)return e.jsx("div",{children:e.jsx("h2",{children:"Missing package name"})});const s=i({projectName:a.projectName,packageName:a.packageName,modelPath:r});return r?.endsWith(".malloy")?e.jsx(t,{resourceUri:s,runOnDemand:!0,maxResultSize:512*1024}):r?.endsWith(".malloynb")?e.jsx(c,{resourceUri:s,maxResultSize:1024*1024}):e.jsx("div",{children:e.jsxs("h2",{children:["Unrecognized file type: ",r]})})}export{o as default};
@@ -1 +0,0 @@
1
- import{t as n,d as c,j as e,E as t,H as o}from"./index-Bu0ub036.js";function l(){const{projectName:s,packageName:a}=n(),r=c();if(s)if(a){const i=t({projectName:s,packageName:a});return e.jsx(o,{onClickPackageFile:r,resourceUri:i})}else return e.jsx("div",{children:e.jsx("h2",{children:"Missing package name"})});else return e.jsx("div",{children:e.jsx("h2",{children:"Missing project name"})})}export{l as default};
@@ -1 +0,0 @@
1
- import{d as a,t as n,j as e,E as o,J as c}from"./index-Bu0ub036.js";function u(){const r=a(),{projectName:s}=n();if(s){const t=o({projectName:s});return e.jsx(c,{onSelectPackage:r,resourceUri:t})}else return e.jsx("div",{children:e.jsx("h2",{children:"Missing project name"})})}export{u as default};
@@ -1 +0,0 @@
1
- import{t as a,j as e,E as t,Z as c}from"./index-Bu0ub036.js";function d(){const{workspace:r,workbookPath:s,projectName:i,packageName:n}=a();if(r)if(s)if(i)if(n){const o=t({projectName:i,packageName:n});return e.jsx(c,{workbookPath:{path:s,workspace:r},resourceUri:o},`${s}`)}else return e.jsx("div",{children:e.jsx("h2",{children:"Missing package name"})});else return e.jsx("div",{children:e.jsx("h2",{children:"Missing project name"})});else return e.jsx("div",{children:e.jsx("h2",{children:"Missing workbook path"})});else return e.jsx("div",{children:e.jsx("h2",{children:"Missing workspace"})})}export{d as default};
@@ -1,184 +0,0 @@
1
- import {
2
- McpServer,
3
- ResourceTemplate,
4
- } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import type { ListResourcesResult } from "@modelcontextprotocol/sdk/types.js"; // Needed for list return type
6
- import { logger } from "../../logger";
7
- import { ProjectStore } from "../../service/project_store";
8
- import { getInternalError, getNotFoundError } from "../error_messages"; // Needed for error handling in list AND get
9
- import { handleResourceGet, McpGetResourceError } from "../handler_utils";
10
- import { RESOURCE_METADATA } from "../resource_metadata";
11
-
12
- // Define an interface for the package object augmented with project name
13
- interface PackageWithProject {
14
- name?: string;
15
- // Add other relevant package properties if needed
16
- projectName: string;
17
- }
18
-
19
- /**
20
- * Registers the Malloy Project resource type with the MCP server.
21
- * Handles getting details for the hardcoded 'home' project and listing packages within it.
22
- */
23
- export function registerProjectResource(
24
- mcpServer: McpServer,
25
- projectStore: ProjectStore,
26
- ): void {
27
- mcpServer.resource(
28
- "project",
29
- new ResourceTemplate("malloy://project/{projectName}", {
30
- /**
31
- * Handles ListResources requests.
32
- * If projectName is specified, lists packages for that project (only 'home' supported).
33
- * If projectName is not specified (general ListResources call), lists packages for the default 'home' project.
34
- */
35
- list: async (/* extra: ListProjectExtra - Deleted */): Promise<ListResourcesResult> => {
36
- logger.info(
37
- "[MCP LOG] Entering ListResources (project) handler (listing ALL packages)...",
38
- );
39
- // Ignore parameters from 'extra' as URI path params aren't passed to list handlers.
40
-
41
- try {
42
- const allProjects = await projectStore.listProjects();
43
- logger.info(
44
- `[MCP LOG] Found ${allProjects.length} projects defined.`,
45
- );
46
-
47
- const packagePromises = allProjects.map(async (proj) => {
48
- try {
49
- logger.info(
50
- `[MCP LOG] Getting project '${proj.name}' to list its packages...`,
51
- );
52
- const projectInstance = await projectStore.getProject(
53
- proj.name!,
54
- false,
55
- ); // Use proj.name
56
- const packages = await projectInstance.listPackages();
57
- logger.info(
58
- `[MCP LOG] Found ${packages.length} packages in project '${proj.name}'.`,
59
- );
60
- // Return packages along with their project name for URI construction
61
- return packages.map((pkg) => ({
62
- ...pkg,
63
- projectName: proj.name,
64
- }));
65
- } catch (projectError) {
66
- logger.error(
67
- `[MCP Server Error] Error getting/listing packages for project ${proj.name}:`,
68
- { error: projectError },
69
- );
70
- return []; // Return empty array for this project on error
71
- }
72
- });
73
-
74
- const results = await Promise.allSettled(packagePromises);
75
- const allPackagesWithProjectName = results
76
- .filter((result) => result.status === "fulfilled")
77
- // Use the specific interface instead of any[]
78
- .flatMap(
79
- (result) =>
80
- (result as PromiseFulfilledResult<PackageWithProject[]>)
81
- .value,
82
- );
83
-
84
- logger.info(
85
- `[MCP LOG] Total packages found across all projects: ${allPackagesWithProjectName.length}`,
86
- );
87
-
88
- const packageMetadata = RESOURCE_METADATA.package;
89
- const mappedResources = allPackagesWithProjectName.map((pkg) => {
90
- const name = pkg.name || "unknown";
91
- // Construct URI using the package's specific projectName
92
- const uri = `malloy://project/${pkg.projectName}/package/${name}`;
93
- return {
94
- uri: uri,
95
- name: name,
96
- type: "package",
97
- description: packageMetadata?.description as
98
- | string
99
- | undefined,
100
- metadata: packageMetadata,
101
- };
102
- });
103
-
104
- logger.info(
105
- `[MCP LOG] ListResources (project): Returning ${mappedResources.length} package resources.`,
106
- );
107
- return {
108
- resources: mappedResources,
109
- };
110
- } catch (error) {
111
- // Catch errors from projectStore.listProjects() itself
112
- logger.error(`[MCP Server Error] Error listing projects:`, {
113
- error,
114
- });
115
- const errorDetails = getInternalError(
116
- `ListResources (project - initial list)`,
117
- error,
118
- );
119
- logger.error("MCP ListResources (project) error:", {
120
- error: errorDetails.message,
121
- });
122
- logger.info(
123
- "[MCP LOG] ListResources (project): Returning empty on error listing projects.",
124
- );
125
- return { resources: [] };
126
- }
127
- },
128
- }),
129
- /** Handles GetResource requests for Malloy Projects */
130
- (uri, params) =>
131
- handleResourceGet(
132
- uri,
133
- params,
134
- "project",
135
- async ({ projectName }: { projectName?: unknown }) => {
136
- logger.info(
137
- `[MCP LOG] Entering GetResource (project) handler for projectName: ${projectName}`,
138
- );
139
- // Validate project name parameter
140
- if (typeof projectName !== "string") {
141
- logger.error(
142
- "[MCP LOG] GetResource (project): Invalid project name param.",
143
- );
144
- throw new Error("Invalid project name parameter.");
145
- }
146
-
147
- try {
148
- logger.info(
149
- `[MCP LOG] GetResource: Getting project '${projectName}'...`,
150
- );
151
- // Get the project instance, but we might not need its metadata directly
152
- await projectStore.getProject(projectName, false);
153
- // Construct the definition object expected by the test
154
- const definition = { name: projectName };
155
- logger.info(
156
- `[MCP LOG] GetResource (project): Returning definition for '${projectName}'.`,
157
- );
158
- // Return the explicit definition structure
159
- return definition;
160
- } catch (error) {
161
- logger.error(
162
- `[MCP LOG] GetResource (project): Error caught for '${projectName}':`,
163
- { error },
164
- );
165
- // Catch expected errors from this specific resource logic
166
- if (error instanceof Error) {
167
- // Use getNotFoundError for the specific project not found case
168
- // or a generic message for the invalid param case.
169
- const errorDetails = getNotFoundError(
170
- error.message.includes("not found")
171
- ? `Project '${projectName}'` // More specific context
172
- : `Invalid project identifier provided for URI ${uri.href}`, // Generic but informative
173
- );
174
- // Re-throw structured error for handleResourceGet to catch
175
- throw new McpGetResourceError(errorDetails);
176
- }
177
- // Re-throw unexpected errors to be caught by handleResourceGet's generic handler
178
- throw error;
179
- }
180
- },
181
- RESOURCE_METADATA.project,
182
- ),
183
- );
184
- }
@@ -1,13 +0,0 @@
1
- import { ProjectNotFoundError } from "../errors";
2
- import { ResourceRepository } from "../storage/DatabaseInterface";
3
-
4
- export async function resolveProjectId(
5
- repository: ResourceRepository,
6
- projectName: string,
7
- ): Promise<string> {
8
- const dbProject = await repository.getProjectByName(projectName);
9
- if (!dbProject) {
10
- throw new ProjectNotFoundError(`Project '${projectName}' not found`);
11
- }
12
- return dbProject.id;
13
- }