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.84 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("hono"),q=require("../compiler-Du1HVm5_.cjs");var b=m=>{const u={...{origin:"*",allowMethods:["GET","HEAD","PUT","POST","DELETE","PATCH"],allowHeaders:[],exposeHeaders:[]},...m},j=(i=>typeof i=="string"?i==="*"?()=>i:n=>i===n?n:null:typeof i=="function"?i:n=>i.includes(n)?n:null)(u.origin),y=(i=>typeof i=="function"?i:Array.isArray(i)?()=>i:()=>[])(u.allowMethods);return async function(n,c){function f(o,r){n.res.headers.set(o,r)}const l=await j(n.req.header("origin")||"",n);if(l&&f("Access-Control-Allow-Origin",l),u.credentials&&f("Access-Control-Allow-Credentials","true"),u.exposeHeaders?.length&&f("Access-Control-Expose-Headers",u.exposeHeaders.join(",")),n.req.method==="OPTIONS"){u.origin!=="*"&&f("Vary","Origin"),u.maxAge!=null&&f("Access-Control-Max-Age",u.maxAge.toString());const o=await y(n.req.header("origin")||"",n);o.length&&f("Access-Control-Allow-Methods",o.join(","));let r=u.allowHeaders;if(!r?.length){const e=n.req.header("Access-Control-Request-Headers");e&&(r=e.split(/\s*,\s*/))}return r?.length&&(f("Access-Control-Allow-Headers",r.join(",")),n.res.headers.append("Vary","Access-Control-Request-Headers")),n.res.headers.delete("Content-Length"),n.res.headers.delete("Content-Type"),new Response(null,{headers:n.res.headers,status:204,statusText:"No Content"})}await c(),u.origin!=="*"&&n.header("Vary","Origin",{append:!0})}};function w(m){const{cubes:h,drizzle:u,schema:j,extractSecurityContext:y,engineType:i,cors:n,basePath:c="/cubejs-api/v1",cache:f}=m;if(!h||h.length===0)throw new Error("At least one cube must be provided in the cubes array");const l=new g.Hono;n&&l.use("/*",b(n));const o=new q.SemanticLayerCompiler({drizzle:u,schema:j,engineType:i,cache:f});return h.forEach(r=>{o.registerCube(r)}),l.post(`${c}/load`,async r=>{try{const e=await r.req.json(),t=e.query||e,a=await y(r),s=o.validateQuery(t);if(!s.isValid)return r.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const d=await o.executeMultiCubeQuery(t,a);return r.json(q.formatCubeResponse(t,d,o))}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 a=await y(r),s=o.validateQuery(t);if(!s.isValid)return r.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const d=await o.executeMultiCubeQuery(t,a);return r.json(q.formatCubeResponse(t,d,o))}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 a=await y(r),s=await q.handleBatchRequest(t,a,o);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=o.getMetadata();return r.json(q.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 y(r),a=o.validateQuery(e);if(!a.isValid)return r.json({error:`Query validation failed: ${a.errors.join(", ")}`},400);const s=e.measures?.[0]||e.dimensions?.[0];if(!s)return r.json({error:"No measures or dimensions specified"},400);const d=s.split(".")[0],p=await o.generateSQL(d,e,t);return r.json(q.formatSqlResponse(e,p))}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),a=await y(r),s=o.validateQuery(t);if(!s.isValid)return r.json({error:`Query validation failed: ${s.errors.join(", ")}`},400);const d=t.measures?.[0]||t.dimensions?.[0];if(!d)return r.json({error:"No measures or dimensions specified"},400);const p=d.split(".")[0],x=await o.generateSQL(p,t,a);return r.json(q.formatSqlResponse(t,x))}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,a=await y(r),s=await q.handleDryRun(t,a,o);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),a=await y(r),s=await q.handleDryRun(t,a,o);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.post(`${c}/explain`,async r=>{try{const e=await r.req.json(),t=e.query||e,a=e.options||{},s=await y(r),d=o.validateQuery(t);if(!d.isValid)return r.json({error:`Query validation failed: ${d.errors.join(", ")}`},400);const p=await o.explainQuery(t,s,a);return r.json(p)}catch(e){return console.error("Explain error:",e),r.json({error:e instanceof Error?e.message:"Explain query failed"},500)}}),l}function C(m,h){const u=w(h);return m.route("/",u),m}function Q(m){const h=new g.Hono;return C(h,m)}exports.createCubeApp=Q;exports.createCubeRoutes=w;exports.mountCubeRoutes=C;