UNPKG

drizzle-cube

Version:

Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.

2 lines (1 loc) 5.45 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("hono"),f=require("../compiler-C6JQHGrF.cjs");var x=q=>{const i={...{origin:"*",allowMethods:["GET","HEAD","PUT","POST","DELETE","PATCH"],allowHeaders:[],exposeHeaders:[]},...q},j=(a=>typeof a=="string"?a==="*"?()=>a:o=>a===o?o:null:typeof a=="function"?a:o=>a.includes(o)?o:null)(i.origin),d=(a=>typeof a=="function"?a:Array.isArray(a)?()=>a:()=>[])(i.allowMethods);return async function(o,c){function y(n,r){o.res.headers.set(n,r)}const l=await j(o.req.header("origin")||"",o);if(l&&y("Access-Control-Allow-Origin",l),i.credentials&&y("Access-Control-Allow-Credentials","true"),i.exposeHeaders?.length&&y("Access-Control-Expose-Headers",i.exposeHeaders.join(",")),o.req.method==="OPTIONS"){i.origin!=="*"&&y("Vary","Origin"),i.maxAge!=null&&y("Access-Control-Max-Age",i.maxAge.toString());const n=await d(o.req.header("origin")||"",o);n.length&&y("Access-Control-Allow-Methods",n.join(","));let r=i.allowHeaders;if(!r?.length){const e=o.req.header("Access-Control-Request-Headers");e&&(r=e.split(/\s*,\s*/))}return r?.length&&(y("Access-Control-Allow-Headers",r.join(",")),o.res.headers.append("Vary","Access-Control-Request-Headers")),o.res.headers.delete("Content-Length"),o.res.headers.delete("Content-Type"),new Response(null,{headers:o.res.headers,status:204,statusText:"No Content"})}await c(),i.origin!=="*"&&o.header("Vary","Origin",{append:!0})}};function w(q){const{cubes:m,drizzle:i,schema:j,extractSecurityContext:d,engineType:a,cors:o,basePath:c="/cubejs-api/v1",cache:y}=q;if(!m||m.length===0)throw new Error("At least one cube must be provided in the cubes array");const l=new p.Hono;o&&l.use("/*",x(o));const n=new f.SemanticLayerCompiler({drizzle:i,schema:j,engineType:a,cache:y});return m.forEach(r=>{n.registerCube(r)}),l.post(`${c}/load`,async r=>{try{const e=await r.req.json(),t=e.query||e,u=await d(r),s=n.validateQuery(t);if(!s.isValid)return r.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const h=await n.executeMultiCubeQuery(t,u);return r.json(f.formatCubeResponse(t,h,n))}catch(e){return console.error("Query execution error:",e),r.json({error:e instanceof Error?e.message:"Query execution failed"},500)}}),l.get(`${c}/load`,async r=>{try{const e=r.req.query("query");if(!e)return r.json({error:"Query parameter is required"},400);let t;try{t=JSON.parse(e)}catch{return r.json({error:"Invalid JSON in query parameter"},400)}const u=await d(r),s=n.validateQuery(t);if(!s.isValid)return r.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const h=await n.executeMultiCubeQuery(t,u);return r.json(f.formatCubeResponse(t,h,n))}catch(e){return console.error("Query execution error:",e),r.json({error:e instanceof Error?e.message:"Query execution failed"},500)}}),l.post(`${c}/batch`,async r=>{try{const e=await r.req.json(),{queries:t}=e;if(!t||!Array.isArray(t))return r.json({error:'Request body must contain a "queries" array'},400);if(t.length===0)return r.json({error:"Queries array cannot be empty"},400);const u=await d(r),s=await f.handleBatchRequest(t,u,n);return r.json(s)}catch(e){return console.error("Batch execution error:",e),r.json({error:e instanceof Error?e.message:"Batch execution failed"},500)}}),l.get(`${c}/meta`,r=>{try{const e=n.getMetadata();return r.json(f.formatMetaResponse(e))}catch(e){return console.error("Metadata error:",e),r.json({error:e instanceof Error?e.message:"Failed to fetch metadata"},500)}}),l.post(`${c}/sql`,async r=>{try{const e=await r.req.json(),t=await d(r),u=n.validateQuery(e);if(!u.isValid)return r.json({error:`Query validation failed: ${u.errors.join(", ")}`},400);const s=e.measures?.[0]||e.dimensions?.[0];if(!s)return r.json({error:"No measures or dimensions specified"},400);const h=s.split(".")[0],g=await n.generateSQL(h,e,t);return r.json(f.formatSqlResponse(e,g))}catch(e){return console.error("SQL generation error:",e),r.json({error:e instanceof Error?e.message:"SQL generation failed"},500)}}),l.get(`${c}/sql`,async r=>{try{const e=r.req.query("query");if(!e)return r.json({error:"Query parameter is required"},400);const t=JSON.parse(e),u=await d(r),s=n.validateQuery(t);if(!s.isValid)return r.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const h=t.measures?.[0]||t.dimensions?.[0];if(!h)return r.json({error:"No measures or dimensions specified"},400);const g=h.split(".")[0],b=await n.generateSQL(g,t,u);return r.json(f.formatSqlResponse(t,b))}catch(e){return console.error("SQL generation error:",e),r.json({error:e instanceof Error?e.message:"SQL generation failed"},500)}}),l.post(`${c}/dry-run`,async r=>{try{const e=await r.req.json(),t=e.query||e,u=await d(r),s=await f.handleDryRun(t,u,n);return r.json(s)}catch(e){return console.error("Dry-run error:",e),r.json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1},400)}}),l.get(`${c}/dry-run`,async r=>{try{const e=r.req.query("query");if(!e)return r.json({error:"Query parameter is required",valid:!1},400);const t=JSON.parse(e),u=await d(r),s=await f.handleDryRun(t,u,n);return r.json(s)}catch(e){return console.error("Dry-run error:",e),r.json({error:e instanceof Error?e.message:"Dry-run validation failed",valid:!1},400)}}),l}function C(q,m){const i=w(m);return q.route("/",i),q}function Q(q){const m=new p.Hono;return C(m,q)}exports.createCubeApp=Q;exports.createCubeRoutes=w;exports.mountCubeRoutes=C;